Use C language to implement basic operations of singly linked lists (complete code attached)

Introduction:

Whether it is a sequential storage structure or a chained storage structure, when storing elements in memory, not only the relevant information of the element needs to be stored, but also the relationship between the element and other elements needs to be stored. The sequence table we learned before The "innate" physical structure can naturally express the relationship between elements and does not require additional information to express the relationship between elements. For non-sequential storage structures such as chain storage, Additional pointers are needed to represent this relationship.

Single list:

In addition to storing data elements, each node also stores a pointer to the next node.

Characteristics of singly linked list:

Advantages : Does not require large continuous space, easy to change capacity

Disadvantages : No random access, it takes a certain amount of space to store pointers

definition:

typedef struct LNode {
    
    
	int data;
	struct LNode* next;//指针指向下一个节点,指针的类型为节点类型;
}*LinkNode;//声明*LinkNode为结构体指针类型

In addition to the above method, we can also first declare LinkNode as a structure type. When using this type, just define the corresponding variable as a pointer.

Singly linked lists are divided into leading nodes and non-leading nodes. We usually mainly study the leading nodes.

Insert image description here

Initialization operation:

Before all operations, we first need to create an empty singly linked list, then the first thing we need to do is allocate the head node.

void InistLinkNode(LinkNode& L) {
    
    
	L = (LNode*)malloc(sizeof(LNode));//分配头结点
	L->next = NULL;
}

Head insertion method:

"Head insertion method", as the name suggests, is to insert the element after the head node. Inserting it once seems to be no different from what we usually talk about, but inserting it after the head node multiple times is the "first real node", then Will there be a phenomenon where the final stored data is in the opposite order to the order we inserted it?

void InsertLinkNode(LinkNode& L) {
    
    
	LNode* s;
	int x,Length;
	printf("请输入你要插入的元素个数:");
	scanf("%d", &Length);
	printf("请输入你要插入的元素:\n");
	for (int j = 0; j < Length; j++) {
    
    
		s = (LNode*)malloc(sizeof(LNode));//每插入一个元素之前,都需要给它分配节点空间
		scanf("%d", &x);
		s->data = x;
		s->next = L->next;
		L->next = s;
	}

} 

Verify the following through the program:

Insert image description here

Tail insertion method:

"Tail insertion method" as the name suggests is to insert elements to the end of the table, which is our ordinary insertion . So how do we find the position of the end of the table? In a sequence table, we can fully utilize the natural characteristics of its sequential storage structure and find it through subscripts. However, there is no way to do this with a singly linked list. We only have two ways, either looping through it or trying to do it at the end of the table. mark.

So which method is good?

The answer is the second one! The way of loop traversal seems to be no problem if you only insert one element, but if you repeat the loop multiple times, it will undoubtedly increase the time complexity, which is obviously not a good method.

The second method does not have the problem of time complexity.只需要在表尾位置做个标记,使它永远指向表尾即可。

void TailInsertLinkNode(LinkNode& L) {
    
    
	LNode* s,*r;
	int x,Length;
	r = L;//r为表尾指针
	printf("请输入你要插入的元素个数:");
	scanf("%d", &Length);
	printf("请输入你要插入的元素:\n");
	for (int j = 0; j < Length; j++) {
    
    
		s = (LNode*)malloc(sizeof(LNode));
		scanf("%d", &x);
		s->data = x;
		r->next = s;
		r = s;//s为当前的表尾指针,将他的值赋值给r----使r永远指向表尾
	}
	printf("\n");
	r->next = NULL;
}

Delete the i-th element:

Since we want to delete an element, first we need to 保证这个元素是非NULL, and secondly, we also need to guarantee 它前面的那个节点也是非NULL, why? Because if the element is deleted from the linked list, the connection between the subsequent element and the previous sublist can only be achieved if the previous node is non-NULL.

void DeleteLinkNode(LinkNode& L) {
    
    
	int x, j = 0,e;
	printf("请输入你要删除的元素位序:\n");
	scanf("%d", &x);
	LNode*p = L;
	while (p != NULL && j < x - 1) {
    
    //寻找要删除元素前的元素
		p = p->next;
		j++;
	}
	if (p == NULL)
	{
    
    
		printf("不存在我们要删除的元素!");
	}
	if (p->next == NULL)//判断该要删除的节点是否为NULL
	{
    
    
		printf("不存在我们要删除的元素!");
	}
	LNode* q = p->next;//q为我们要删除的节点
	e = q->data;
	p->next = q->next;
	free(q);//需要及时的将删除了的元素空间进行释放
}

其他的基本操作都是很常规化的,这里就不单独的进行解释了,需要注意的点,我会在文章结尾部分的完整代码的注释中展出。

Insert at position i:

