• 使用C语言实现循环单链表(带头节点)


    目录

    1.循环单链表

    2.循环单链表相关操作

    (1)单链表的定义

    (2)初始化和销毁操作

    (3)判空,判满和表的长度

    (4)插入操作

    (5)按序插入到第i个位置

    (6)按值查找节点

    (7)按值删除和按序删除第i个节点

    (8)打印和主函数

    (9)测试


    1.循环单链表

     

     特点:表中最后一个节点的指针域指向头结点,整个链表形成一个环。

    使用C语言实现带头节点的单链表

    使用C语言实现不带头节点的单链表

    2.循环单链表相关操作

    (1)单链表的定义

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

    (2)初始化和销毁操作

    1. //初始化不带头节点
    2. void InitList(LinkList&L){
    3. L=(LNode*)malloc(sizeof(LNode));
    4. if(L==NULL){
    5. printf("内存分配失败!\n");
    6. return ;
    7. }
    8. //注意这个地方,不再是指向NULL,而是头结点本身
    9. L->next=L;
    10. printf("空间申请成功!\n");
    11. }
    12. //销毁操作
    13. void DestryList(LinkList&L){
    14. LNode*p=L->next;
    15. while(p->next!=L){
    16. LNode*s=p->next;
    17. p->next=s->next;
    18. free(s);
    19. }
    20. //最后一个节点特殊处理
    21. LNode*s=p->next;
    22. p->next=L->next;
    23. L=p;
    24. free(s);
    25. }

    销毁的主要思路是:首选释放前n-1个节点的空间,随后再将最后一个节点做单独的处理:如图

     

    (3)判空,判满和表的长度

    1. //判断链表是否为空
    2. bool Empty(LinkList L){
    3. if(L->next==L){
    4. return true;
    5. }else{
    6. return false;
    7. }
    8. }
    9. //判断节点p是否为尾节点
    10. bool isTail(LinkList L,LNode*p){
    11. if(p->next==L){
    12. return true;
    13. }else{
    14. return false;
    15. }
    16. }
    17. //表的长度
    18. int LinkListLength(LinkList L){
    19. int len=0;
    20. LNode*p=L->next;
    21. while(p->next!=L){
    22. p=p->next;
    23. len++;
    24. }
    25. return len;
    26. }

    (4)插入操作

     

    1. //循环链表的插入操作
    2. //这里从后插,并且让L指向尾部,便于插入和删除
    3. void InsertLNode(LinkList&L,ElemType e){
    4. LNode*s=(LNode*)malloc(sizeof(LNode));
    5. s->data=e;
    6. s->next=L->next;
    7. L->next=s;
    8. L=s;
    9. printf("插入节点成功!\n");
    10. }

    (5)按序插入到第i个位置

    1. //查找第i个节点
    2. LNode*FindILNode(LinkList L,int i){
    3. if(i>LinkListLength(L)){
    4. printf("没有相关的位置可插入!\n");
    5. return NULL;
    6. }
    7. int j=1;
    8. LNode*p=L->next;
    9. //这里使用j
    10. while(p!=L&&j
    11. p=p->next;
    12. j++;
    13. }
    14. if(p==L){
    15. printf("插入的位置不合法!\n");
    16. return NULL;
    17. }
    18. return p;
    19. }
    20. //在第i个位置插入节点
    21. void InsertILNode(LinkList&L,int i,ElemType e){
    22. LNode*p=FindILNode(L,i);
    23. LNode*s=(LNode*)malloc(sizeof(LNode));
    24. s->data=e;
    25. s->next=p->next;
    26. p->next=s;
    27. printf("插入节点成功!\n");
    28. }

    (6)按值查找节点

    1. //按值查找操作
    2. bool FindElem(LinkList L,ElemType&e){
    3. LNode*p=L->next;
    4. while(p->next!=NULL){
    5. if(p->next->data==e){
    6. return true;
    7. }
    8. p=p->next;
    9. }
    10. return false;
    11. }

    (7)按值删除和按序删除第i个节点

    1. //定位删除节点
    2. void DeleteILNode(LinkList&L,int i,ElemType&e){
    3. LNode*p=FindILNode(L,i);
    4. LNode*s=p->next;
    5. e=s->data;
    6. p->next=s->next;
    7. free(s);
    8. }
    9. //按值删除节点(删除所有值相同的节点
    10. void DeleteElemLNode(LinkList&L,ElemType e){
    11. LNode*p=L->next;
    12. //如果只有一个节点则需要进行特殊的处理
    13. if(LinkListLength(L)==1&&p->next->data==e){
    14. LNode*s=p->next;
    15. p->next=L->next;
    16. L=p;
    17. free(s);
    18. return ;
    19. }
    20. while(p!=L){
    21. LNode*s=p->next;
    22. //如果是尾节点的话需要进行特殊的处理,因为L也是指向尾节点的
    23. if(s==L&&s->data==e){
    24. while(L!=p){
    25. L=L->next;
    26. }
    27. L->next=s->next;
    28. free(s);
    29. return ;
    30. }
    31. if(s->data==e){
    32. p->next=s->next;
    33. free(s);
    34. }else{
    35. p=p->next;
    36. }
    37. }
    38. }

    (8)打印和主函数

    1. //打印操作
    2. void DisplayList(LinkList L){
    3. LNode*p=L->next;
    4. while(p!=L){
    5. p=p->next;
    6. printf("%d\t",p->data);
    7. }
    8. printf("\n");
    9. }
    10. int main(){
    11. LinkList L;
    12. InitList(L);
    13. //对顺序表进行插入操作
    14. ElemType x;
    15. int flag=-1;
    16. LNode*p=L;
    17. //各种操作
    18. while(1) {
    19. int i=0;
    20. ElemType e=0;
    21. MenuLinkList();
    22. printf("请输入操作: ");
    23. scanf("%d",&flag);
    24. int len=0;
    25. bool exist=false;
    26. LNode*s;
    27. switch(flag){
    28. case 1:
    29. printf("请输入元素(-1_end): ");
    30. scanf("%d",&x);
    31. while(x!=-1) {
    32. InsertLNode(L,x);
    33. printf("请输入元素(-1_end): ");
    34. scanf("%d",&x);
    35. }
    36. break;
    37. case 2:
    38. printf("请输入元素插入位置: \n");
    39. scanf("%d",&i);
    40. printf("请输入元素: ");
    41. scanf("%d",&x);
    42. InsertILNode(L,i,x);
    43. break;
    44. case 3:
    45. printf("请输入查找元素位置: ");
    46. scanf("%d",&i);
    47. s=FindILNode(L,i);
    48. printf("查找的元素为 = %d\n",s->next->data);
    49. break;
    50. case 4:
    51. printf("请输入要查找的值: ");
    52. scanf("%d",&x);
    53. exist=FindElem(L,x);
    54. if(exist){
    55. printf("查找的元素存在!\n");
    56. }else{
    57. printf("查找的元素不存在!\n");
    58. }
    59. break;
    60. case 5:
    61. printf("请输入删除的定位位置: ");
    62. scanf("%d",&i);
    63. DeleteILNode(L,i,e);
    64. printf("删除的元素为 = %d\n",e);
    65. break;
    66. case 6:
    67. printf("请输入要删除的元素: ");
    68. scanf("%d",&e);
    69. DeleteElemLNode(L,e);
    70. printf("删除节点成功!\n");
    71. break;
    72. case 7:
    73. DestryList(L);
    74. printf("删除成功!\n");
    75. break;
    76. case 8:
    77. len=LinkListLength(L);
    78. printf("表的长度 = %d\n",len);
    79. break;
    80. case 9:
    81. DisplayList(L);
    82. break;
    83. default:
    84. DestryList(L);
    85. printf("结束操作\n");
    86. }
    87. if(flag==10){
    88. break;
    89. }
    90. }
    91. return 0;
    92. }

    (9)测试

     

     

     

     

     

  • 相关阅读:
    人工智能在制造业的工程化应用实践----工业软件讲坛第九次讲座
    2022 年牛客多校第四场补题记录
    省市区三级联动
    闭包学习记录-iOS开发
    唯品会三年,我只做了5件事,如今跳槽天猫拿下offer(Java岗)
    Springboot从数据库读取配置文件
    CentOS 7迁移Tencent OS 2.4 tk
    联盟 | SHOPYY 与 HelpLook 达成战略合作,携手助力独立站卖家快速增长!
    VirtualLab专题实验教程-3.二维分束超表面光栅
    来聊一聊std::function和lambda性能效率问题
  • 原文地址:https://blog.csdn.net/Keep_Trying_Go/article/details/126217221