欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c语言下的双向循环链表

程序员文章站 2024-03-22 11:24:34
...

二.双向循环链表

1.概念

双向循环链表的节点包含一个数据域,两个指针域,一个指针域指向上一个节点,另一个指针域指向下一个节点

这样双向循环链表构成了两个相反方向遍历的圆环

双向循环链表与单链表相比,提高了访问的效率,也付出了多维护一个指针的代价

双向循环链表的插入和删除操作比单向链表复杂,查找和修改和单向链表的算法一样

#include <stdio.h>
#include <stdlib.h>
#include “dlist.h”

//创建空链表
dlist_t create_emptydlist()
{
//构造头节点
dlist_t head = (dlist_t)malloc(sizeof(dlist));
if(head){
head->data = -1;
//头节点的前置和后置都指向自己表示空链表
head->prev = head;
head->next = head;
}

return head;

}

//按值删除,返回删除元素个数
int delete_by_value(dlist_t head,T dt)
{
int i = 0;
dlist_t tmp = NULL;

while(tmp = search_by_value(head,dt)){
    //要删除节点的后一个节点的前置指针指向要删除节点的前一个节点
    tmp->next->prev = tmp->prev;
    //要删除节点的前一个节点的后置指针指向要删除节点的后一个节点
    tmp->prev->next = tmp->next;
    //释放要删除的节点
    free(tmp);
    tmp = NULL;
    i++;
}

return i;

}

//按值查找
dlist_t search_by_value(dlist_t head,T dt)
{
//略过无效头节点
dlist_t tmp = head->next;

while(tmp!=head){
    if(tmp->data==dt)
        return tmp;
    tmp = tmp->next;
}

return NULL;

}

//按位置删除
int delete_by_pos(dlist_t head,int pos)
{
//先查找链表,找到要删除的节点
dlist_t tmp = search_by_pos(head,pos);

//如果找到了就删掉,没找到就返回错误
if(tmp){
    //要删除节点的后一个节点的前置指针指向要删除节点的前一个节点
    tmp->next->prev = tmp->prev;
    //要删除节点的前一个节点的后置指针指向要删除节点的后一个节点
    tmp->prev->next = tmp->next;
    //释放要删除的节点
    free(tmp);
    tmp = NULL;

    return 0;
}

//没有找到节点,返回-1
return -1;

}

//按位置查找
dlist_t search_by_pos(dlist_t head,int pos)
{
int i = 1;
dlist_t tmp = head->next;

//遍历到头节点为止
while(tmp!=head){
    if(i==pos)
        return tmp;
    tmp = tmp->next;
    i++;
}

//回到头节点,谁没有符合编号的节点
return NULL;

}

//从指定位置之后插入节点
dlist_t insert(dlist_t p,T dt)
{
if(!p)
return NULL;

//构造新节点
dlist_t newnode = (dlist_t)malloc(sizeof(dlist));
if(newnode){
    newnode->data = dt;
    //将新节点的前置指向p,后置指向p的下一个节点
    newnode->prev = p;
    newnode->next = p->next;
    //将p的后置指向新节点,将P的下一个节点的前置指向新节点
    p->next->prev = newnode;
    p->next = newnode;
    
}

return newnode;

}

//排序
void sort(dlist_t head)
{
dlist_t tmp = head->next,p = NULL,q = NULL;

//将链表置空
head->next = head;
head->prev = head;

while(tmp!=head){
    //保存原链表中tmp的下一个节点
    q = tmp->next;
    
    //找到tmp插入的位置
    for(p=head->prev;p!=head&&p->data>tmp->data;p=p->prev);
    //将tmp插入到p之后
    tmp->prev = p;
    tmp->next = p->next;
    p->next->prev = tmp;
    p->next = tmp;

    //将tmp指向要插入的下一个节点
    tmp = q;
}

}

//销毁链表
void destory_dlist(dlist_t *phead)
{
dlist_t head = (*phead)->next,p = NULL;

while(head!=*phead){
    p = head;
    head = head->next;
    free(p);
}
free(head);

*phead = NULL;
p = NULL;   

}

//遍历
void travel(dlist_t head)
{
//略过无效头节点
dlist_t tmp = head->next;

while(tmp!=head){
    printf("%d ",tmp->data);
    tmp = tmp->next;
}
printf("\n");

}

双向循环链表(https://download.csdn.net/download/qq_41256954/11079083)