数据结构————链表及其简单应用

来源:互联网 发布:淘宝自动发卡平台 编辑:程序博客网 时间:2024/05/20 23:04

链表及其简单应用1

1.链表的基本概念

  • 链表是什么:
    链表是一种逻辑顺序是连续的但物理存储单元上非连续、非顺序的存储结构。
  • 链表实现方法:
    链表是通过以结构体为节点,然后将所有节点通过结构体的指针域指向下一个节点连接起来(连接的实现),将数据存储到数据域中(存储的实现)。
struct node//节点  {      int data;//数据域  (数据域可以多组数据,多种类型)    struct lianbiao *next;//指针;  };
  • 链表的优缺点(同数组相比):
    优点:不需要预先知道数据的个数,删除添加只需要改变附近节点的指针域
    缺点:创建使用麻烦
  • 链表的图示:
    这里写图片描述
    说明:
    1. 头指针为与链表节点类型相同的指针
    2. 一般情况情况下,头指针所指向的第一个节点不存数据,这样对在后面进行添加删除排序有很大的便利
    3. 最后一个节点指针域存NULL。方便在遍历链表时提示遍历完成

2.链表的建立

1.尾插法

  • 特点:
    输入顺序和存储顺序相同(同头插法相比)
  • 思路:
    1. \将新建的节点同之前已连接好的链表最后的节点连接起来,后
    2. 循环重复步骤1,直到符合终止条件停止循环。
    3. 使最后一个节点指针域为NULL
  • 核心代码:
    pEnd->next=pNew;//将新节点同之前已链接好的尾节点链接起来    pEnd=pNew;//尾节指针移动指向新的尾节点    pNew->next=NULL;//结束循环后使尾节点指针域为NULL
  • 完整代码:
    struct node *create()    {        int i;        struct node *pHead,*pNew,*pEnd;        printf("请输入正整数,输入小于0的数停止输入:\n");         pHead=pEnd=(struct node *)malloc(sizeof(struct node));//头指针所指的节点不存数据         pHead->next=NULL;        pNew=(struct node *)malloc(sizeof(struct node));//申请新节点         scanf("%d",&pNew->date);//向数据域输入数据         while(pNew->date>0)        {            pEnd->next=pNew;//连接             pNew->next=NULL;//新节点指针域变空             pEnd=pNew;            pNew=(struct node *)malloc(sizeof(struct node));            scanf("%d",&pNew->date);        }        free(pNew);//释放最后存入小于0的节点         return pHead;//返回头指针     }
  • 图示:
    画图示意输入 3 4 -1的过程
    这里写图片描述
  • 解释:
    1. pHead,pNew,pEnd 全部为指针变量,类型为结构体,不是结构体变量。
    2. pHead为头指针,pNew为新建的节点,pEnd为已连接好的节点最后一个节点

2. 头插法

  • 特点:
    存储顺序与输入顺序相反。
  • 思路:
    1. 将新建节点插入到头结点(不存数据的节点)之后。
    2. 循环重复步骤1,直到遇到终止条件停止循环
  • 核心代码:

    pNew->next=pHead->next;//将新节点与第二个连接
    pHead->next=pNew;//将新节点与头节点连接
  • 完整代码:
     struct node *create()    {        int i;        struct node *pHead,*pNew,*pEnd;        printf("请输入正整数,输入小于0的数停止输入:\n");         pHead=pEnd=(struct node *)malloc(sizeof(struct node));//头指针所指的节点不存数据         pHead->next=NULL;        pNew=(struct node *)malloc(sizeof(struct node));//申请新节点         scanf("%d",&pNew->date);//向数据域输入数据         while(pNew->date>0)        {            pNew->next=pHead->next;//将新节点与第二个连接             pHead->next=pNew;//将新节点与头节点连接             pNew=(struct node *)malloc(sizeof(struct node));            scanf("%d",&pNew->date);        }        free(pNew);//释放最后存入小于0的节点         return pHead;//返回头指针     }
  • 图示:
    此处应该有图,但画图太心累。大家自己动手画吧。●v●

3.链表的遍历以及增删改查

1.遍历链表

  • 思路:
    1. 定义一个指针,初始化为头指针的指针域(不存数据时)
    2. 访问操作它所指向的节点的数据域
    3. 移动指针使它指向下一个节点。
    4. 循环重复1-3,直到指针指向NULL(指针移动到尾节点)
      5.遍历是链表操作的基础
  • 核心代码:
     while(pt!=NULL)    {        pt=pt->next;    }
  • 完整代码:
     void output(struct node *pHead)    {        struct node *pt=pHead->next;        while(pt!=NULL)        {            printf("%d\n",pt->date);//输出            pt=pt->next;//指针移动        }    }

2.增加新节点

  • 思路:
    1. 新建节点。
    2. 再利用指针遍历链表找到插入位置的前一个节点(pt),
    3. 操作指针,插入新建的节点
  • 核心代码:
     pNew->next=pt->next;        pHead->nt=pNew;
  • 完整代码:
     void increase(struct node *pHead)     {        struct node *pt=pHead,*pNew;        int a;        printf("你想插在数字几的后面:\n");        scanf("%d",&a);        while(pt&&pt->date!=a)            pt=pt->next;        if(pt==NULL)            printf("未找到这个数\n");         else        {            pNew=(struct node *)malloc(sizeof(struct node));             printf("输入需要插入的数");            scanf("%d",&pNew->date);            pNew->next=pt->next;            pt->next=pNew;        }            }

3. 删除节点

  • 思路:
    1. 寻找需删除的节点和前一个节点
    2. 操作指针,连接删除节点的前后节点
    3. 释放需删除节点所占用的内存空间
  • 核心代码:
     pt_1->next=pt->next;
  • 完整代码:
     void strike_out(struct node *pHead)//删除    {        int a;         struct node *pt_1=pHead,*pt=pHead;        printf("请输入你想删除数字\n");        scanf("%d",&a);        while(pt&&pt->date!=a)        {            pt_1=pt;//该节点的前一个节点             pt=pt->next;        }           if(pt==NULL)            printf("未找到这个数!\n");        else        {            pt_1->next=pt->next;//删除             free(pt);//释放空间             printf("已删除!\n");        }    }

4.修改数据

  • 思路:遍历链表,找到需改变的节点,操作数据域。
  • 其他类似与遍历链表

5. 查找数据

  • 思路:遍历链表,找到查询的节点,输出数据域。
  • 其他类似与遍历链表。

4.升序合并,冒泡排序,插入排序

1. 升序合并

  • 思路:
    1. 建立两个链表,a链和b链
    2. 定义三个链表指针变量,a,b,c
    3. a遍历a链,b遍历b链,c用来合并
    4. 比较a和b当前指的节点。
    5. c和两者中小的连接起来,移动c和两者中小的指针。循环重复,直到某条链表移动到尾部。将c和未遍历完连接起来。
  • 核心代码:
     c->next=a(b);//c连接值较小的节点     c=a(b);//c移动     a(b)=a(b)->next;//指向小的节点的指针移动
  • 完整代码:
  • 想看代码点我
  • 或者点我

2. 冒泡排序

  • 思路:
    1. 假设有n个节点。进行n趟排序,每趟比较0到第n-i-1个数(i为趟数)中相邻的节点(使用指针遍历)。
    2. 符合条件交换节点位置(也可以交换数据)。
    3. 然后移动指针,注意如果使用交换节点的方法进行冒泡时,有没有交换移动指针的方式不同。
  • 核心代码:
     交换两个相邻节点(pj和pj_h,pj_1为pj的前一个节点,pt为临时指针)      pt=pj->next;     pj->next=pj_h->next;     pj_h->next=pt;     pt=pj_1->next;     pj_1->next=pj_h->next;     pj_h->next=pt;
  • 完整代码:
     void sore(struct node *pHead) //排序     {        int i,j,flag;        struct node *pj_1,*pj,*pj_h,*pt;        for(i=0;i<iCound-1;i++)            for(j=0,pj=pHead,flag=0;j<iCound-i-1;j++)             {                if(flag==0)                {                    pj_1=pj;                    pj=pj->next;                    pj_h=pj->next;                }                if(flag==1)                {                    pj_1=pj_1->next;                    pj_h=pj->next;                }                   flag=0;                if((pj->aver)<(pj_h->aver))                {                pt=pj->next;                pj->next=pj_h->next;                pj_h->next=pt;                pt=pj_1->next;                pj_1->next=pj_h->next;                pj_h->next=pt;                flag=1;                 }               }    }

3. 插入排序

  • 思路:
    1. 将无序节点插入到有序节点。
    2. 有序表节点初始为第一个节点。
    3. 将有序表的下一个节点(无序节点的第一个)按大小插入到有序表表中。
    4. 插入时,先删除需插入的节点(但不释放内存)。再插入。
  • 核心代码:
     pi_1->next=pi->next;//删除     pi->next=pj->next;//连接     pj->next=pi;
  • 完整代码:
void sore(struct node *pHead) //排序  {    struct node *pt,*pt_h,*pi;    pt=pHead->next;    pt_h=pt->next;    pHead->next=NULL;    while(pt){        for(pi=pHead;pi->next&&pi->next->expn<pt->expn;pi=pi->next);        pt_h=pt->next;        pt->next=pi->next;        pi->next=pt;        pt=pt_h;        }} 

5.简单应用

1.删除a链中与b链重复的节点

  • 思路:
    1. 将a链每一个节点同b链进行比较。(两重循环)
    2. 删除相同节点
  • 完整代码:
  • 想看代码点我
  • 或者点我

2. n个小孩报m个数的问题

  • 问题:n个小孩从1到m报数,报到m的小孩出队,然后继续从0到m报数,报到m的小孩出队。当最后一个报完后,从第1个小孩继续报数,循环重复,直到只剩一名小孩,输出该小孩的序号。
  • 思路:
    1. 建立一个n个节点的循环链表(头结点也存数据,尾节点指针域存头结点地址)。
    2. 遍历,删除报到第m个数节点。
  • 完整代码
  • 想看源代码点我
  • 或者点我

3.简单的学生管理习统

  • 实现功能:
    1. 简单的文字界面
    2. 简单的密码登陆(密码输入的时候显示*)。
    3. 信息的增删改查
    4. 按平均分排序。
  • 完整代码
  • 想看源代码点我
  • 或者点我

最后一些废话

写这个博客真很心累,特别是画图,强迫症的我为了对齐,画了好长时间,原计划要画好多图的,因为链表这一块画图真的很有助于理解。非常建议大家画图。最后,我也是初学者,有些地方难免有所疏漏,希望大家可以多多包涵。在评论中指出错误指出。
还有文中的超链接 一份是有道云笔记,一份是我的cmdn代码片。应该都可以直接运行。有什么错误也可以指出。

0 0
原创粉丝点击