C language basics - (linked list instance of C language)

Comments from friends are welcome✨✨ This chapter series is a deep thinking and summary of C language, and the content of C language will continue to be updated


foreword

This chapter will bring you an example based on C language linked list.

1. What is a linked list

A linked list is a common and important data structure. Linked list is a structure for dynamic storage allocation, and it will open up memory units according to needs.
The linked list has a "head pointer" variable, which stores an address, which points to an element. Each element in the linked list is called a "node", and each node should include two parts: 1. The
actual data;
2. The address of the next node. It can be seen that the "head pointer" points to an element, and the first element points to the second element... until the last element, this element no longer points to other elements, it is called "table tail", and its address part is placed A "NULL" (meaning "empty address"), the linked list ends here.
For such a linked list data structure, the addresses of its elements in memory may be discontinuous. To find an element, you must first find the previous element of the element, and then find the next element according to the address of the next element it provides. If the "head pointer" is not provided, the entire linked list cannot be accessed. A linked list is like an iron chain, one link after another, and the middle cannot be broken. Obviously, the data structure of the linked list must be realized by using a pointer variable, that is, a node should contain a pointer variable, and use it to store the address of the next node.

2. Create a simple static linked list

For example, you can design a structure type like this:

struct   data
{
    
    
	int num;
	struct data *next;   //next 是指针变量,指向结构体变量
};

Note: The above only defines a struct data type, and does not actually allocate storage space. Only when variables are defined can storage units be allocated.
Among them, the member num is used to store the data in the node (the data that the user needs to use), and next is a member of the pointer type, which points to the struct data type data (that is, the structure type where next is located). A member of a pointer type can point to other types of structure data, and can also point to the structure type data in which it is located. Now, next is a member of the struct data type, which in turn points to the data of the struct data type. In this way, a linked list can be created.
An example of a single-node code is as follows:

#include <stdio.h>
#pragma pack(1)  //字节对齐
struct   data
{
    
    
	int num;
	struct data* next;   //next 是指针变量,指向结构体变量
};

int main()
{
    
    
	struct data  a, b, c, * head, * p; //定义3个结构体变量a,b,c作为链表的结点;
	a.num = 0;  //对结点a的num成员赋值;
	b.num = 1;  //对结点b的num成员赋值; 
	c.num = 2;  //对结点c的num成员赋值;
	head = &a;  //将结点a的起始地址赋值给头指针head;
	a.next = &b; //将结点b的起始地址赋给a结点的next成员;
	b.next = &c; //将结点c的起始地址赋给b结点的next成员;
	c.next = NULL; //c结点的next成员不存放其他结点地址;
	p = head;     //使p指向a结点;
	while (p != NULL)  //输出完c结点后的值为NULL,循环终止;
	{
    
    
		printf("%d\n", p->num);  //输出p指向的结点的数据;
		p = p->next;             //使p指向下一结点;

	}
	return 0;
}

Compilation and running results are as follows:
insert image description here
Multi-node code examples are as follows:

#include <stdio.h>
#pragma pack(1)  //字节对齐
struct   data
{
    
    
	int num;
	struct data* next_1;   //next_1 是指针变量,指向结构体变量
	struct data* next_2;   //next_2 是指针变量,指向结构体变量
};

