数据结构与算法(双向循环链表)

目录

双向循环链表定义

双向循环链表结构

链表创建

链表遍历

链表插入

链表删除某节点

链表清空

链表查询某节点

链表长度


双向循环链表定义


1、双向链表的定义:在单链表的每个结点里增加一个指向其前驱的指针prior,这样链表中就形成了有两个方向不同的链,称为双向链表。

2、双向循环链表:循环的同时,让头结点的前驱指针指向链表的最后一个结点,让最后一个结点的后继指针指向头结点。

优点:

‌双向访问‌:双向链表允许从任意节点向前或向后遍历,这使得在需要频繁访问链表前后节点的场景中,双向链表比单向链表更加高效。
‌循环特性‌:双向循环链表的头尾相连,形成一个环,这使得在处理需要循环访问所有节点的任务时,双向循环链表比单向循环链表更加方便。
‌空间效率‌:虽然双向链表比单向链表多存储了一个指向直接前驱和后继的指针,但在某些应用场景中,这种设计带来的便利性可能超过其空间复杂度的增加。

缺点:

​‌空间复杂度较高‌:由于每个节点需要存储指向直接前驱和后继的指针,双向链表的空间复杂度比单向链表高。
‌实现复杂‌:虽然双向链表的实现看起来简单,但在某些特定操作上,如插入和删除节点时,需要处理更多的指针操作,这可能会比单向链表更复杂。

设p为链表中某结点的指针, 有对称性:(p->prior)->next = p = (p->next)->prior

双向循环链表结构

#ifndef _DLIST_H_
#define _DLIST_H_

typedef struct node{    

        int data;
        struct node *prior;//前驱指针
        struct node *next;//后驱指针
}dlistnode;

dlistnode * dlist_create();
void dlist_show(dlistnode *H);
void dlist_insert(dlistnode *H,int value,int pos);
void dlist_clear(dlistnode *H);
dlistnode *dlist_get(dlistnode *H,int pos);
int dlist_len(dlistnode *H);
int dlist_delete(dlistnode *H,int pos);
#endif

链表创建

    dlistnode * dlist_create(){
        dlistnode *H,*p,*r ;
    //判断头节点申请成功
        if((H = (dlistnode *)malloc(sizeof(dlistnode)))== NULL){
                printf("malloc error\n");
                return NULL;
               }
        //头结点初始化
        H->next = H;
        H->data = 0;
        H->prior = H;
        r = H;
        //同时根据用户输入在插入后续节点,如果输入-1结束输入
        while(1){    
                int ch; 
                printf("please input:input 'end'exit\n");
                scanf("%d",&ch);
                if(ch ==-1 ){    
                        printf("exit\n");
                        break;
                }
                if((p = (dlistnode *)malloc(sizeof(dlistnode))) == NULL){    
    
                        printf("p malloc eror\n");
                        return NULL;
                }
                //尾结点插入需要注意指针链接顺序,头结点的data作为链表长度使用
                p->data = ch; 
                p->prior = r;
                p->next = H;
                H->prior = p;
                r->next = p;
                r = p;
                H->data++;
        }
        return H;
}

链表遍历

void dlist_show(dlistnode *H){
        if(H == NULL){
                printf("H is NULL\n");
                return;
        }
        dlistnode *p;
        p = H->next;
        while(p!=H){
                printf("%d ",p->data);
                p = p->next;
        }
        puts("");

}

链表插入

void dlist_insert(dlistnode *H,int value,int pos){
        if(H == NULL){
                printf("H is NULL\n");
                return;
        }//pos小于0大于当前长度都是无效插入位置
        if(pos<0||pos>H->data){
                printf("pos is error\n");
                return;
        }
        dlistnode *p,*r=H;
        int i=0;
        if((p=(dlistnode *)malloc(sizeof(dlistnode))) == NULL){

                printf("malloc is NULL\n");
                return;
        }
        //指针移动到插入的前一个位置
        while(i<pos){

                r=r->next;
                i++;
        }//插入后头结点data自加1
        p->data =value;
        p->prior = r;
        p->next = r->next;
        r->next->prior = p;
        r->next = p;
        H->data++;


}

链表删除某节点

int dlist_delete(dlistnode *H,int pos){
        if(H == NULL){
                printf("H is NULL\n");
                return -1;
        }
        if(pos<0||pos>H->data-1||H->data == 0){
                printf("pos get error\n");
                return -1;
        }
        dlistnode *p,*r;
        p = dlist_get(H,pos);
        r = H;
        //找到pos节点前一个节点地址
        while(r->next!=p){

                r=r->next;
        }//删除节点后data自减1
        int a = p->data;
        r->next =r->next->next;
        r->next->prior = r;
        H->data--;
        free(p);
        return a;
}

链表清空

oid dlist_clear(dlistnode *H){
        if(H == NULL || H->data ==0){
                printf("H delete wrong\n");
                return;
        }
        dlistnode *r,*p;
        p = H->next;
        r = H;
        while(p!=H){
                r = p;
                p = p->next;
                free(r);
        }
        H->data = 0;

}

链表查询某节点

dlistnode *dlist_get(dlistnode *H,int pos){
        if(H == NULL){
                printf("H is NULL\n");
                return NULL;
        }//pos小于0等于data或者空结点,pos都是无效输入位置
        if(pos<0||pos>H->data-1||H->data == 0){
                printf("pos get error\n");
                return NULL;
        }
        int i=0;
        dlistnode *p = H;
        while(i<pos){
            p = p->next;
            i++;
        }//查询节点返回p的下一个地址
        return p->next;
}

链表长度

int dlist_len(dlistnode *H){
        if(H == NULL){
                printf("H is NULL\n");
                return -1;
        }

        return H->data;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值