当前位置:   article > 正文

C语言——单链表_c语言单链表

c语言单链表

一,链表的定义

链表是一种常见的采用动态存储分配方式的数据结构。在链表中,有一个头指针变量,用这个指针保存一个地址,头指针指向一个变量,这个变量称为元素。链表中,每一个元素包括两部分:数据部分和指针部分。数据部分用来存放元素中包含的数据,指针部分用来指向下一个元素 。(最后一个元素指向NULL)

在链表中,第一个结点前虚假一个头结点,头指针指向头结点,头结点的指针域指向第一个实际有效结点,该节点可以称为首元结点。

确定一个链表需要一个参数:头指针,通过头指针可以推算出链表其他所有的参数

二,单链表

链表中,每个结点只有一个指针,所有指针都是单线联系,除了末尾结点指针为空外,每个结点的指针都指向下一个结点,一环扣一环。

单链表的特点:

1)有一个head指针变量,存放头结点地址,称为头指针。

2)头结点的指针域head->next,存放首元结点(第一个实际有效结点)的地址。

3)数据域存放用户需要的实际数据,指针域存放下一个结点的地址。

4)链表的使用,可以使程序的内存利用率和时间效率大大提高。

5)链表各结点间顺序由指针域next来确定

1.单链表的初始化

由于链表的每个结点都包含数据域和指针域,即每个结点都要包含不同的数据类型,所以结点的数据类型必须选用结构体类型。其中必须有一个成员的类型是指向本结构体的指针类型。

对于这种结构体类型,C语言允许递归递归定义。例如定义一个链表表示一个班级,其中每一个结点表示一位学生,他的结构体类型如下:

  1. typedef struct node{
  2. char name[20];//姓名
  3. int number;//学号
  4. struct node *next;//next的类型是指向本结构体数据类型的指针类型
  5. }Node,*LinkList;

Node是结构体类型,LinkList是结构体指针类型。LinkList head 相当于 Node *head,也相当于struct node *head。在 next 成员定义中,引用了本结构体类型,也就是说类型定义中采用了递归。

单链表的初始化就是创建一个头结点,若头结点的指针域为空,表示空单链表。单链表初始化代码如下:

  1. LinkList InitList()
  2. {
  3. LinkList head;//定义头指针变量
  4. head = (Node*)malloc(sizeof(Node));//头指针指向分配的头结点内存空间
  5. head->next=NULL;//头指针指针域为空
  6. return head;//返回头结点地址,即头指针
  7. }

2.单链表的建立

单链表的建立就是在程序运行过程中,从无到有的建立一个链表,即一个一个分配结点的内存空间,然后输入结点中的数据,并建立结点间的相连关系。单链表的建立分为尾插法和头插法。

1)尾插法建立单链表

从第一个空表开始,重复读入数据,生成新结点,将读入的数据存放到新结点的数据域中,然后将新结点插入到当前链表的表尾,直至读入结束标志为止。由于每次插入的新结点都插入到链表表尾,所以增加一个指针 r 来始终指向链表的最后一个结点,以便新结点的插入。尾插法创建单链表代码如下:

  1. void CreatByRear(LinkList head)
  2. {
  3. Node *r,*s;//s指向新创建的结点
  4. char name[20];
  5. int number;
  6. r = head;//r指向头结点 ,即当前单链表的尾结点
  7. printf ("请输入学生姓名和学号:\n");
  8. while(1)
  9. {
  10. scanf ("%s",name);
  11. scanf ("%d",&number);
  12. if (number==0)
  13. break;
  14. s = (Node*)malloc(sizeof(Node));//分配结点的内存空间 ,令s指向新分配的内存
  15. //分别赋值姓名和学号
  16. strcpy(s->name ,name);
  17. s->number = number;
  18. r->next = s;//原来的结点指向新结点
  19. r = s;//r指向新结点
  20. }
  21. r->next = NULL;//链表的尾结点指针为空
  22. }

在 while 循环中,用 s 指向新分配的内存,分别赋值姓名和学号,如果学号为 0 ,则结束输入,退出循环,最后将链表的最后一个结点的指针域赋值为NULL,表示链表创建结束。

2)头插法创建单链表

