[C Language] Efficient Data Storage and Retrieval: Application of C Language Linked List

Table of contents

1. Overview of linked list

Second, the advantages and disadvantages of arrays and linked lists

3. Design of static linked list

Fourth, typedef aliases the structure type

5. Take the student management system as an example to explain the linked list in detail

1. Main test function

2. link.h header file declaration

3. Realize the operation function link.c

4. Realize query linked list operation function

5. Delete the specified node of the linked list

6. Release the linked list

7. Flip the linked list

8. The linked list is sorted by student number

Six, two-way circular linked list

1 Overview

2. Node design

 3. Example of two-way circular linked list


1. Overview of linked list

The linked list is a linear storage structure          in which the data elements are not continuous in physical storage , and are logically continuous through the pointer link order in the linked list .

The linked list consists of a series of nodes (each element in the linked list is called a node), and the nodes are dynamically generated         at runtime (malloc)

Each node consists of two parts :

One is a data field that stores data elements, and the other is a pointer field
that stores the address of the next node

Ways to save the address of the head node:

Leading linked list: use a node with empty data to store, and use its pointer field to save the address of the head node.

 Linked list without a head: define a 4B pointer variable to store the address of the head node.

Second, the advantages and disadvantages of arrays and linked lists

Advantages of arrays: high efficiency in traversing elements

Array disadvantages:

Static array: int arr[N]; The number of array elements must be determined in advance , too much waste is too small and easy to overflow, delete and insert data is inefficient (need to move a large amount of data )

Dynamic array: No need to know the number of elements in advance , apply dynamically during use , delete and insert data is inefficient (need to move a large amount of data )

Advantages of linked list: No need to know the number of data in advance, apply dynamically during use, insert and delete without moving data

Disadvantages of linked list: low traversal efficiency

3. Design of static linked list

Take the names of four students as an example:

#include <stdio.h>
struct stu
{
	//数据域
	int num;
	char name[100];
	//指针域
	struct stu* next;
};
void test()
{
	struct stu node1 = { 1,"lucy",NULL };
	struct stu node2 = { 2,"bob",NULL };
	struct stu node3 = { 3,"张三",NULL };
	struct stu node4 = { 4,"李四",NULL };
	//定义链表头
	struct stu* head = &node1;
	//连接链表
	node1.next = &node2;
	node2.next = &node3;
	node3.next = &node4;
	//遍历链表
	struct stu * pb = &head;//重新定义另外一个指针变量,防止指向错误导致链表头丢失
	while (pb != NULL)
	{
		printf("%d %s\n", pb->num, pb->name);
		pb移动到下一个节点位置
		pb=pb->next;
	}
}
int main(int argc, char const* argv[])
{
	test();
	return 0;
}

Fourth, typedef aliases the structure type

Method 1:

typedef struct data_long
{
	int a;
	short b;
}DATA;//DATA是类型
void test()
{
	struct data_long ob1;
	DATA ob2;//用别名定义
}

Method 2:

struct data_long
{
	int a;
	short b;
};
void test()
{
	typedef struct data_long DATA;
	DATA ob2;//用别名定义
}

Structure pointer aliases:

typedef struct data_long
{
	int a;
	short b;
}DATA,*DATA_P;
void test()
{
	//DATA==struct data_long
	DATA A = {10,20};//用别名初始化
	//DATA_P==struct data_long *
	DATA_P p = &A;
	printf("%d %d", p->a, p->b);
}

5. Take the student management system as an example to explain the linked list in detail

        The system includes five regular linked list operations, including linked list insertion , linked list traversal , linked list query , deletion of specified nodes in the linked list, and release of the linked list. For the convenience of viewing, the implementation operation functions of linked list query , deleted linked list specified node, released linked list, etc. are listed separately.

1. Main test function

