双链表的C语言操作

今天是双链表建立以及结点的插入和删除

话不多说,直接上代码

 打印链表定义和之前一样

void PrintList(DLinkList L) {
    L = L->next;
    while (L != nullptr) {            //for循环遍历数组类型  while循环遍历其他类型
        printf("%3d", L->data);
        L = L->next;
    }
    printf("\n");
}

首先是结点定义,注意双链表的结点包含前后指针

typedef int ElemType ;
typedef struct DNode{
    ElemType data ;
    DNode *prior ,*next ;     //定义前驱和后继指针
}DNode,*DLinkList ;

 初始化双链表代码如下:

void InitDNode(DLinkList &L){       //初始化链表 建立头指针   DLinkList 和 DNode* 等价
    L=(DNode *)malloc(sizeof(DNode));
    L->prior= nullptr;
    L->next= nullptr;
}

之后是头插法和尾插法建立链表

void list_head_insert(DNode *&L){          //头插法插入新元素
    ElemType x ;
    DNode *s ;
    L=(DNode *)malloc(sizeof(DNode)) ;     //LNode*是结构体指针 和 LinkList完全等价
    L->prior= nullptr;
    L->next= nullptr ;
    scanf("%d" ,&x) ;
    while (x!=9999){
        s=(DLinkList)malloc(sizeof(DNode)) ;     //LNode*是结构体指针 和 LinkList完全等价
        s->data=x ;
        s->next=L->next ;
        if(L->next!= nullptr){             //插入第一个元素时,后结点的前指针不用返回
            L->next->prior=s ;
        }
        s->prior=L ;
        L->next=s ;
        scanf("%d" ,&x) ;
    }
}
void list_tail_insert(DNode *&L){          //尾插法插入新元素
    ElemType x ;
    L=(DNode *)malloc(sizeof(DNode)) ;     //LNode*是结构体指针 和 LinkList完全等价
    L->prior= nullptr;
    L->next= nullptr ;
    DNode *s,*r=L ;                    //指针r 必须在确定 L 前后指针之后定义,确保r的前后指针为空
    scanf("%d" ,&x) ;
    while (x!=9999){
        s=(DNode *)malloc(sizeof(DNode)) ;      //内部无须再次声明 s结点
        s->data=x ;
        r->next=s ;
        s->prior=r ;
        r=s ;
        scanf("%d" ,&x) ;
    }
    r->next= nullptr ;                           //最终最后一个结点 后继 指向空
}

然后是删除结点定义:

void DNodeDelete(DLinkList &L ,ElemType x){
    int len=0 ;
    DNode *p=L->next ,*q=L ;
    while (p!= nullptr && p->data!=x){        //用while或者for循环遍历元素,if只能执行一次
        q=p ;
        p=p->next ;
        len++ ;//计数器原理
        }
    if(p!= nullptr && p->data==x){            //该if在循环外,否则找到对应元素后仍无法删除,执行while
        q->next=p->next ;
        if(p->next!= nullptr){
            p->next->prior=q ;
        }
        free(p) ;
        printf("该值在第%d位\n",len+1) ;   //数组下标是len 所以位置应该是len+1
    }else if(p== nullptr){
        printf("链表没有该元素\n") ;
    }
}

 总体代码实现如下:

#include <stdio.h>
#include <stdlib.h>          //malloc申请的头文件


typedef int ElemType ;
typedef struct DNode{
    ElemType data ;
    DNode *prior ,*next ;     //定义前驱和后继指针
}DNode,*DLinkList ;

void InitDNode(DLinkList &L){       //初始化链表 建立头指针   DLinkList 和 DNode* 等价
    L=(DNode *)malloc(sizeof(DNode));
    L->prior= nullptr;
    L->next= nullptr;
}

void list_head_insert(DNode *&L){          //头插法插入新元素
    ElemType x ;
    DNode *s ;
    L=(DNode *)malloc(sizeof(DNode)) ;     //LNode*是结构体指针 和 LinkList完全等价
    L->prior= nullptr;
    L->next= nullptr ;
    scanf("%d" ,&x) ;
    while (x!=9999){
        s=(DLinkList)malloc(sizeof(DNode)) ;     //LNode*是结构体指针 和 LinkList完全等价
        s->data=x ;
        s->next=L->next ;
        if(L->next!= nullptr){             //插入第一个元素时,后结点的前指针不用返回
            L->next->prior=s ;
        }
        s->prior=L ;
        L->next=s ;
        scanf("%d" ,&x) ;
    }
}

void list_tail_insert(DNode *&L){          //尾插法插入新元素
    ElemType x ;
    L=(DNode *)malloc(sizeof(DNode)) ;     //LNode*是结构体指针 和 LinkList完全等价
    L->prior= nullptr;
    L->next= nullptr ;
    DNode *s,*r=L ;                    //指针r 必须在确定 L 前后指针之后定义,确保r的前后指针为空
    scanf("%d" ,&x) ;
    while (x!=9999){
        s=(DNode *)malloc(sizeof(DNode)) ;      //内部无须再次声明 s结点
        s->data=x ;
        r->next=s ;
        s->prior=r ;
        r=s ;
        scanf("%d" ,&x) ;
    }
    r->next= nullptr ;                           //最终最后一个结点 后继 指向空
}

void DNodeDelete(DLinkList &L ,ElemType x){
    int len=0 ;
    DNode *p=L->next ,*q=L ;
    while (p!= nullptr && p->data!=x){        //用while或者for循环遍历元素,if只能执行一次
        q=p ;
        p=p->next ;
        len++ ;//计数器原理
        }
    if(p!= nullptr && p->data==x){            //该if在循环外,否则找到对应元素后仍无法删除,执行while
        q->next=p->next ;
        if(p->next!= nullptr){
            p->next->prior=q ;
        }
        free(p) ;
        printf("该值在第%d位\n",len+1) ;   //数组下标是len 所以位置应该是len+1
    }else if(p== nullptr){
        printf("链表没有该元素\n") ;
    }
}

void PrintList(DLinkList L) {
    L = L->next;
    while (L != nullptr) {            //for循环遍历数组类型  while循环遍历其他类型
        printf("%3d", L->data);
        L = L->next;
    }
    printf("\n");
}


int main() {                     //双链表插入建立与删除
    DLinkList (L) ;
    printf("********************************************************************\n") ;
    InitDNode(L) ;
    list_head_insert(L) ;
    PrintList(L) ;
    printf("********************************************************************\n") ;
    DNodeDelete(L,3) ;
    PrintList(L) ;
    printf("********************************************************************\n") ;
    list_tail_insert(L);
    PrintList(L) ;
    printf("********************************************************************\n") ;
    return 0;
}

若要对 1 2 3 4 9999和 5 6 7 8 9999操作(9999为结束标志)则会输出如下结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值