int main()
{
    
    
	struct data  a, b, c,d,e,f, * head_1,*head_2, * p; //定义3个结构体变量a,b,c作为链表的结点;
	a.num = 0;  //对结点a的num成员赋值;
	b.num = 1;  //对结点b的num成员赋值; 
	c.num = 2;  //对结点c的num成员赋值;
	d.num = 3;  //对结点a的num成员赋值;
	e.num = 4;  //对结点b的num成员赋值; 
	f.num = 5;  //对结点c的num成员赋值;
	head_1 = &a;  //将结点a的起始地址赋值给头指针head_1;
	a.next_1 = &b; //将结点b的起始地址赋给a结点的next_1成员;
	b.next_1 = &c; //将结点c的起始地址赋给b结点的next_1成员;
	c.next_1 = NULL; //c结点的next_1成员不存放其他结点地址;

	head_2 = &d;   //将结点d的起始地址赋值给头指针head_2;
	d.next_2 = &e; //将结点e的起始地址赋给d结点的next_2成员;
	e.next_2 = &f; //将结点f的起始地址赋给e结点的next_2成员;
	f.next_2 = NULL; //f结点的next_2成员不存放其他结点地址

	p = head_1;     //使p指向a结点;
	while (p != NULL)  //输出完c结点后的值为NULL,循环终止;
	{
    
    
		printf("%d\n", p->num);  //输出p指向的结点的数据;
		p = p->next_1;             //使p指向下一结点;

	}
	p = head_2;     //使p指向a结点;
	while (p != NULL)  //输出完c结点后的值为NULL,循环终止;
	{
    
    
		printf("%d\n", p->num);  //输出p指向的结点的数据;
		p = p->next_2;             //使p指向下一结点;

	}
	return 0;
}

Compilation and running results are as follows:
insert image description here

2. Create a simple dynamic linked list

The so-called establishment of a dynamic linked list refers to the establishment of a linked list from scratch during program execution, that is, to open up nodes one by one and input the data of each node, and to establish a front-to-back relationship. Use the form of dynamic memory allocation to allocate space for the required data.
The code example is as follows:

#include <stdio.h>
#include <stdlib.h>
#pragma pack(1)
struct   data
{
    
    
	int num;
	struct data* next;   //next是指针变量,指向结构体变量
};

int main()
{
    
    
	struct data   * head ,* p1,*p2; //定义3个结构体指针变量head,p1,p2用来指向struct data类型数据的;
	head = p1 = p2 = (struct data*)malloc(sizeof(struct data)); //开辟内存动态存储区,把起始地址赋值给 head;
	
	for (int i = 0; i < 3; i++)
	{
    
    
		p1 -> num = i;        //给指针p1指向的结构体成员 num 赋值;
		p2 -> next = p1;      //把指针p1的地址赋值给 指针p2指向的结构体成员指针next;
		p2 = p1;              //把指针p1的地址赋值给 p2
							 /*注意此时指针p1的地址分别赋值给了指针p2和结构体成员指针next*/
		p1 = (struct data*)malloc(sizeof(struct data));  //重新给p1开辟新空间;
	}  //此时进入下一个循环,指针p1、指针p2、当前结构体指针next,向后移动一个sizeof(struct data)单元;
	   //由于未释放内存动态存储区,故结构体与结构体之间使用指针 next 连接了起来。
		//在这个过程中,指针p1 和 指针 p2 的作用就是交换地址,使结构体成员 next 连接到下一个结构体; 
	p2->next = NULL; //当循环结束时,给指针p2指向的结构体成员指针next赋值为0(NULL);
	while (head != NULL)
	{
    
    
		
			printf("%d\n", head->num);  //输出p指向的结点的数据;
			head = head->next;   //使p指向下一结点;
	} 		       
	return 0;
}

After compilation it looks like this:
insert image description here

3. Addition, deletion, modification and query of linked list

1. Linked list query: loop through the required node information, or search according to the known number of nodes, and query the structure data. 2. Linked list
insertion: loop through the required node information, or according to the known How many nodes, when you find the required node, just insert the structure
3. Delete the linked list: loop through the required node information, or according to the known number of nodes, when you find the required node When clicking, delete the structure.
4. Change the linked list: loop through the required node information, or according to the known number of nodes, when the required node is found, change the structure data. The code example is as
follows :

#include <stdio.h>
#include <stdlib.h>

int init(); //初始化结点函数;
int head_add(int da);  //在头的前面增加结点函数;
int body_add(int num, int da);  //在中间增加结点函数;
int tail_add(int da);  //在尾的后面增加结点函数;