#include <stdio.h>
#include <string.h>
#include"link.h>
STU *head=NULL;//链表头设置为NULL(链表存在依据)
void help(void)
{
    printf("*******************************\n");
    printf("*help:帮助信息 *\n");
    printf("*insert:插入链表节点 *\n");
    printf("*print:遍历链表节点 *\n");
    printf("*search:查询链表某个节点 *\n");
    printf("*delete:删除链表某个节点 *\n");
    printf("*free:释放整个链表 *\n");
    printf("*quit:退出程序 *\n");
    printf("*reverse:翻转链表 *\n");
    printf("*sort:链表排序 *\n");
    printf("*******************************\n");
}
int main(int argc, char const *argv[])
{
    help();
    while (1)
{
    char cmd[128] = "";//定义commend命令
    printf("请输入操作命令:");
    scanf("%s", cmd);
if (strcmp(cmd, "help") == 0)
{
    help();
}
else if (strcmp(cmd, "insert") == 0)
{
    printf("‐‐‐‐‐‐‐‐‐链表插入‐‐‐‐‐‐‐‐\n");
    printf("请输入需要插入的学生信息num name score:");
    STU tmp;
    scanf("%d %s %f",&temp.num,tmp.name,tmp.score);
    //将tmp插入到链表中
    head=insert_link(head,tmp);//返回值更新head指向
}
lse if (strcmp(cmd, "print") == 0)
{
    printf("‐‐‐‐‐‐‐‐‐链表遍历‐‐‐‐‐‐‐‐\n");
    print_link(head);
}
else if (strcmp(cmd, "search") == 0)
{
    printf("‐‐‐‐‐‐‐‐‐链表查询‐‐‐‐‐‐‐‐\n");
    printf("请输入要查找的姓名:");
    char name[32]="";
    scanf("%s\n",name);
    STU *ret=search_link(head,name);
    if(ret!=NULL)
    {
       printf("查询的结果:%d %s %f\n",ret->num,ret->name,ret->score);
    }
}
else if (strcmp(cmd, "delete") == 0)
{
    printf("‐‐‐‐‐‐‐‐‐删除链表指定节点‐‐‐‐‐‐‐‐\n");
    printf("请输入要删除的学号:");
    scanf("%d",num);
    head=delete_link(head,num);
}
else if (strcmp(cmd, "free") == 0)
{
    printf("‐‐‐‐‐‐‐‐‐释放链表‐‐‐‐‐‐‐‐\n");
    head=free_link(head);
}
else if (strcmp(cmd, "quit") == 0)
{
    head=free_link(head);
    break;
}
else if(strcmp(cmd,"reserve")==0)
{
    head=reverse_link(head);
}
else if(strcmp(cmd,"aort")==0)
{
    sort_link(head);
}
}
    return 0;
}

2. link.h header file declaration

Linked list node type design:

//防止头文件重复包含
#ifndef _LINK_H_
#ifdef _LINK_H_
//定义链表节点类型
typedef struct stu
{
    //数据域
    int num;
    char name[30];
    float score;
    //指针域
    struct stu *next;
}STU;
//声明
extern STU *insert_link(STU *head, STU tmp);
extern void print_link(STU *head);
extern STU *search_link(STU *head,char *name);
extern STU *delete_link(STU *head,int num);
extern STU* free_link(STU* head)
extern STU* reverse_link(STU *head)
extern void sort_link(STU *head)
#endif

3. Realize the operation function link.c

