c语言单向链表

一、链表概述  

  链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。它可以根据需要开辟内存单元。链表有一个“头指针”变量,以head表示,它存放一个地址。该地址指向一个元素。链表中每一个元素称为“结点”,每个结点都应包括两个部分:一为用户需要用的实际数据,二为下一个结点的地址。因此,head指向第一个元素:第一个元素又指向第二个元素;……,直到最后一个元素,该元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。
        链表的各类操作包括:学习单向链表的创建、删除、  插入(无序、有序)、输出、  排序(选择、插入、冒泡)、反序等等。
二、链表创建、删除、插入等如下,将函数与声明定义进行分离为.h和.c:

2.1 linklist.h

 1 #pragma once
 2 typedef struct list
 3 {
 4     int data;//数据域
 5     struct list *next;//指针域
 6 }LinkList;
 7 LinkList *crate_list();    //建立一个节点
 8 void traverse(LinkList*ls);//循环遍历链表
 9 LinkList* insert_list(LinkList* ls, int n, int data);//在指定位置插入元素
10 int delete_list(LinkList* ls, int n);//删除指定位置元素
11 int count_list(LinkList* ls);//返回链表元素的个数
12 void clear_list(LinkList *ls);//清空链表,只保留首节点
13 int empty_list(LinkList *ls);//返回链表是否为空
14 LinkList *local_list(LinkList*ls, int n);//返回链表指定的位置节点
15 LinkList * elem_list(LinkList* ls, int data);//返回指定位置data
16 int elem_pos(LinkList *ls, int data);//返回数据域等于DATA的位置
17 LinkList *last_list(LinkList *ls);//得到链表的最后一个节点
18 void merge_list(LinkList * s1,LinkList* s2);//合并两个链表
19 void reverse_lsit(LinkList *ls);//链表反转

2.2  linklist.c

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include "linlist.h"
  4 //建立一个节点
  5 LinkList * crate_list()
  6 {
  7     return (LinkList*)calloc(sizeof(LinkList),1);
  8 }
  9 //循环遍历链表
 10 void traverse(LinkList * ls)
 11 {
 12     LinkList *p = ls;
 13     while (p)
 14     {
 15         printf("%d\n",p->data);
 16         p = p->next;
 17     }
 18 
 19 }
 20 //插入元素
 21 LinkList * insert_list(LinkList * ls, int n, int data)
 22 {
 23     LinkList *p = ls;
 24     while (p&&n--)
 25     {
 26         p = p->next;
 27     }
 28     if (p==NULL)
 29     {
 30         return NULL;//n的位置大于链表节点数
 31     }
 32     LinkList *node = crate_list();//新建一个节点
 33     node->data = data;
 34     node->next = p->next;
 35     p->next = node;
 36     return node;
 37 }
 38 //删除节点
 39 int delete_list(LinkList * ls, int n)
 40 {
 41     LinkList *p = ls;
 42     while (p&&n--)
 43     {
 44         p = p->next;
 45     }
 46     if (p==NULL)
 47     {
 48         return -1;
 49     }
 50     LinkList *tmp = p->next;
 51     p->next = p->next->next;
 52     free(tmp);
 53     return 0;
 54 }
 55 //返回链表元素的个数
 56 int count_list(LinkList * ls)
 57 {
 58     LinkList *p = ls;
 59     int count = 0;
 60     while (p)
 61     {
 62         count++;
 63         p = p->next;
 64     }
 65     return count;
 66 }
 67 //清空链表,只保留首节点
 68 void clear_list(LinkList * ls)
 69 {
 70     LinkList* p = ls->next;
 71     while (p)
 72     {
 73         LinkList * tmp = p->next;
 74         free(p);
 75         p = tmp;
 76     }
 77     ls->next = NULL;//只有首节点,则首节点next实则为NULL
 78 }
 79 //返回聊表是否为空
 80 int empty_list(LinkList * ls)
 81 {
 82     if (ls->next)
 83         return 0;
 84     else
 85         return -1;
 86     return 0;
 87 }
 88 //返回链表指定位置的节点数据域
 89 LinkList * local_list(LinkList * ls, int n)
 90 {
 91     LinkList* p = ls;
 92     while (p&&n--)
 93     {
 94         p=p->next;
 95     }
 96     if (p == NULL)
 97         return NULL;
 98     return p;
 99 }