int head_dele();  //在头的前面删除结点函数;
int body_dele(int num);  //在中间删除结点函数;
int tail_dele();  //在尾的后面删除结点函数;

int head_change(int da);  //更改头结点函数;
int body_change(int num, int da);  //更改中间结点函数;
int tail_change(int da);  //更改尾结点函数;
void examine(int num);//查结点
void Inquire();//遍历输出
#pragma pack(1)
struct   data
{
    
    
	int num;
	struct data* next;   //next是指针变量,指向结构体变量
};

struct data* head, *tail,* p1 ,* p2,*ptemp,*pt2; //定义3个结构体指针变量head,p1,p2用来指向struct data类型数据的;

int main()
{
    
    
	if (init() == 0)
	{
    
    
		printf("*******************初始化成功!**********************\n");
	}
	head_add(12);  //增加头
	body_add(2,88);//增加中
	tail_add(13);//增加尾
	head_dele(); //删除头
	body_dele(1);//删除中
	tail_dele();//删除尾
	head_change(9);//更改头
	body_change(1,8);//更改中
	tail_change(7); //更改尾
	examine(1); //查询
	return 0;
}

/*************************初始化*****************************/
int init()
{
    
    
	head = p1 = p2 = (struct data*)malloc(sizeof(struct data)); //开辟内存动态存储区,把起始地址赋值给 head;
	for (int i = 0; i < 3; i++)
	{
    
    
		p1->num = i;        //给指针p1指向的结构体成员 num 赋值;
		p2->next = p1;      //把指针p1的地址赋值给 指针p2指向的结构体成员指针next;
		p2 = p1;              //把指针p1的地址赋值给 p2
		/*注意此时指针p1的地址分别赋值给了指针p2和结构体成员指针next*/
		p1 = (struct data*)malloc(sizeof(struct data));  //重新给p1开辟新空间;
	}  //此时进入下一个循环,指针p1、指针p2、当前结构体指针next,向后移动一个sizeof(struct data)单元;
	   //由于未释放内存动态存储区,故结构体与结构体之间使用指针 next 连接了起来。
		//在这个过程中,指针p1 和 指针 p2 的作用就是交换地址,使结构体成员 next 连接到下一个结构体; 
	p2->next = NULL; //当循环结束时,给指针p2指向的结构体成员指针next赋值为0(NULL);
	tail = p2; //保存到尾结点,用于尾结点的增加和删除;
	Inquire();//遍历输出
	return 0;
}

int head_add(int da) //在头的前面增加
{
    
    	
	p1 = (struct data*)malloc(sizeof(struct data));  //重新给p1开辟新空间;
	p1->num = da;     //给新的结点设置数据;
	p1->next = head;  //结构体指针p1的成员指针next指向头指针head;
	head = p1;        //将结构体指针p1内存地址赋值给头指针head;
	printf("********************head_add执行成功!*************************\n");
	Inquire();//遍历输出
	return 0;
}


/*******************
int body_add(int num, int da)
num:表示第几个结点,不能为0,因为0结点是头;
da:表示增加的数据;
*******************/
int body_add(int num,int da ) //在中间增加结点函数;
{
    
    
	struct data* p=head;
	for (int i = 0; i < num; i++)  //获取在几个结点的后面增加结点数据
	{
    
    
		p=p->next;
	}
	p1 = (struct data*)malloc(sizeof(struct data)); //重新给p1开辟新空间;
	p1->num = da;  //给新的结点设置数据;
	p1->next = p->next; //把当前结点指向下一个结点的指针,赋值给结构体指针p1指向的下一个结点的指针;
	p->next = p1;       //然后把结构体p1指针内存地址赋值给当前结点结构体指针指向的下一个结点的指针;
	printf("********************body_add执行成功!*************************\n");
	Inquire();//遍历输出
	return 0;
}