#include<stdio.h>//perror等头文件
#include<stdlib.h>//malloc,exit头文件
#include<string.h>
#include"link.h"
#if 1 //链表头部插入
STU* insert_link(STU *head, STU tmp)
{
    //为待插入的数据申请空间
    STU *pi=(STU *)calloc(1,sizeof(STU));
    if(pi=NULL)
    {
        perror("calloc");//打印错误信息
        exit(-1);
    }
    //tmp数据赋值到*pi
    *pi=tmp;
    pi->next=NULL;
    //判断链表是否存在
    if(head=NULL)
    {
        head=pi;
    else //存在
    {
        pi->next=head;
        head=pi;
    }
    return head;    
}
#endif
#if 0  //链表尾部插入
STU* insert_link(STU *head, STU tmp)
{
    //为待插入的数据申请空间
    STU *pi=(STU *)calloc(1,sizeof(STU));
    if(pi=NULL)
    {
        perror("calloc");//打印错误信息
        exit(-1);
    }
    //tmp数据赋值到*pi
    *pi=tmp;
    pi->next=NULL;
    //判断链表是否存在
    if(head=NULL)
    {
        head=pi;
    else //存在
    {
        STU *pb=head;
        while(pb!=NULL)
        {
            pb=pb->next;
        }
        pb->next=pi;
    }
    return head;    
}
#endif
#if 0  //按学号有序插入(包含头部和尾部插入)
STU* insert_link(STU *head, STU tmp)
{
    //为待插入的数据申请空间
    STU *pi=(STU *)calloc(1,sizeof(STU));
    if(pi=NULL)
    {
        perror("calloc");//打印错误信息
        exit(-1);
    }
    //tmp数据赋值到*pi
    *pi=tmp;
    pi->next=NULL;
    //判断链表是否存在
    if(head=NULL)
    {
        head=pi;
    else //存在
    {
        //寻找插入点位置
        STU *pb=head,*pf=head;
        while((pb‐>num < pi‐>num) && (pb‐>next != NULL))
        {
            pf=pb;
            pb=pb->next;
        }
        if(pb‐>num >= pi‐>num)//头部,中部插入
        {
            if(head=pi)
            {
                pi->next=head;
                head=pi
            }
            else //中部插入
            {
                pf->next=pi;
                pi->next=pb;
                }
        else
        {
            pb‐>next = pi;
            
        }
    }
    return head;    
}
#endif
void print_link(STU *head)
{
    //判断链表是否存在
    if(head=NULL)
    {
    printf("link not exits");
    return;
    }
    else
    {
        STU *pb=head;
        while(pb!=NULL)
        {
            printf("%d %s %f\n",pb->num,pb->name,pb->score);
            pb=pb->next;
        }
    }
    return;
}
    

4. Realize query linked list operation function

STU *search_link(STU *head, char *name)
{
    //判断链表是否存在
    if (NULL == head)
    {
        printf("link not exist\n");
        return NULL;
    }
    else //链表存在
    {
        STU *pb = head;
        while ((strcmp(pb‐>name, name) != 0) && (pb‐>next != NULL))
        {
            pb = pb‐>next;
        }
//找到
        if (strcmp(pb‐>name, name) == 0)
        {
            return pb;
        }
    }
    printf("未找到相关数据\n");
    return NULL;
}

5. Delete the specified node of the linked list

STU* delete_link(STU *head, int num)
{
    //判断链表是否存在
    if(NULL == head)
    {
        printf("link not exist\n");
        return head;
    }
    else
    {
        //查找删除的点
        STU *pb=head, *pf = head;
        while((pb‐>num != num)&&(pb‐>next != NULL))
            {
                pf = pb;
                pb = pb‐>next;
            }
        if(pb‐>num == num)//找到
        {
            //判断删除点的位置
            if(pb == head)//删除头节点
            {
                head=head‐>next;
                //free(pb);
            }
            else//删除中尾部节点
            {
                pf‐>next = pb‐>next;
                //free(pb);
            }
            free(pb);
            printf("已成功删除num=%d的节点\n", num);
        }
        else//未找到
        {
            printf("未找到需要删除的节点\n");
        }
    }
return head;
}

6. Release the linked list

STU* free_link(STU* head)
{
    //判断链表是否存在
    if(NULL == head)
    {
        printf("link not exist\n");
    }
    else
    {
        STU *pb = head;
        while(pb!=NULL)
        {
            head = pb‐>next;
            free(pb);
            pb = head;
        }
    }
return NULL;
}

7. Flip the linked list

STU* reverse_link(STU *head)
{
    //判断链表是否存在
    if(NULL == head)
    {
        printf("link not exist\n");
        //return head;
    }
    else
    {
        STU *pb = head‐>next;
        STU *pn = NULL;
        head‐>next = NULL;
        while(pb != NULL)
        {
            //纪录pb下一个节点位置
            pn = pb‐>next;
            //pb连接上一个节点
            pb‐>next = head;
            head = pb;
            pb = pn;
        }
        printf("链表翻转成功\n");
    }
return head;
}

8. The linked list is sorted by student number

void sort_link(STU *head)
{
    //判断链表是否存在
    if (NULL == head)
    {
        printf("link not exist\n");
        return;
    }
    else
    {
        STU *p_i = head, *p_j = head; //int i=0,j=0;
        while (p_i‐>next != NULL) //for(i=0;i<n‐1;i++)
        {
            STU *p_min = p_i; //int min = i;
            p_j = p_min‐>next; //j=min+1;
            while (p_j != NULL) //for(;j<n;j++)
             {
                 if (p_min‐>num > p_j‐>num) //if(arr[min] > arr[j])
                 p_min = p_j; //min = j;
                p_j = p_j‐>next; //j++
             }
            if (p_i != p_min) //if(i != min)
            {
                //交换数据
                STU tmp = *p_i;
                *p_i = *p_min;
                *p_min = tmp;
                tmp.next = p_i‐>next;
                 p_i‐>next = p_min‐>next;
                 p_min‐>next = tmp.next;
            }
            p_i = p_i‐>next; //i++
        }
    }
return;
}

Six, two-way circular linked list

1 Overview

2. Node design

typedef struct stu
{
    //数据域
    int num;
    char name[32];
    //指针域
    struct stu *pre;
    struct stu *next;
}STU;

 3. Example of two-way circular linked list

        Design a student information system with a doubly linked list, including functions such as insertion, traversal, search, deletion, and release.

1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 typedef struct stu
5 {
6 //数据域
7 int num;
8 char name[32];
9
10 //指针域
11 struct stu *pre;
12 struct stu *next;
13 } STU;
14 STU *head = NULL;
15 void insert_link(STU **p_head, STU tmp);
16 void print_link(STU *head);
17 STU *search_link(STU *head, int num);
18 void delete_link(STU **p_head, int num);
19 void free_link(STU **p_head);
20 int main(int argc, char const *argv[])
21 {
22 int n = 0;
23 printf("请输入学生的个数:");
24 scanf("%d", &n);
25
26 int i = 0;
27 for (i = 0; i < n; i++)
28 {
29 printf("请输入第%d个学员的信息:", i + 1);
30 STU tmp;
31 scanf("%d %s", &tmp.num, tmp.name);
32
33 insert_link(&head, tmp);
34 }
35
36 //遍历链表
37 print_link(head);
38
39 //查询
40 printf("请输入你要查询的学号:");
41 int num = 0;
42 scanf("%d", &num);
43 STU *ret = search_link(head, num);
44 if (ret != NULL)
45 {
46 printf("查询的结果:%d %s\n", ret‐>num, ret‐>name);
47 }
48
49 //删除指定节点
50 printf("请输入你要删除的学号:");
51 scanf("%d", &num);
52
53 delete_link(&head, num);
54
55 //遍历链表
56 print_link(head);
57
58 //释放这个链表
59 free_link(&head);
60
61 //遍历链表
62 print_link(head);
63
64 return 0;
65 }
66
67 //尾插法
68 void insert_link(STU **p_head, STU tmp)
69 {
70 STU *head = *p_head;
71
72 //为插入的节点申请空间
73 STU *pi = (STU *)calloc(1, sizeof(STU));
74 *pi = tmp;
75 pi‐>next = NULL;
76 pi‐>pre = NULL;
77
78 //判断链表是否为空
79 if (NULL == head)
80 {
81 head = pi;
82 pi‐>next = pi;
83 pi‐>pre = pi;
84 }
85 else
86 {
87 head‐>pre‐>next = pi;
88 pi‐>next = head;
89 pi‐>pre = head‐>pre;
90 head‐>pre = pi;
91 }
92
93 //更新外部的head
94 *p_head = head;
95 }
96
97 void print_link(STU *head)
98 {
99 //判断链表是否存在
100 if (NULL == head)
101 {
102 printf("link not exist\n");
103 return;
104 }
105 else
106 {
107 STU *pn = head;
108 STU *pr = head‐>pre;
109
110 while (1)
111 {
112 if (pn == pr) //链表节点为奇数个
113 {
114 printf("%d %s\n", pn‐>num, pn‐>name);
115 break;
116 }
117 else if (pn‐>next == pr) 链表节点为偶数个
118 {
119 printf("%d %s\n", pn‐>num, pn‐>name);
120 printf("%d %s\n", pr‐>num, pr‐>name);
121 break;
122 }
123 else
124 {
125 printf("%d %s\n", pn‐>num, pn‐>name);
126 printf("%d %s\n", pr‐>num, pr‐>name);
127 pn = pn‐>next;
128 pr = pr‐>pre;
129 }
130 }
131 }
132 return;
133 }
134
135 STU *search_link(STU *head, int num)
136 {
137 //判断链表是否存在
138 if (NULL == head)
139 {
140 printf("link not exist\n");
141 return NULL;
142 }
143 else
144 {
145 STU *pn = head;
146 STU *pr = head‐>pre;
147
148 while ((pn‐>num != num) && (pr‐
>num != num) && (pn != pr) && (pn‐>next != pr))
149 {
150 pn = pn‐>next;
151 pr = pr‐>pre;
152 }
153
154 if (pn‐>num == num)
155 {
156 return pn;
157 }
158 else if (pr‐>num == num)
159 {
160 return pr;
161 }
162 else
163 {
164 printf("没有找到相关节点\n");
165 }
166 }
167
168 return NULL;
169 }
170
171 #if 0
172 void delete_link(STU **p_head, int num)
173 {
174 STU *head = *p_head;
175
176 if (NULL == head)
177 {
178 printf("link not exist\n");
179 return;
180 }
181 else
182 {
183 STU *pn = head;
184 STU *pr = head‐>pre;
185
186 while ((pn‐>num != num) && (pr‐
>num != num) && (pn != pr) && (pn‐>next != pr))
187 {
188 pn = pn‐>next;
189 pr = pr‐>pre;
190 }
191
192 if (pn‐>num == num) //头部、中部节点
193 {
194 if (pn == head) //删除头节点
195 {
196 head‐>next‐>pre = head‐>pre;
197 head‐>pre‐>next = head‐>next;
198 head = head‐>next;
199 //free(pn);
200 }
201 else //删除中部节点
202 {
203 pn‐>pre‐>next = pn‐>next;
204 pn‐>next‐>pre = pn‐>pre;
205 //free(pn);
206 }
207 printf("成功删除节点:%d %s\n", pn‐>num, pn‐>name);
208 free(pn);
209 }
210 else if (pr‐>num == num) //尾部、中部
211 {
212 pr‐>pre‐>next = pr‐>next;
213 pr‐>next‐>pre = pr‐>pre;
214 printf("成功删除节点:%d %s\n", pr‐>num, pr‐>name);
215 free(pr);
216 }
217 else
218 {
219 printf("没有找到相关节点\n");
220 }
221 }
222
223 *p_head = head;
224 }
225 #endif
226
227 #if 1
228 void delete_link(STU **p_head, int num)
229 {
230 STU *head = *p_head;
231
232 if (NULL == head)
233 {
234 printf("link not exist\n");
235 return;
236 }
237 else
238 {
239 STU *pn = head;
240 STU *pr = head‐>pre;
241
242 while ((pn‐>num != num) && (pr‐
>num != num) && (pn != pr) && (pn‐>next != pr))
243 {
244 pn = pn‐>next;
245 pr = pr‐>pre;
246 }
247
248 if (pn‐>num == num) //头部、中部节点
249 {
250 pn‐>next‐>pre = pn‐>pre;
251 pn‐>pre‐>next = pn‐>next;
252 if (pn == head) //删除头节点
253 {
254 head = head‐>next;
255 }
256
257 printf("成功删除节点:%d %s\n", pn‐>num, pn‐>name);
258 free(pn);
259 }
260 else if (pr‐>num == num) //尾部、中部
261 {
262 pr‐>pre‐>next = pr‐>next;
263 pr‐>next‐>pre = pr‐>pre;
264 printf("成功删除节点:%d %s\n", pr‐>num, pr‐>name);
265 free(pr);
266 }
267 else
268 {
269 printf("没有找到相关节点\n");
270 }
271 }
272
273 *p_head = head;
274 }
275 #endif
276
277 void free_link(STU **p_head)
278 {
279 STU *head = *p_head;
280
281 if (NULL == head)
282 {
283 printf("link not exist\n");
284 return;
285 }
286 else
287 {
288 STU *pn = head;
289 do
290 {
291 head = head‐>next;
292 free(pn);
293 pn = head;
294 } while (pn != (*p_head));
295 }
296
297 *p_head = NULL;
298 return;
299 }

Guess you like

Origin blog.csdn.net/m0_75045191/article/details/131729008