void IncreaseLinkNode(LinkNode& L) {
    
    
	printf("请输入你要插入的元素和位序:(元素和位序之间用逗号隔开)\n");
	int x, j = 0, e;
	scanf("%d,%d",&e, &x);
	LNode* s = L, * r= (LNode*)malloc(sizeof(LNode));
	while (j < x-1  && s != NULL) {
    
    
		j++;
		s = s->next;
	}
	r->data = e;
	r->next = s->next;
	s->next = r;
}

如下所示的代码顺序不能发生改变,否则会出现无法和后面的节点;

r->next = s->next;
s->next = r;

The complete code is as follows:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode {
    
    
	int data;
	struct LNode* next;
}*LinkNode;
//初始化
void InistLinkNode(LinkNode& L) {
    
    
	L = (LNode*)malloc(sizeof(LNode));//分配头结点
	L->next = NULL;
}
//头插法
void InsertLinkNode(LinkNode& L) {
    
    
	LNode* s;
	int x,Length;
	printf("请输入你要插入的元素个数:");
	scanf("%d", &Length);
	printf("请输入你要插入的元素:\n");
	for (int j = 0; j < Length; j++) {
    
    
		s = (LNode*)malloc(sizeof(LNode));
		scanf("%d", &x);
		s->data = x;
		s->next = L->next;
		L->next = s;
	}
} 
//尾插法
void TailInsertLinkNode(LinkNode& L) {
    
    
	LNode* s,*r;
	int x,Length;
	r = L;
	printf("请输入你要插入的元素个数:");
	scanf("%d", &Length);
	printf("请输入你要插入的元素:\n");
	for (int j = 0; j < Length; j++) {
    
    
		s = (LNode*)malloc(sizeof(LNode));
		scanf("%d", &x);
		s->data = x;
		r->next = s;
		r = s;
	}
	printf("\n");
	r->next = NULL;
}
//输出单链表
void PrintLinkNode(LinkNode& L)
{
    
    
	LNode* s=L->next;
	printf("单链表元素如下:\n");
	while (s != NULL) {
    
    
		printf("%d", s->data);
		s =s->next;
	}
	printf("\n");
}
//求线性表长度
void lengthLinkNode(LinkNode& L)
{
    
    
	LNode* s = L->next;
	int n=0;
	while (s != NULL) {
    
    
		n++;
		s = s->next;
	}
	printf("单链表长度为:%d",n);
	printf("\n");
}
//取第i个元素
void GetElemLinkNode(LinkNode& L) {
    
    
	printf("请输入你要查找的元素位序:\n");
	int i, j = 0;
	LNode* s=L;
	scanf("%d", &i);
	while (j < i && s != NULL) {
    
    
		j++;
		s = s->next;
	}
	if (s == NULL) {
    
    
		printf("不存在我们要查找的元素!");
	}
	else {
    
    
		printf("元素位序为%d的元素是%d",i, s->data);
	}
	printf("\n");
}
//删除第i个元素
void DeleteLinkNode(LinkNode& L) {
    
    
	int x, j = 0,e;
	printf("请输入你要删除的元素位序:\n");
	scanf("%d", &x);
	LNode*p = L;
	while (p != NULL && j < x - 1) {
    
    
		p = p->next;
		j++;
	}
	if (p == NULL)
	{
    
    
		printf("不存在我们要删除的元素!");
	}
	if (p->next == NULL)
	{
    
    
		printf("不存在我们要删除的元素!");
	}
	LNode* q = p->next;
	e = q->data;
	p->next = q->next;
	free(q);
}
//在第i个位置插入
void IncreaseLinkNode(LinkNode& L) {
    
    
	printf("请输入你要插入的元素和位序:(元素和位序之间用逗号隔开)\n");
	int x, j = 0, e;
	scanf("%d,%d",&e, &x);
	LNode* s = L, * r= (LNode*)malloc(sizeof(LNode));
	while (j < x-1  && s != NULL) {
    
    
		j++;
		s = s->next;
	}
	r->data = e;
	r->next = s->next;
	s->next = r;
}
//查找位序
void SearchLinkNode(LinkNode &L) {
    
    
	int x,j=1;
	LNode* p=L->next;
	printf("请输入你要查找的元素:\n");
	scanf("%d", &x);
	while (p != NULL && p->data != x) {
    
    
		p = p->next;
		j++;
	}
	if (p == NULL) {
    
    
		printf("您要查找的元素不存在!");
	}
	else {
    
    
		printf("你要查找的元素%d的位序为%d", x, j);
	}
}
int main() {
    
    
	LinkNode L;
	InistLinkNode(L);
	/*InsertLinkNode(L);*/
	TailInsertLinkNode(L);
	PrintLinkNode(L);
	lengthLinkNode(L);
	GetElemLinkNode(L);
	IncreaseLinkNode(L);
	PrintLinkNode(L);
	DeleteLinkNode(L);
	PrintLinkNode( L);
	SearchLinkNode(L);
}

Output:

Insert image description here

Guess you like

Origin blog.csdn.net/m0_64365419/article/details/127464995