100 //返回指定位置数据域对应的节点
101 LinkList * elem_list(LinkList * ls, int data)
102 {
103     LinkList*p = ls;
104     while (p)
105     {
106         if (p->data = data)
107             return p;
108         p = p->next;
109     }
110     return NULL;//没有找到
111 }
112 //返回数据域等于data的节点位置
113 int elem_pos(LinkList * ls, int data)
114 {
115     LinkList * p = ls;
116     int index = 0;
117     while (p)
118     {
119         index++;
120         if (p->data = data)
121             return index;
122         p = p->next;
123     }
124     return -1;//没有找到索引
125 }
126 
127 LinkList * last_list(LinkList * ls)
128 {
129     LinkList * p = ls;
130     while (p->next)
131     {
132         p = p->next;
133     }
134     return p;
135 }
136 //合并两个链表,将结构放在第一个链表中
137 void merge_list(LinkList * s1, LinkList * s2)
138 {
139     //合并连标点节点,不合并链表头
140     last_list(s1)->next = s2->next;
141     free(s2);
142 }
143 
144 void reverse_lsit(LinkList * ls)
145 {
146     if (ls->next == NULL)
147         return;//只有只有一个头节点
148     if (ls->next->next == NULL)
149         return;
150     LinkList * last = ls->next;//ls->next为最后一个节点
151     LinkList * pre = ls;//上一个节点的指针
152     LinkList *cur = ls->next;//当前节点
153     LinkList*next = NULL;//下一个节指针
154     while (cur)
155     {
156         next = cur->next;
157         cur->next = pre;
158         pre = cur;
159         cur = next;
160     }
161     ls->next = pre;
162     last->next = NULL;
163 }

2.3  测试主函数

 1 #include<stdlib.h>
 2 #include<stdio.h>
 3 #include"linlist.h"
 4 #define Len 10
 5 int main()
 6 {
 7     LinkList *first = crate_list();//创建第一个节点
 8     LinkList *second = crate_list();//创建第二个节点
 9     LinkList *third = crate_list();//创建第三个节点
10     first->next = second;//指针域第一个节点的指针指向下一节点
11     second->next = third;//指针域第二个节点的指针指向下一节点
12     third->next = NULL;//指针域第三个节点的指针指向下一节点,只有三个元素,所以下一节点为NULL
13     first->data = 1;//数据域第一个元素
14     second->data = 2;//数据域第二个元素
15     third->data = 3;//数据域第二个元素
16     //遍历链表
17     printf("插入前:\n");
18     traverse(first);//遍历头即可打印整个链表,因为链表是靠指针连接在一起
19     insert_list(first,0,100);
20     printf("插入后:\n");
21     traverse(first);
22     printf("删除后\n");
23     delete_list(first,2);
24     traverse(first);
25     printf("--------------------------------------\n");
26     printf("链表的个数cout=%d\n", count_list(first));
27     //printf("清空链表,直保留首节点\n");
28     //clear_list(first);
29     printf("链表的个数cout=%d\n", count_list(first));
30     printf("%d\n",local_list(first,2)->data);
31     printf("data=%d\n",last_list(first)->data);
32     printf("-----------------------------------------\n");
33 
34     LinkList * pp = crate_list();
35     for (int i = 0; i < Len; i++)
36     {
37         insert_list(pp,0,i);
38     }
39     merge_list(first,pp);
40     traverse(first);
41     printf("xxxxxxxxxxxxxxxxxxxx");
42     reverse_lsit(first);
43     traverse(first);
44     return 0;
45 }

2.4 结果显示:

posted on 2019-09-01 15:40  lfylcj  阅读(382)  评论(0编辑  收藏  举报

导航