• 使用C语言实现双向链表(带头结点)


    目录

    1.双链表

    2.双链表的相关操作

    (1)数据结构的定义

    (2)初始化和销毁

    (3)判断空和表的长度

    (4)节点的后插操作

    (5)按序查找第i个节点和按值查找节点

    (6)定位删除和按序删除

    (7)打印操作

    (8)主函数

    (9)测试


    1.双链表

    相对于单链表来说就是多一个前驱的指针prior,指向前一个节点(主要是为了方便删除和插入)。

    注:由于之前的实现的单链表总是会遇到一种情况就是,如果要删除当前的节点p的话,那么只能通过一种技巧的方式计算交换值;但是如果是需要进行更加复杂的操作的话,就会比较麻烦,可能还需要辅助的指针r来指向当前节点的前驱,这会给程序写起来和理解起来带来不便,所以为了实现当前节点能够访问前驱节点,那么提出了双链表的概念。

    使用C语言实现单链表(带头结点)

    使用C语言实现单链表(不带头结点)

    2.双链表的相关操作

    (1)数据结构的定义

    1. #include
    2. #include
    3. #define MAXSIZE 10
    4. typedef int ElemType;
    5. typedef struct DNode {
    6. ElemType data;
    7. struct DNode*prior,*next;
    8. }DNode,*DLinkList;
    9. //清单列表
    10. void MenuLinkList(){
    11. printf("-------------1.插入操作-------------\n");
    12. printf("-------------2.定位插入操作---------\n");
    13. printf("-------------3.按序查找操作---------\n");
    14. printf("-------------4.按值查找操作---------\n");
    15. printf("-------------5.定位删除操作---------\n");
    16. printf("-------------6.按值删除元素---------\n");
    17. printf("-------------7.删除整个表元素节点---\n");
    18. printf("-------------8.表的长度-------------\n");
    19. printf("-------------9.打印操作-------------\n");
    20. printf("-------------10.结束操作-------------\n");
    21. }

    (2)初始化和销毁

    1. //初始化操作
    2. void InitDLinkList(DLinkList&L){
    3. L=(DNode*)malloc(sizeof(DNode));
    4. if(L==NULL){
    5. printf("申请空间失败!\n");
    6. return ;
    7. }
    8. L->prior=NULL;
    9. L->next=NULL;
    10. printf("申请空间成功!\n");
    11. }
    12. //销毁表(头节点不销毁)
    13. DNode* DestryDLinkList(DNode*p,DLinkList&L,int flag=9){
    14. //从尾部开始删除节点
    15. DNode*r=p;
    16. while(r!=L){
    17. DNode*s=r;
    18. r=r->prior;
    19. r->next=s->next;
    20. free(s);
    21. }
    22. //如果是结束操作的话,直接将头节点释放
    23. if(flag==10){
    24. free(L);
    25. L=NULL;
    26. }
    27. return r;
    28. }

    这里的销毁操作主要是从最后节点开始进行删除,更加的方便,如果从头结点开始删除的话,需要判断的条件更多,相对麻烦一点,所以采用这种方法。读者自己可以实现从前往后的删除操作。

    (3)判断空和表的长度

    1. //判空
    2. bool Empty(DLinkList L){
    3. if(L->next==NULL){
    4. return true;
    5. }else{
    6. return false;
    7. }
    8. }
    9. //表的长度
    10. int DLinkListLength(DLinkList L){
    11. int len=0;
    12. DNode*p=L->next;
    13. while(p!=NULL){
    14. len++;
    15. p=p->next;
    16. }
    17. return len;
    18. }

    (4)节点的后插操作

    1. //节点的插入操作(后插)
    2. DNode* InsertDLinkList(DNode*p,ElemType e){
    3. if(p==NULL){
    4. printf("插入的节点不合法!\n");
    5. return NULL;
    6. }
    7. DNode*s=(DNode*)malloc(sizeof(DNode));
    8. s->data=e;
    9. s->next=p->next;
    10. p->next=s;
    11. s->prior=p;
    12. printf("插入节点成功!\n");
    13. return s;
    14. }
    15. //在第i个位置插入节点
    16. void InsertIDLinkList(DLinkList&L,int i,ElemType e){
    17. DNode*p=FindDNode(L,i);
    18. //如果是插入到尾节点
    19. if(p->next==NULL){
    20. InsertDLinkList(p,e);
    21. return ;
    22. }
    23. //插入到中间的节点
    24. if(p!=NULL){
    25. DNode*s=(DNode*)malloc(sizeof(DNode));
    26. s->data=e;
    27. s->next=p->next;
    28. p->next->prior=s;
    29. p->next=s;
    30. s->prior=p;
    31. printf("插入节点成功!\n");
    32. return ;
    33. }
    34. }

    (5)按序查找第i个节点和按值查找节点

    1. //查找第i个位序的节点
    2. DNode*FindDNode(DLinkList L,int i){
    3. if(L==NULL){
    4. printf("表为空!\n");
    5. return NULL;
    6. }
    7. if(i<0||i>DLinkListLength(L)){
    8. printf("查找的位置不正确!\n");
    9. return NULL;
    10. }
    11. int j=1;
    12. DNode*p=L->next;
    13. while(p!=NULL&&j
    14. p=p->next;
    15. j++;
    16. }
    17. return p;
    18. }
    19. //按值查找操作
    20. DNode*FindDElem(DLinkList L,ElemType e){
    21. if(L==NULL){
    22. printf("表为空!\n");
    23. return NULL;
    24. }
    25. DNode*p=L->next;
    26. while(p->data!=e){
    27. p=p->next;
    28. }
    29. return p;
    30. }

    (6)定位删除和按序删除

    1. //定位删除节点
    2. void DeleteDLNode(DLinkList&L,int i,ElemType&e){
    3. DNode*p=FindDNode(L,i);
    4. e=p->data;
    5. //如果是尾节点直接删除
    6. if(p->next==NULL){
    7. p->prior->next=p->next;
    8. free(p);
    9. return ;
    10. }
    11. if(p!=NULL){
    12. DNode*s=p;
    13. p->prior->next=s->next;
    14. p->next->prior=s->prior;
    15. free(s);
    16. return ;
    17. }
    18. }
    19. //按值删除
    20. void DeleteDElem(DLinkList&L,ElemType e){
    21. DNode*p=FindDElem(L,e);
    22. //如果是尾节点直接删除
    23. if(p->next==NULL){
    24. p->prior->next=p->next;
    25. free(p);
    26. return ;
    27. }
    28. if(p!=NULL){
    29. DNode*s=p;
    30. p->prior->next=s->next;
    31. p->next->prior=s->prior;
    32. free(s);
    33. return ;
    34. }
    35. }

    (7)打印操作

    1. //打印
    2. void PrintDLinkList(DLinkList L){
    3. DNode*p=L->next;
    4. while(p!=NULL){
    5. printf("%d\t",p->data);
    6. p=p->next;
    7. }
    8. printf("\n");
    9. }

    (8)主函数

    1. int main(){
    2. DLinkList L;
    3. InitDLinkList(L);
    4. //对顺序表进行插入操作
    5. ElemType x;
    6. int flag=-1;
    7. DNode*p=L;
    8. //各种操作
    9. while(1) {
    10. int i=0;
    11. ElemType e=0;
    12. MenuLinkList();
    13. printf("请输入操作: ");
    14. scanf("%d",&flag);
    15. int len=0;
    16. DNode*s;
    17. switch(flag){
    18. case 1:
    19. printf("请输入元素(-1_end): ");
    20. scanf("%d",&x);
    21. while(x!=-1) {
    22. p=InsertDLinkList(p,x);
    23. printf("请输入元素(-1_end): ");
    24. scanf("%d",&x);
    25. }
    26. break;
    27. case 2:
    28. printf("请输入元素插入位置: \n");
    29. scanf("%d",&i);
    30. printf("请输入元素: ");
    31. scanf("%d",&x);
    32. InsertIDLinkList(L,i,x);
    33. break;
    34. case 3:
    35. printf("请输入查找元素位置: ");
    36. scanf("%d",&i);
    37. s=FindDNode(L,i);
    38. if(s!=NULL){
    39. printf("查找的元素为 = %d\n",s->data);
    40. }
    41. break;
    42. case 4:
    43. printf("请输入要查找的值: ");
    44. scanf("%d",&x);
    45. s=FindDElem(L,x);
    46. if(s!=NULL){
    47. printf("查找的元素存在!\n");
    48. }else{
    49. printf("查找的元素不存在!\n");
    50. }
    51. break;
    52. case 5:
    53. printf("请输入删除的定位位置: ");
    54. scanf("%d",&i);
    55. DeleteDLNode(L,i,e);
    56. printf("删除的元素为 = %d\n",e);
    57. break;
    58. case 6:
    59. printf("请输入要删除的元素: ");
    60. scanf("%d",&e);
    61. DeleteDElem(L,e);
    62. break;
    63. case 7:
    64. p=DestryDLinkList(p,L);
    65. printf("删除成功!\n");
    66. break;
    67. case 8:
    68. len=DLinkListLength(L);
    69. printf("表的长度 = %d\n",len);
    70. break;
    71. case 9:
    72. PrintDLinkList(L);
    73. break;
    74. default:
    75. DestryDLinkList(p,L,flag);
    76. printf("结束操作\n");
    77. }
    78. if(flag==10){
    79. break;
    80. }
    81. }
    82. return 0;
    83. }

    (9)测试

     

     

  • 相关阅读:
    NSSCTF做题(4)
    SELinux零知识学习八、SELinux策略语言之客体类别和许可(2)
    LeetCode 1465. 切割后面积最大的蛋糕
    【python】pytorch包(第四章)手写数字图像识别
    数据接口工程对接BI可视化大屏(五)数据接口发布
    return语句
    蓝牙耳机哪个品牌最好?双11平价好用的蓝牙耳机推荐
    Sharding-Jdbc分库分表集成Mybatis-Plus+多数据源管理
    Easy Touch 5 简单使用
    【版本控制】Github和Gitlab同时使用ssh
  • 原文地址:https://blog.csdn.net/Keep_Trying_Go/article/details/126233816