int tail_add(int da) //在尾的后面增加结点函数;
{
    
    
	p1 = (struct data*)malloc(sizeof(struct data));  //重新给p1开辟新空间;
	p1->num = da;          //给指针p1指向的结构体成员 num 赋值;
	p1->next = NULL;       //把指针p1的地址赋值给 指针p2指向的结构体成员指针next;
	tail->next = p1;       //把结构体指针p1赋值给尾结构体指针指向的下一个结点;
	tail = p1;				//然后在把p1赋值给尾部指针;
	printf("********************tail_add执行成功*************************\n");
	Inquire();//遍历输出
	return 0;
}

void Inquire() //遍历输出
{
    
    
	struct data* p = head;
	printf("当前链表中的数据是:");
	while (p != NULL)         //知道结点指向的指针为NULL
	{
    
    
		printf("%d,", p->num);  //输出p指向的结点的数据;
		p = p->next;   //使p指向下一结点;
	}
	printf("\n");
}


int head_dele()  //在头的前面删除结点函数;
{
    
    
	p1 = head;  //把头指针内存地址赋值给p1指针
    head=head->next;  //把头指针指向的下一个结点赋值给head指针	
	free(p1);  //释放p1指针分配的内存空间;
	p1 = NULL;
	printf("********************head_dele执行成功!*************************\n");
	Inquire();//遍历输出
	return 0;
}
int body_dele(int num)  //在中间删除结点函数;
{
    
    
	struct data* p = head;
	for (int i = 0; i < num; i++)  //获取在几个结点的后面增加结点数据
	{
    
    
		p = p->next;
	}
	p1 = p->next;  //把当前结点的下一个结点内存地址赋值给指着p1
	p->next=p->next->next; //把当前结点的下下结点内存地址赋值给下结点内存地址
	free(p1);  //释放p1指针分配的内存空间;
	printf("********************body_dele执行成功!*************************\n");
	Inquire();//遍历输出
	return 0;
}
int tail_dele()  //在尾的后面删除结点函数;
{
    
    	
	struct data* p = head,*pt=head;
	pt = pt->next;
	pt = pt->next;
	while (pt != NULL)      //知道结点指向的指针为NULL
	{
    
    
		p = p->next;   //使p指向下一结点;
		pt = pt->next; //使pt指向下一结点;
	}  //当pt指向NULL时p指向的下一个结点为尾结点前面的一个结点
	p1 = p->next; 
	tail = p;
	free(p1);//释放p1指针分配的内存空间;
	p->next = NULL;
	printf("********************tail_dele执行成功!*************************\n");
	Inquire();//遍历输出
	return 0;
}

int head_change(int da)  //更改头结点函数;
{
    
    
	head->num =da;  //更改头结点的数据	
	printf("********************head_change执行成功!*************************\n");
	Inquire();//遍历输出
	return 0;
}
int body_change(int num, int da)  //更改中间结点函数;
{
    
    
	struct data* p = head;
	for (int i = 0; i < num; i++)  //获取在几个结点的后面增加结点数据
	{
    
    
		p = p->next;
	}
	p->num = da; //更改当前结点的数据
	printf("********************body_change执行成功!*************************\n");
	Inquire();//遍历输出
	return 0;
}
int tail_change(int da)  //更改尾结点函数;
{
    
    
	tail->num = da;       //更改尾结点的数据;
	printf("********************tail_change执行成功!*************************\n");
	Inquire();//遍历输出
	return 0;
}

void examine(int num) //查结点
{
    
    
	struct data* p = head;
	for (int i = 0; i < num; i++)  //获取在几个结点的后面增加结点数据
	{
    
    
		p = p->next;
	}
	printf("************************查询成功!*********************\n");
	printf("当前结点的数据是:%d\n",p->num);
}

Compile and run as follows:
insert image description here

Four. Summary

Linked lists are widely used in data storage.

Guess you like

Origin blog.csdn.net/weixin_44759598/article/details/129757129