• 单链表的建立(尾插法,头插法,链表的删除,链表的初始化)


    最近学习了数据结构,我们现在来实现单链表的操作实现.

    所谓单链表,就是

    209eddb0fcb54ae7a6937645e191aaf3.png

     

     存储数据的,带有指针的,单向指引的数据结构. 头结点一般是识别链表的,所以不包含数据,如果链表为空,那么头结点指向第一个节点的尾指针也是NULL.

    所以我们现在开始建立一个链表.

    首先我们刚开始只有一个头结点,我们还需要新建结点,所以我们要申请链表结点同类型的空间,引入

    #include
    #include

    接下来,我们既然是存储链表,链表结点包括数据和指针,所以我们要建立链表这个数据类型,就要定义相关的类型

    typedef int ElemType;                


    自定义结点的数据类型

    接着定义单链表结点的指针和数据

    typedef struct LNode
    {
        ElemType data;                //节点的数据区,用类型定义的结构属性
        struct LNode *next;
    }LinkList;

    我们现在,就已经,定义出结点的数据和指针了,接下来的工作就是链表初始化,和链表的插入,输出,清空链表的操作了,我们一  一进行.

    我们看一个代码,首先从其主函数入手,所以我们首先建立相关的函数接口,把他们的操作逻辑上链接起来,这样有助于我们熟悉大致的框架.然后再去着手函数细节,就有助于我们操作.

    主函数的相关操作:

    int main()
    {
        LinkList *L1,*L2;        //定义两个链表                        
        ElemType a[8] = {1,2,3,4,5,6,7,8};        //链表数据数组
        CreatListF(L1,a,8);                        //头插法建立链表,输入的参数分别是建立的链表,输入的数据数组, 建立的数据个数
        printf("头插法的结果");

        DispList(L1);                                //展示链表
        CreatListR(L2,a,8);                        
        printf(尾插法的结果);                        //同理
        DispList(L2);
        DestroyList(L1);                        //清空链表
        DestroyList(L2);
        return 0;
    }


    我们要建立单链表,那就需要有数据插入,所以我们先用链表结点的数据类型来定义一个数据,然后建立链表的时候,就可以从数组来获取数据了(数组也是指针类型,并且不可修改)

    这样我们的大概操作就已经完成了,接下来就是去处理具体的操作了.

    头插法建立链表:

    我们头插法,就是在头结点后面插入数据,然后新结点指针指向后面的数据

    98d3aa9df9c849bf8c7525bac5544772.jpeg

     所以,我们现在就要实现的是,头结点的尾指针指向新结点,新结点的尾指针指向后面的结点.

    开始我们的操作,

    定义成员函数

    void CreateListF(LinkList *&L,ElemType a[],int n){                //传入修改建立的链表, 传入的数据数组,  结点的个数

    //首先定义链表节点

    LinkList *s;

    然后分配头结点空间

    L=(LinkList*)malloc(sizeof(LinkList));

    L->next = NULL;                //初始的时候,头结点尾指针是空的,头结点的数据区无内容起到表示作用


    我们会想到,既然头结点分配空间了,为什么新建街店不分配空间呢?不慌,我们需要插入很多次,所以每次插入就要为新节点分配空间.

        for(i=0;i     {
            s=(LinkList*)malloc(sizeof(LinkList));        //每次插入都为新节点分配空间
            s->data=a[i];                                                //节点的数据区,用自定义类型定义的结构属性
            s->next = L->next;
            L->next=s;

        }

    }

    上面两行不可调换

    我们直接把L->next送给新节点的后继指针,就把新节点和后面一个节点链接起来了

    然后再把新节点的位置送到头结点发后继指针

    这样就把新节点插入了

    不能强行调换的原因是,L->next里面存放的是下一个节点的位置,不能直接覆盖,我们一会儿还要用,所以覆盖指针前要三思,先把要覆盖的指针处理好,再进行操作。

    尾插法建表:

    b5f87967d78b47ea9a8f85ab8b100d13.jpeg

     尾插法就是在单链表的最后一个结点上,添加一个节点,实质就是让最后一个节点的尾指针指向新的节点,

    开始我们的实操:

    定义成员变量传入参数


    void CreateListR(LinkList *&L,ElemType a[], int n){

            //我们要用到的节点是新建节点 ,  一直标志尾结点的节点,这样我们才能定位到尾结点,然后进行变换指针 

           LinkList *s,*r;

            //头结点初始化,先分配空间

           L = (LinkList*)malloc(sizeof(LinkList));

            //头结点置空

            L->next=NULL;

            //然后尾结点

            r=L;                    //r始终指向终端结点,开始时指向头结点
        for (i=0; i     {
            s=(LinkList *)malloc(sizeof(LinkList));  //创建新结点,分配空间
            s->data=a[i];                //新节点赋值
            r->next=s;          //将*s插入*r之后
            r=s;

        }
        r->next=NULL;           //终端结点next域置为NULL

     

    }


    顺序不能调换,我们要在结尾插入结点,依据就是,让链表最后一个结点的尾指针指向这个新的结点, 所以我们就要把新结点的指针赋值给尾结点的尾指针 r->next

    然后,我们再让这个新结点,成为尾结点  r 

    销毁单链表

    void DestroyList(LinkList *&L)  //销毁单链表
    {
        LinkList *p=L,*q=p->next;
        while (q!=NULL)
        {
            free(p);
            p=q;
            q=p->next;
        }
        free(p);    //此时q为NULL,p指向尾结点,释放它
    }
     


    我们想要销毁链表就需要从头开始,因为这是单链表,单向联系

    用一个指针*p表示头指针, 用一个q来存放下一个结点的位置,其实就是存放头结点的尾指针

    直到下一个结点是null, 就说明就剩一个头结点没有覆盖了,我们就可以进行最后的销毁了

    209eddb0fcb54ae7a6937645e191aaf3.png

     

    单链表的输出:

    void DispList(LinkList*L)  //输出单链表

    {

            LinkList *p = L->next;

            while(p!=NULL)

            {

                    printf("%d",p->data);

                    p=p->next;

             }        

            printf("\n");

    }


    输出链表就更简单了,参照链表销毁,我们只是遍历了一下尾指针,接连遍历

    注意:每当我们修改结点,或者覆盖指针的时候,注意一下,那个指针是否对我们后续操作有用,我们是否进行了存储, 再进行下一步操作

    源代码如下:

    1. #include
    2. #include
    3. typedef int ElemType;
    4. typedef struct LNode //定义单链表结点类型
    5. {
    6. ElemType data;
    7. struct LNode *next; //指向后继结点
    8. } LinkList;
    9. void CreateListF(LinkList *&L,ElemType a[],int n);//头插法建立单链表
    10. void CreateListR(LinkList *&L,ElemType a[],int n);//尾插法建立单链表
    11. void DestroyList(LinkList *&L); //销毁单链表
    12. void DispList(LinkList *L); //输出单链表
    13. int main()
    14. {
    15. LinkList *L1, *L2;
    16. ElemType a[8]= {7, 9, 8, 2, 0, 4, 6, 3};
    17. CreateListF(L1, a, 8);
    18. printf("头插法建表结果:");
    19. DispList(L1);
    20. CreateListR(L2, a, 6);
    21. printf("尾插法建表结果:");
    22. DispList(L2);
    23. DestroyList(L1);
    24. DestroyList(L2);
    25. return 0;
    26. }
    27. void CreateListF(LinkList *&L,ElemType a[],int n)//头插法建立单链表
    28. {
    29. LinkList *s;
    30. int i;
    31. L=(LinkList *)malloc(sizeof(LinkList)); //创建头结点
    32. L->next=NULL;
    33. for (i=0; i
    34. {
    35. s=(LinkList *)malloc(sizeof(LinkList));//创建新结点
    36. s->data=a[i];
    37. s->next=L->next; //将*s插在原开始结点之前,头结点之后
    38. L->next=s;
    39. }
    40. }
    41. void CreateListR(LinkList *&L,ElemType a[],int n)//尾插法建立单链表
    42. {
    43. LinkList *s,*r;
    44. int i;
    45. L=(LinkList *)malloc(sizeof(LinkList)); //创建头结点
    46. L->next=NULL;
    47. r=L; //r始终指向终端结点,开始时指向头结点
    48. for (i=0; i
    49. {
    50. s=(LinkList *)malloc(sizeof(LinkList));//创建新结点
    51. s->data=a[i];
    52. r->next=s; //将*s插入*r之后
    53. r=s;
    54. }
    55. r->next=NULL; //终端结点next域置为NULL
    56. }
    57. void DestroyList(LinkList *&L) //销毁单链表
    58. {
    59. LinkList *p=L,*q=p->next;
    60. while (q!=NULL)
    61. {
    62. free(p);
    63. p=q;
    64. q=p->next;
    65. }
    66. free(p); //此时q为NULL,p指向尾结点,释放它
    67. }
    68. void DispList(LinkList *L) //输出单链表
    69. {
    70. LinkList *p=L->next;
    71. while (p!=NULL)
    72. {
    73. printf("%d ",p->data);
    74. p=p->next;
    75. }
    76. printf("\n");
    77. }

     

     

  • 相关阅读:
    网络安全系统性学习路线「全文字详细介绍」
    FreeRTOS操作系统中,断言输出 Error:..\..\FreeRTOS\portable\RVDS\ARM_CM4F\port.c,766 原因
    Redis事务、pub/sub、PipeLine-管道、benchmark性能测试详解
    前端进击笔记第四节 如何设计一个前端项目
    【PTA题目】6-20 使用函数判断完全平方数 分数 10
    C语言字符转数字函数
    C++学习笔记(十)
    【STM32】---存储器,电源核时钟体系
    使用dockerfile制作定时执行任务镜像
    大数据之hadoop入门
  • 原文地址:https://blog.csdn.net/qq_57484399/article/details/127116764