从第一个空表开始,重复读入数据,生成新结点,将读入的数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头结点之后,直至读入结束标志为止。尾插法创建单链表代码如下:

  1. void CreatByHead(LinkList head)
  2. {
  3. Node *s;
  4. char name[20];
  5. int number;
  6. printf ("请输入学生姓名和学号:\n");
  7. while(1)
  8. {
  9. scanf ("%s",name);
  10. scanf ("%d",&number);
  11. if (number==0)
  12. break;
  13. s = (Node*)malloc(sizeof(Node));
  14. strcpy(s->name ,name);
  15. s->number = number;
  16. s->next = head->next ;//新结点指向原来的首元结点
  17. head->next = s;//链表的头结点指向新结点
  18. }
  19. }

3.单链表的遍历

  1. void OutPut(LinkList head)
  2. {
  3. Node *p;//循环所用的临时指针
  4. p = head->next ;//p指向链表的首元结点
  5. while (p)
  6. {
  7. printf ("姓名:%s\n",p->name);//输出姓名
  8. printf ("学号:%d\n",p->number);//输出学号
  9. p = p->next; //移动临时指针到下一个结点
  10. }
  11. }

OutPut函数功能是将链表中的数据进行输出。函数参数中,head表示一个链表的头指针,函数中定义一个临时指针 p 用来进行循环操作,使其指向要输出链表的首元结点。

将链表的初始化,创建和遍历输出操作整合在一起,就编写了一个包含学生信息的链表结构。具体如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. typedef struct node{
  5. char name[20];//姓名
  6. int number;//学号
  7. struct node *next;//next的类型是指向本结构体数据类型的指针类型
  8. }Node,*LinkList;
  9. //单链表的初始化:就是创建一个头结点
  10. LinkList InitList()
  11. {
  12. LinkList head;//定义头指针变量
  13. head = (Node*)malloc(sizeof(Node));//头指针指向分配的头结点内存空间
  14. head->next=NULL;//头指针指针域为空
  15. return head;//返回头结点地址,即头指针
  16. }
  17. //尾插法创建单链表
  18. void CreatByRear(LinkList head)
  19. {
  20. Node *r,*s;//s指向新创建的结点
  21. char name[20];
  22. int number;
  23. r = head;//r指向头结点 ,即当前单链表的尾结点
  24. printf ("请输入学生姓名和学号:\n");
  25. while(1)
  26. {
  27. scanf ("%s",name);
  28. scanf ("%d",&number);
  29. if (number==0)
  30. break;
  31. s = (Node*)malloc(sizeof(Node));//分配结点的内存空间 ,令s指向新分配的内存
  32. //分别赋值姓名和学号
  33. strcpy(s->name ,name);
  34. s->number = number;
  35. r->next = s;//原来的结点指向新结点
  36. r = s;//r指向新结点
  37. }
  38. r->next = NULL;//链表的尾结点指针为空
  39. }
  40. //头插法创建单链表
  41. void CreatByHead(LinkList head)
  42. {
  43. Node *s;
  44. char name[20];
  45. int number;
  46. printf ("请输入学生姓名和学号:\n");
  47. while(1)
  48. {
  49. scanf ("%s",name);
  50. scanf ("%d",&number);
  51. if (number==0)
  52. break;
  53. s = (Node*)malloc(sizeof(Node));
  54. strcpy(s->name ,name);
  55. s->number = number;
  56. s->next = head->next ;//新结点指向原来的首元结点
  57. head->next = s;//链表的头结点指向新结点
  58. }
  59. }
  60. //单链表的遍历
  61. void OutPut(LinkList head)
  62. {
  63. Node *p;//循环所用的临时指针
  64. p = head->next ;//p指向链表的首元结点
  65. while (p)
  66. {
  67. printf ("姓名:%s\n",p->name);//输出姓名
  68. printf ("学号:%d\n",p->number);//输出学号
  69. p = p->next; //移动临时指针到下一个结点
  70. }
  71. }
  72. int main (void)
  73. {
  74. LinkList ha,hb;//定义单链表头指针
  75. ha = InitList();//初始化单链表
  76. CreatByRear(ha);//尾插法创建单链表
  77. OutPut(ha);//输出单链表
  78. hb = InitList();
  79. CreatByHead(hb);
  80. OutPut(hb);
  81. return 0;
  82. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/557092
推荐阅读
相关标签
  

闽ICP备14008679号