数据结构与算法学习(二)——双链表

本文详细介绍了双链表的基本概念,包括其结构定义、初始化、显示、查找、插入及删除等核心操作的具体实现过程,适合初学者理解双链表的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

双链表的结点包括3个域,一个是存放数据信息的info域,另外两个是指针域,

双链表的结构定义如下

typedef struct dlink_node{
    datatype info;
    struct dlink_node *llink,*rlink;
}dnode;

双链表中第一个结点没有前驱,它的llink域为NULL;最后一个结点没有后继它的rlink域为NULL;结点中的rlink域作用和单链表结点的next域一样,因此双链表的一些基本操作的实现并不复杂,

  • 建立一个空的双链表
dnode *init(){
    return NULL;
}
  • 输出双链表中的各个结点的值
void display(dnode *head){
    dnode *p;
    printf("\n");
    p = head;
    if(!p){
        printf("\n 双链表是空的!");
    }else{
        while(p){
            printf("%5d",p->info);
            p = p->rlink;
        }
    }
}
  • 查找双链表的第i个结点的值
dnode *find(dnode *head,int i){
    dnode *p = head;
    int j=1;
    if(i < 1){
        printf("\n 第%d 个结点不存在!\n",i);
        return NULL;
    }
    while(p && i!=j){   /*没有找完整个表并且没有找到*/
        p = p->rlink;
        j++;           /*继续沿着右指针向后查找,计数器加1 */
    }
    if(!p){
        printf("\n第%d 个结点不存在!\n");
        return NULL;
    }
    return p;
}
  • 双链表的插入操作

对于双链表的插入操作,如果要在双链表中q所指向的结点后插入一个新的结点p,其中要涉及的结点有q指向的结点、p指向的结点以及q的后继结点(q->rlink 指向的结点),要设置或修改的只有4个指针,具体要做的设置为:p的rlink的设置为q的后继结点(q->rlink);p的llink的设置为q;q的后继结点的前驱为(q->rlink->llink)修改为p;q的后继结点(q->rlink)修改为p。对于特殊情形,双链表同单链表一样需要做特殊处理。

dnode *insert(dnode *head,datatype x,int i){
    dnode *p,*q;
    p = (dnode *)malloc(sizeof(dnode));
    p->info = x;
    if(i == 0){
        p->llink = NULL;       /*新插入的结点没有前驱*/
        p->rlink = head;       /*新插入的结点的后继是原来双链表中的第一个结点*/
        if(!head){
            head = p;
        }
        else{
            head->llink = p;   /*原来双链表中第一个结点的前驱是新插入的结点*/
            head = p;         /*新结点成为双链表的第一个结点*/
        }
        return head;
    }
    q = find(head,i);
    if(!q){
        printf("第%d 个结点不存在,无法进行插入");
        free(q);
        return head;
    }
    if(q->rlink == NULL){       /*在最后一个结点后插入*/
         p->rlink = q->rlink;
         p->llink = q;
         q->rlink = p;
    }else{      /*一般情况下的插入(中间插入)*/
        p-rlink = q-rlink;
        p->llink = q;
        q->rlink->llink = p;
        q->rlink = p;
    }
   return head;
} 

双链表的删除操作

dnode *dele(dnode *head,datatype x){
    dnode *q;
    if(!head){
        printf("\n 双链表为空,无法进行删除\n");
        return head;
    }
    q = head;
    while(q&&q->info!=x)
        q = q->rlink;
    if(!q){
        printf("\n 没有找到值为%d 的结点! 不做删除操作!\n",x);
    }
    if(q == head &&head->rlink){   /*被删除的结点是第一个结点并且表中不止一个结点*/
        head = head->rlink;
        head->llink = NULL;
        free(q);
        return head;
    }
    if(q == head && !head->rlink){  /*被删除的结点是第一个结点并且表中只有一个结点*/
        free(q);
        return NULL;    /*双链表置空*/
    }else{
        if(!q->rlink){     /*被删除的结点是双链表的最后一个结点*/
            q->llink->rlink = NULL;
            free(q);
            return head;
        }else{
            q->llink-rlink = q->rlink;
            q->rlink-llink = q->llink;
            free(q);
            return head;
        }       
     }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值