• 使用C语言实现单链表的功能(带头节点)


    目录

    1.单链表定义

    2. 单链表特点

    3.顺序表和单链表的对比

    4.单链表的定义

    5.单链表的相关操作

    (1)初始化(申请头节点)

    (2)销毁单链表

    (3)按序查找第i个节点和按值查找节点的存在性

    (4)第i位置插入节点

    (5)指定节点的后插操作和前插操作

    (6)删除指定节点,删除指定值的节点,按序删除第i个节点

    (7)求表长和打印

    (8)主函数

    (9)测试


    1.单链表定义

    每个节点除了存放数据元素外,还要存储指向下一个节点的指针。

    2. 单链表特点

    (1)链式存储结构:不要求逻辑上相邻的元素在物理位置上也相邻。

    (2)包含两个域:数据域和指针域,其中数据域用来存储数据元素信息,指针域用来存储直接后继存储位置。

    (3)头指针:整个链表的存取必须从头指针位置开始,头指针指示链表中的第一个节点的存储位置。

    (4)尾指针:最后一个数据元素没有直接后继,因此线性链表中最后一个节点的指针为“空”(NULL)。

    (5)头节点:头节点的数据域可以不用存储任何信息,也可存储如线性表的长度子类的附加信息,头节点的指针域指向第一个节点的指针。但是有了头节点对于后面的插入,删除等操作非常有帮助。

    3.顺序表和单链表的对比

       顺序表:

              优点:可以随机的存取,存储密度高;

              缺点:要求大片连续的存储空间;

       单链表:

               优点:不要去大片连续的空间,改变容量方便;

               缺点:不能进行随机的存取,需要耗费一点时间才能访问到,如果是第一个节点,O(1),如果是最后一个节点O(n).

    使用C语言实现动态顺序表

    使用C语言实现静态顺序表

    4.单链表的定义

    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. }

    5.单链表的相关操作

    (1)初始化(申请头节点)

    1. //初始化不带头节点
    2. void InitList(LinkList&L){
    3. L=(LNode*)malloc(sizeof(LNode));
    4. if(L==NULL){
    5. printf("内存分配失败!\n");
    6. return ;
    7. }
    8. L->next=NULL;
    9. printf("空间申请成功!\n");
    10. }

    (2)销毁单链表

    1. //销毁链表
    2. void DestryLinkList(LinkList&L,int flag=1){
    3. //这里不删除头节点
    4. LNode*p=L;
    5. while(p->next!=NULL){
    6. LNode*s=p->next;
    7. p->next=s->next;
    8. free(s);
    9. }
    10. //当flag==9表示结束操作,则删除整个表
    11. if(flag==10){
    12. free(p);
    13. }
    14. }

    (3)按序查找第i个节点和按值查找节点的存在性

    1. //获取单链表的第i个节点
    2. LNode*GetElem(LinkList L,int i){
    3. int j=1;
    4. LNode*p=L->next;
    5. if(i<0)return NULL;
    6. if(i==0)return L->next;
    7. while(p!=NULL&&j
    8. p=p->next;
    9. j++;
    10. }
    11. return p;
    12. }
    13. //按值查找节点是否存在
    14. LNode*FindElem(LinkList L,ElemType e){
    15. LNode*p=L->next;
    16. while(p!=NULL&&p->data!=e){
    17. p=p->next;
    18. }
    19. return p;
    20. }

    (4)第i位置插入节点

    1. //按位序查找第i个节点
    2. LNode*FindLNode(LinkList L,int i){
    3. if(i<1){
    4. printf("不符合插入节点位置!\n");
    5. return NULL;
    6. }
    7. LNode*p=L;
    8. int j=0;
    9. while(p!=NULL&&j-1){
    10. p=p->next;
    11. j++;
    12. }
    13. if(p==NULL){
    14. printf("不符合插入节点位置!\n");
    15. return NULL;
    16. }
    17. return p;
    18. }
    19. //按位序插入节点操作
    20. void ListInsert(LinkList L,int i,ElemType e){
    21. LNode*p=FindLNode(L,i);
    22. LNode*s=(LNode*)malloc(sizeof(LNode));
    23. s->data=e;
    24. s->next=p->next;
    25. p->next=s;
    26. printf("插入节点成功!\n");
    27. }

    (5)指定节点的后插操作和前插操作

     

    1. //指定节点的后插操作
    2. LNode* InsertNextNode(LNode*p,ElemType e){
    3. if(p==NULL){
    4. printf("插入位置不合法!\n");
    5. return NULL;
    6. }
    7. LNode*s=(LNode*)malloc(sizeof(LNode));
    8. if(s==NULL){
    9. printf("内存分配失败!\n");
    10. return NULL;
    11. }
    12. s->data=e;
    13. s->next=p->next;
    14. p->next=s;
    15. printf("插入节点成功!\n");
    16. return s;
    17. }
    18. //指定节点前的插入操作
    19. void InsertPriorLNode(LNode*p,ElemType e){
    20. if(p==NULL){
    21. printf("插入位置不合法!\n");
    22. return ;
    23. }
    24. LNode*s=(LNode*)malloc(sizeof(LNode));
    25. ElemType temp=p->data;
    26. s->data=temp;
    27. p->data=e;
    28. s->next=p->next;
    29. p->next=s;
    30. printf("插入节点成功!\n");
    31. }

    (6)删除指定节点,删除指定值的节点,按序删除第i个节点

     

    1. //删除指定节点
    2. void DeleteElemLNode(LNode*p){
    3. if(p==NULL){
    4. printf("删除不合法!\n");
    5. return ;
    6. }
    7. LNode*q=p->next;
    8. p->data=q->data;
    9. p->next=q->next;
    10. free(q);
    11. }
    12. //删除指定值节点(删除所有这样的值)
    13. void DeleteLNode(LinkList&L,ElemType e){
    14. if(L->next==NULL){
    15. printf("表为空!\n");
    16. return ;
    17. }
    18. LNode*p=L->next;
    19. LNode*s,*q;
    20. while(p!=NULL){
    21. LNode*temp;
    22. temp=p;
    23. if(p->data==e&&p->next!=NULL){
    24. DeleteElemLNode(temp);
    25. }else{
    26. //针对删除尾节点
    27. q=p;
    28. s->next=p->next;
    29. free(q);
    30. }
    31. //s用来记录p的前一个节点
    32. s=p;
    33. //如果存在连续的几个值和e相等,则不进行p=p->next
    34. if(p->data!=e){
    35. p=p->next;
    36. }
    37. }
    38. printf("删除指定值节点成功!\n");
    39. }
    40. //按序删除第i个节点
    41. void DeleteOrder(LinkList&L,int i,ElemType&e){
    42. if(L->next==NULL){
    43. printf("表为空!\n");
    44. return ;
    45. }
    46. LNode*p=L->next;
    47. int j=1;
    48. while(p!=NULL&&j1){
    49. p=p->next;
    50. j++;
    51. }
    52. if(p==NULL){
    53. printf("删除位置不合法!\n");
    54. return ;
    55. }
    56. LNode*s=p->next;
    57. e=s->data;
    58. p->next=s->next;
    59. free(s);
    60. printf("删除节点成功!\n");
    61. }

    (7)求表长和打印

    1. //表的长度
    2. int LinkListLength(LinkList L){
    3. int len=0;
    4. LNode*p=L;
    5. while(p->next!=NULL){
    6. len++;
    7. p=p->next;
    8. }
    9. return len;
    10. }
    11. //打印链表的节点
    12. void PrintLinkList(LinkList L){
    13. LNode*p=L->next;
    14. while(p!=NULL){
    15. printf("%d\t",p->data);
    16. p=p->next;
    17. }
    18. printf("\n");
    19. }

    (8)主函数

    1. int main(){
    2. LinkList L;
    3. InitList(L);
    4. //对顺序表进行插入操作
    5. ElemType x;
    6. int flag=-1;
    7. LNode*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. LNode*s;
    17. switch(flag){
    18. case 1:
    19. printf("请输入元素(-1_end): ");
    20. scanf("%d",&x);
    21. while(x!=-1) {
    22. p=InsertNextNode(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. ListInsert(L,i,x);
    33. break;
    34. case 3:
    35. printf("请输入查找元素位置: ");
    36. scanf("%d",&i);
    37. s=GetElem(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=FindElem(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. DeleteOrder(L,i,e);
    56. printf("删除的元素为 = %d\n",e);
    57. break;
    58. case 6:
    59. printf("请输入要删除的元素: ");
    60. scanf("%d",&e);
    61. DeleteLNode(L,e);
    62. break;
    63. case 7:
    64. DestryLinkList(L);
    65. printf("删除成功!\n");
    66. break;
    67. case 8:
    68. len=LinkListLength(L);
    69. printf("表的长度 = %d\n",len);
    70. break;
    71. case 9:
    72. PrintLinkList(L);
    73. break;
    74. default:
    75. DestryLinkList(L,flag);
    76. printf("结束操作\n");
    77. }
    78. if(flag==10){
    79. break;
    80. }
    81. }
    82. return 0;
    83. }

    (9)测试

     

     

     

     

     

     

  • 相关阅读:
    前端必备工具
    Java常规题技术分享
    一个基于.Net Core开发的适合外贸商城系统
    Elasticsearch小bug记录:term: XXX was completely eliminated by analyzer
    vue中 process.env 对象为空对象问题
    人大金仓分析型数据库外部表(二)
    Java常用功能
    Open-TeleVision——通过VR沉浸式感受人形机器人视野:兼备远程控制和深度感知能力
    AI大预言模型——ChatGPT与AI绘图及论文高效写作
    Linux下编译MySQL++及简单使用
  • 原文地址:https://blog.csdn.net/Keep_Trying_Go/article/details/126202360