C language linked list - addition, deletion, modification and search

Table of contents

1. The concept of linked list

1.1 What is a linked list:

2. The difference between linked lists and arrays:

2.1 Advantages and disadvantages of linked lists and arrays:

        2.1.1 Advantages and Disadvantages of Arrays:

        2.1.2 Advantages and disadvantages of linked lists:

3. Static addition and dynamic traversal of linked lists:

4. Count the number of linked list nodes and search the linked list

5. Linked list insertion

5.1 Insert a new node from behind the specified node in the linked list:

5.2 Insert a new node from the front of the specified node in the linked list:

6. Delete the specified node from the linked list

7. Change the data of the specified node in the linked list

8. Dynamically create linked lists

8.1 Dynamically create the head insertion method of the linked list:

8.2 Dynamically create tail insertion method of linked list:

9. Add, delete, modify and check linked list


1. The concept of linked list

1.1 What is a linked list:

  • A linked list is a data structure and an idea of ​​data storage .

2. The difference between linked lists and arrays:

  • Arrays allocate memory statically, and linked lists allocate memory dynamically.

  • Arrays are continuous in memory, linked lists are discontinuous

  • Arrays are positioned using subscripts, and linked lists locate elements through traversal.

  • Array insertion and deletion require moving other elements, and linked list insertion or deletion does not require moving other elements.

2.1 Advantages and disadvantages of linked lists and arrays:

2.1.1 Advantages and Disadvantages of Arrays:

  • Random access is relatively strong, and you can quickly locate it through subscripts.

  • Fast search speed

  • Insertion and deletion are inefficient and require moving other elements.

  • It will cause a waste of memory. Because the memory is continuous, the size of the memory must be specified when applying for an array. If it is inappropriate, it will cause a waste of memory.

  • The memory space requirement is high. To create an array, you must have enough continuous memory space.

  • The size of the array is fixed and is specified when the array is created, and cannot be dynamically expanded.

2.1.2 Advantages and disadvantages of linked lists:

  • Insertion and deletion are very efficient. You only need to change the pointing of the pointer to insert and delete.

  • The memory utilization rate is high and memory will not be wasted. Small discontinuous spaces in the memory can be used, and space is created only when needed. The size is not fixed and the expansion is very flexible.

  • The search efficiency is low because the linked list is traversed backwards from the first node.

#include <stdio.h>

struct Test
{
        int data;			//存放的数据
        struct Test *nest;	//下一个节点的地址
};

int main()
{
        int i;
        int len;
        int arr[3] = {1,2,3};

        len = sizeof(arr)/sizeof(arr[0]);
        for(i=0; i<len; i++){
                printf("%d ",arr[i]);
        }
        putchar('\n');

        struct Test t1 = {1,NULL};
        struct Test t2 = {2,NULL};
        struct Test t3 = {3,NULL};

        t1.nest = &t2;
        t2.nest = &t3;

        printf("use t1 to print three nums\n");
        printf("%d %d %d\n",t1.data,t1.nest->data,t1.nest->nest->data);
        return 0;
}
/*
CLC@Embed_Learn:~/lianbiao$ gcc link.c -o link
CLC@Embed_Learn:~/lianbiao$ ./link
1 2 3 
use t1 to print three nums
1 2 3
*/

3. Static addition and dynamic traversal of linked lists:

#include <stdio.h>

struct Test
{
        int data;			//数据
        struct Test *nest;	//指向同类型的指针
};

//链表动态遍历输出
void printLink(struct Test *hand)
{
        struct Test *point;	

        point = hand;						//point指向链表头
        while(point != NULL){				//遍历到链表尾巴NULL时,循环结束
                printf("%d ",point->data);	//输出当前节点data的值
                point = point->nest;		//point指向下一个节点
        }
        putchar('\n');
};

int main()
{
    	//对所有的节点进行赋值
        struct Test t1 = {1,NULL};	
        struct Test t2 = {2,NULL};
        struct Test t3 = {3,NULL};
        struct Test t4 = {4,NULL};

        t1.nest = &t2;	//将节点t2的地址赋值给t1节点的nest
        t2.nest = &t3;	//将节点t3的地址赋值给t2节点的nest
        t3.nest = &t4;	//将节点t4的地址赋值给t3节点的nest

        printf("use t1 to ptint four nums\n");
        printLink(&t1);	//把链表头传到printLink函数中去
        return 0;
}
/*
CLC@Embed_Learn:~/lianbiao$ gcc link1.c -o link1
CLC@Embed_Learn:~/lianbiao$ ./link1
use t1 to ptint four nums
1 2 3 4 

*/

4. Count the number of linked list nodes and search the linked list

#include <stdio.h>

struct Test
{
	int data;			//数据
	struct Test *nest;	//指向同类型的指针
};

//链表动态遍历输出
void printLink(struct Test *hand)
{
	struct Test *point;
	
	point = hand;					//point指向链表头		
	while(point != NULL){			//遍历到链表尾巴NULL时,循环结束
		printf("%d ",point->data);	//输出当前节点data的值
		point = point->nest;		//point指向下一个节点
	}
	putchar('\n');
}

//统计链表节点个数函数
int getLinkTotalNodeNum(struct Test *hand)
{
	int cnt = 0;
	struct Test *point;
	
	point = hand;					//point指向链表头	
	while(point != NULL){			//遍历到链表尾巴NULL时,循环结束
		cnt++;
		point = point->nest;		//point指向下一个节点
	}
	return cnt;
}

//查找链表函数
int searchLink(struct Test *hand, int data)
{
	struct Test *point;
	
	point = hand;					//point指向链表头	
	while(point != NULL){			//遍历到链表尾巴NULL时,循环结束
		if(point->data == data){	//如果当前节点的数据和输入的数据一样
			return 1;				//找到就返回1
		}
		point = point->nest;		//point指向下一个节点
	}
	return 0;						//没有找到就返回0
}

int main()
{
	struct Test t1 = {1,NULL};
	struct Test t2 = {2,NULL};
	struct Test t3 = {3,NULL};
	struct Test t4 = {4,NULL};
	struct Test t5 = {5,NULL};
	
	t1.nest = &t2;		//将节点t2的地址赋值给t1节点的nest
	t2.nest = &t3;		//将节点t3的地址赋值给t2节点的nest
	t3.nest = &t4;		//将节点t4的地址赋值给t3节点的nest
	t4.nest = &t5;		//将节点t5的地址赋值给t4节点的nest
	
	printf("链表动态输出:\n");
	printLink(&t1);		//把链表头传到printLink函数中去
	
	int ret = getLinkTotalNodeNum(&t1);
	printf("链表的节点个数是:%d\n",ret);
	
	ret = searchLink(&t1,1);	//函数返回最终结果
	if(ret == 0){
		printf("没有找到1\n");
	}else{
		printf("找到1了\n");
	}
	
	ret = searchLink(&t1,8);	//函数返回最终结果
	if(ret == 0){
		printf("没有找到8\n");
	}else{
		printf("找到8了\n");
	}
	return 0;
}
/*
E:\code\一阶段C语言\链表>gcc demo_lb_bianli.c

E:\code\一阶段C语言\链表>a.exe
链表动态输出:
1 2 3 4 5
链表的节点个数是:5
找到1了
没有找到8
*/

5. Linked list insertion

  • There are two ways to insert into a linked list:

  • The first one: Insert a new node from behind the specified node

  • Second type: Insert a new node from the front of the specified pointing point

5.1 Insert a new node from behind the specified node in the linked list:

#include <stdio.h>

struct Test
{
	int data;			//数据
	struct Test *nest;	//指向同类型的指针
};

//链表动态遍历输出
void printLink(struct Test *hand)
{
	struct Test *point;
	
	point = hand;					//point指向链表头		
	while(point != NULL){			//遍历到链表尾巴NULL时,循环结束
		printf("%d ",point->data);	//输出当前节点data的值
		point = point->nest;		//point指向下一个节点
	}
	putchar('\n');
}

//从指定节点后方插入新节点
int insertFromBehind(struct Test *hand, int data, struct Test *new)
{
	struct Test *p = hand;
	
	while(p != NULL){
		if(p->data == data){	//判断当前节点是不是指定节点
			new->nest = p->nest;//把新节点的next指向指定节点的下一个节点(这边要注意顺序不能换,否则链表会断掉)
			p->nest = new;		//再把指定节点的next指向新节点
			return 1;
		}
		p = p->nest;			//p指向下一节点
	}
	return 0;
}

int main()
{
    struct Test *hand = NULL;
    //定义结构体变量,作为节点,给节点赋值
	struct Test t1 = {1,NULL};
	struct Test t2 = {2,NULL};
	struct Test t3 = {3,NULL};
	struct Test t4 = {4,NULL};
	struct Test t5 = {5,NULL};
	
	t1.nest = &t2;		//将节点t2的地址赋值给t1节点的nest
	t2.nest = &t3;		//将节点t3的地址赋值给t2节点的nest
	t3.nest = &t4;		//将节点t4的地址赋值给t3节点的nest
	t4.nest = &t5;		//将节点t5的地址赋值给t4节点的nest
    
    hand = &t1;
    struct Test new = {100,NULL};	//定义一个新节点
	
	printf("链表动态输出:\n");
	printLink(hand);		//把链表头传到printLink函数中去

    int ret = insertFromBehind(hand, 3, &new);	//把链表头,要插入的位置,和新节点的地址传递过去
	if(ret == 1){
		printf("插入成功!\n");
	}else{
		printf("插入失败!\n");
	}
	
	printLink(hand);	//把链表头传过去,打印链表
	return 0;
}
/*
E:\code\一阶段C语言\链表>gcc demo_指定节点后方插入新节点.c

E:\code\一阶段C语言\链表>a.exe
链表动态遍历:
1 2 3 4 5
插入成功!
1 2 3 100 4 5
*/

5.2 Insert a new node from the front of the specified node in the linked list:

If you want to insert a new node before the specified node, you need to consider two situations:

  1. Insert new node before first node

  2. Insert a new node before the specified node in the middle

#include <stdio.h>

struct Test
{
	int data;			//数据
	struct Test *nest;	//指向同类型的指针
};

//链表动态遍历输出
void printLink(struct Test *hand)
{
	struct Test *p = hand;		//p指向链表头
						
	while(p != NULL){			//遍历到链表尾巴NULL时,循环结束
		printf("%d ",p->data);	//输出当前节点data的值
		p = p->nest;			//p指向下一个节点
	}
	putchar('\n');
}

//链表在指定节点前方插入新节点
struct Test* insertFromfront(struct Test *hand, int data, struct Test *new)
{
	struct Test *p = hand;
	//在头节点插入(链表头会改变)
	if(p->data == data){//判断指定的节点是不是头节点
		new->nest = p;	//让新节点的next指向p
		printf("第一个节点前插入成功,链表头发生改变!\n");
		return new;		//现在new是新的链表头,return到main函数
	}
	//在中间指定节点前插入
	while(p->nest != NULL){			//因为这里是从中间节点插入,所以会从第二个节点开始遍历链表,直到链表尾NULL时停止
		if(p->nest->data == data){	//判断当前节点是不是指定节点
			new->nest = p->nest;	//让要插入新节点的next指向p->next(就是当前节点的下一个节点)
			p->nest = new;			//在让当前节点next指向要插入的新节点new
			printf("插入成功!\n");
			return hand;			//把链表头return回main函数
		}
		p = p->nest;				//使p指向下一节点
	}
	printf("插入失败!\n");
	return hand;
}

int main()
{
	struct Test *hand = NULL;
	
	 //定义结构体变量,作为节点,给节点赋值
	struct Test t1 = {1,NULL};
	struct Test t2 = {2,NULL};
	struct Test t3 = {3,NULL};
	struct Test t4 = {4,NULL};
	struct Test t5 = {5,NULL};
	
	t1.nest = &t2;	//将节点t2的地址赋值给t1节点的nest
	t2.nest = &t3;	//将节点t3的地址赋值给t2节点的nest
	t3.nest = &t4;	//将节点t4的地址赋值给t3节点的nest
	t4.nest = &t5;	//将节点t5的地址赋值给t4节点的nest
	
	hand = &t1;					//把链表头的地址赋值给hand
	printf("动态输出链表:\n");
	printLink(hand);			//把链表头传过去,打印链表
	
	struct Test new = {100,NULL};//创建一个新节点new
	
	hand = insertFromfront(hand,1,&new);//把链表头,要插入的位置,和新节点new的地址传过去,返回链表头
	printf("在第一个节点前插入一个新节点:\n");
	printLink(hand);
	
	struct Test new2 = {200,NULL};//创建一个新节点new2
	
	hand = insertFromfront(hand,2,&new2);//把链表头,要插入的位置,和新节点new的地址传过去,返回链表头
	printf("在链表中间指定节点前插入一个新节点:\n");
	printLink(hand);
	
	return 0;
}
/*
E:\code\一阶段C语言\链表>gcc demo_指定节点前方插入新节点.c

E:\code\一阶段C语言\链表>a.exe
动态输出链表:
1 2 3 4 5
第一个节点前插入成功,链表头发生改变!
在第一个节点前插入一个新节点:
100 1 2 3 4 5
插入成功!
在链表中间指定节点前插入一个新节点:
100 1 200 2 3 4 5
*/

6. Delete the specified node from the linked list

  • Two situations in which the specified node is deleted from the linked list:

  1. Determine whether the node to be deleted is the first node. If it is the first node, directly change the head of the linked list so that the second node becomes the new head of the linked list.

  2. If the node to be deleted is not the first node, pass the nest of the node before the node to be deleted to the node to be deleted, and then point to the node next to the node to be deleted.

  • Now the linked list is created statically. If the linked list is created dynamically, remember to release the memory of the deleted node through the free function to prevent memory leaks.

#include <stdio.h>

struct Test
{
	int data;			//数据
	struct Test *nest;	//指向同类型的指针
};

//链表动态遍历输出
void printLink(struct Test *hand)
{
	struct Test *p = hand;		//p指向链表头
						
	while(p != NULL){			//遍历到链表尾巴NULL时,循环结束
		printf("%d ",p->data);	//输出当前节点data的值
		p = p->nest;			//p指向下一个节点
	}
	putchar('\n');
}

//链表删除指定节点
struct Test* deleteNode(struct Test *hand, int data)
{
	struct Test *p = hand;
	//删除第一个节点
	if(p->data == data){				//判断要删除的节点是不是头节点
		p = p->nest;					//让p指向下一个节点
		printf("成功删除第一个节点,链表头发生改变!\n");
		return p;						//把新的链表头return回去
	}
	//删除其他节点
	while(p->nest != NULL){				//从第二个节点开始遍历链表
		if(p->nest->data == data){		//判断当前节点是不是要删除的节点
			p->nest = p->nest->nest;	//把要删除节点的前一个节点的next越过要删除的节点,然后指向要删除节点的下一个节点
			printf("成功删除指定节点!\n");
			return hand;				//把链表头return回去
		}
		p = p->nest;					//p指向下一个节点
	}
    return hand;
}

int main()
{
	struct Test *hand = NULL;
	
	 //定义结构体变量,作为节点,给节点赋值
	struct Test t1 = {1,NULL};
	struct Test t2 = {2,NULL};
	struct Test t3 = {3,NULL};
	struct Test t4 = {4,NULL};
	struct Test t5 = {5,NULL};
	
	t1.nest = &t2;	//将节点t2的地址赋值给t1节点的nest
	t2.nest = &t3;	//将节点t3的地址赋值给t2节点的nest
	t3.nest = &t4;	//将节点t4的地址赋值给t3节点的nest
	t4.nest = &t5;	//将节点t5的地址赋值给t4节点的nest
	
	hand = &t1;					//把链表头的地址赋值给hand
	printf("动态输出链表:\n");
	printLink(hand);			//把链表头传过去,打印链表
	
	hand = deleteNode(hand,3);	//把链表头,和要删除第几个节点传过去
	printf("链表动态输出:\n");
	printLink(hand);			//把链表头传过去,打印链表
	return 0;
}
/*
E:\code\一阶段C语言\链表>gcc demo_链表删除指定节点.c

E:\code\一阶段C语言\链表>a.exe
链表动态输出:
1 2 3 4 5
成功删除第一个节点,链表头发生改变!
链表动态输出:
2 3 4 5

E:\code\一阶段C语言\链表>gcc demo_链表删除指定节点.c

E:\code\一阶段C语言\链表>a.exe
链表动态输出:
1 2 3 4 5
成功删除指定节点!
链表动态输出:
1 2 4 5

E:\code\一阶段C语言\链表>gcc demo_链表删除指定节点.c

E:\code\一阶段C语言\链表>a.exe
链表动态输出:
1 2 3 4 5
成功删除指定节点!
链表动态输出:
1 2 3 4

E:\code\一阶段C语言\链表>gcc demo_链表删除指定节点.c

E:\code\一阶段C语言\链表>a.exe
链表动态输出:
1 2 3 4 5
成功删除指定节点!
链表动态输出:
1 2 4 5
*/

7. Change the data of the specified node in the linked list

#include <stdio.h>

struct Test
{
	int data;			//数据
	struct Test *nest;	//指向同类型的指针
};

//链表动态遍历输出
void printLink(struct Test *hand)
{
	struct Test *p = hand;		//p指向链表头
						
	while(p != NULL){			//遍历到链表尾巴NULL时,循环结束
		printf("%d ",p->data);	//输出当前节点data的值
		p = p->nest;			//p指向下一个节点
	}
	putchar('\n');
}

//改变链表指定节点的数据
int gaiLink(struct Test *hand, int data, int newData)
{
	struct Test *p = hand;
	
	while(p != NULL){
		if(p->data == data){		//找到指定节点
			p->data = newData;		//改变指定节点的数据
			return 1;
		}
		p = p->nest;
	}
	return 0;
}

int main()
{
	int newData;	//要改变的数据
	int node;		//指定节点
	struct Test *hand = NULL;
	
	 //定义结构体变量,作为节点,给节点赋值
	struct Test t1 = {1,NULL};
	struct Test t2 = {2,NULL};
	struct Test t3 = {3,NULL};
	struct Test t4 = {4,NULL};
	struct Test t5 = {5,NULL};
	
	t1.nest = &t2;	//将节点t2的地址赋值给t1节点的nest
	t2.nest = &t3;	//将节点t3的地址赋值给t2节点的nest
	t3.nest = &t4;	//将节点t4的地址赋值给t3节点的nest
	t4.nest = &t5;	//将节点t5的地址赋值给t4节点的nest
	
	hand = &t1;					//把链表头的地址赋值给hand
	printf("动态输出链表:\n");
	printLink(hand);			//把链表头传过去,打印链表
	
	printf("请输入你要改那个节点的数据:\n");
	scanf("%d",&node);
	printf("请输入你要改的数据:\n");
	scanf("%d",&newData);
	
	int ret = gaiLink(hand,node,newData);//把链表头,指定节点和要改变的数据传过去
	if(ret == 1){
		printf("数据改变成功!\n");
	}else{
		printf("数据改变失败!\n");
	}
	printf("数据改变之后输出链表:\n");
	printLink(hand);
	return 0;
}
/*
E:\code\一阶段C语言\链表>gcc demo_改变链表指定节点的数据.c

E:\code\一阶段C语言\链表>a.exe
链表动态遍历输出:
1 2 3 4 5
请输入你要改那个节点的数据:
2
请输入你要改的数据:
100
数据改变成功!
数据改变之后输出链表:
1 100 3 4 5
*/

8. Dynamically create linked lists

  • There are two ways to dynamically create a linked list:

  1. Head insertion method

  2. tail insertion method

8.1 Dynamically create the head insertion method of the linked list:

  • There is no linked list at the beginning, and we need to create it dynamically: we dynamically create a new node. If head is NULL, then let our new node be used as the head of the linked list. Each time a new node is created, it is inserted before the head of the linked list, so that the new node As the head of the linked list

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

struct Test
{
	int data;			//数据
	struct Test *nest;	//指向同类型的指针
};

//链表动态遍历输出
void printLink(struct Test *head)
{
	struct Test *p = head;		//p指向链表头
						
	while(p != NULL){			//遍历到链表尾巴NULL时,循环结束
		printf("%d ",p->data);	//输出当前节点data的值
		p = p->nest;			//p指向下一个节点
	}
	putchar('\n');
}

//动态创建链表之头插法
struct Test* insertFromHead(struct Test *head, struct Test *new)
{
	if(head == NULL){		//当没有链表的时候
		head = new;			//创建的第一个节点当作链表头
	}else{					//如果链表有其他节点存在
		new->nest = head;	//创建的新节点的nest指向后面的节点
		head = new;			//新节点当作链表头
	}
	return head;			//return链表头
}

//动态创建链表
struct Test* creatLink(struct Test *head)
{
	struct Test *new;
	
	while(1){
		new = (struct Test *)malloc(sizeof(struct Test));	//创建一个新节点
		new->nest = NULL;									//新节点的nest指向NULL,否则遍历输出链表会出错
		printf("创建新节点完成,请输入新节点的数据:\n");	
		scanf("%d",&(new->data));							//输入新节点的数据
		if(new->data == 0){									//判断输入新节点的数据是否为0
			printf("0 quit\n");
			free(new);										//释放节点数据为0的节点
			return head;									//停止创建链表,return链表头
		}
		head = insertFromHead(head,new);					//新节点当作链表头
	}
	return head;											//return链表头
}

int main()
{
	struct Test *head = NULL;
	
	head = creatLink(head);					//head指向链表头
	printf("动态创建链表完成,动态输出链表:\n");
	printLink(head);
    
    struct Test t1 = {100,NULL};
	head = insertFromHead(head,&t1);
	printf("随时可以将创建的新节点通过头插法插入到链表中:\n");
	printLink(head);
	return 0;
}
/*
E:\code\一阶段C语言\链表>gcc demo_链表动态创建之头插法.c

E:\code\一阶段C语言\链表>a.exe
创建新节点完成,请输入新节点的数据:
1
创建新节点完成,请输入新节点的数据:
2
创建新节点完成,请输入新节点的数据:
3
创建新节点完成,请输入新节点的数据:
0
0 quit
动态创建链表完成,动态输出链表:
3 2 1
随时可以将创建的新节点通过头插法插入到链表中:
100 3 2 1
*/

8.2 Dynamically create tail insertion method of linked list:

  • There is no linked list at the beginning, we need to create it dynamically: we dynamically create a new node, the first node created is used as the head of the linked list, and then each new node created is inserted into the nest of the last node of the linked list.

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

struct Test
{
	int data;			//数据
	struct Test *nest;	//指向同类型的指针
};

//链表动态遍历输出
void printLink(struct Test *head)
{
	struct Test *p = head;		//p指向链表头
						
	while(p != NULL){			//遍历到链表尾巴NULL时,循环结束
		printf("%d ",p->data);	//输出当前节点data的值
		p = p->nest;			//p指向下一个节点
	}
	putchar('\n');
}

//动态创建链表之头插法
struct Test* insertBehind(struct Test *head, struct Test *new)
{
	struct Test *p = head;
	
	if(head == NULL){	//当没有链表的时候
		head = new;		//创建的第一个节点当作链表头
		return head;	//return链表头
	}
	
	while(p->nest != NULL){	//遍历到最后一个节点
		p = p->nest;		//p指向下一个节点
	}
	p->nest = new;			//创建的新节点插入到最后一个节点的nest中
	
	return head;			//return链表头
}

//动态创建链表
struct Test* creatLink(struct Test *head)
{
	struct Test *new;
	
	while(1){
		new = (struct Test *)malloc(sizeof(struct Test));	//创建一个新节点
		new->nest = NULL;									//新节点的nest指向NULL,否则遍历输出链表会出错
		printf("创建新节点完成,请输入新节点的数据:\n");
		scanf("%d",&(new->data));							//输入新节点的数据
		if(new->data == 0){									//判断输入新节点的数据是否为0
			printf("0 quit\n");
			free(new);										//释放节点数据为0的节点
			return head;									//停止创建链表,return链表头
		}
		head = insertBehind(head,new);						//每次动态创建的新节点通过尾插法插入到链表中
	}
	return head;											//return链表头
}

int main()
{
	struct Test *head = NULL;
	
	head = creatLink(head);
	printf("动态创建链表完成,动态输出链表:\n");
	printLink(head);
	
	struct Test t1 = {100,NULL};
	head = insertBehind(head,&t1);
	printf("随时可以将创建的新节点通过尾插法插入到链表中:\n");
	printLink(head);
	return 0;
}
/*
E:\code\一阶段C语言\链表>gcc demo_链表动态创建之尾插法.c -g

E:\code\一阶段C语言\链表>a.exe
创建新节点完成,请输入新节点的数据:
1
创建新节点完成,请输入新节点的数据:
2
创建新节点完成,请输入新节点的数据:
3
创建新节点完成,请输入新节点的数据:
0
0 quit
动态创建链表完成,动态输出链表:
1 2 3
随时可以将创建的新节点通过尾插法插入到链表中:
1 2 3 100
*/

9. Add, delete, modify and check linked list

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

struct Test
{
	int data;
	struct Test *nest;
};

//动态遍历链表
void printLink(struct Test *head)
{
	struct Test *p = head;
	
	while(p != NULL){
		printf("%d ",p->data);
		p = p->nest;
	}
	putchar('\n');
}

//动态创建链表之尾插法
struct Test* insertFromBehind(struct Test *head, struct Test *new)
{
	struct Test *p = head;
	
	if(head == NULL){
		head = new;
		return new;
	}
	
	while(p->nest != NULL){
		p = p->nest;
	}
	p->nest = new;
	
	return head;
}

//动态创建链表
struct Test* creatLink(struct Test *head)
{
	struct Test *new;
	
	while(1){
		new = (struct Test *)malloc(sizeof(struct Test));
		new->nest = NULL;
		printf("动态创建新节点完成,请输入新节点data的数据:\n");
		scanf("%d",&(new->data));
		if(new->data == 0){
			printf("0 quit\n");
			free(new);
			return head;
		}
		head = insertFromBehind(head,new);
	}
	return head;
}

//统计链表节点个数
int getLinkTotalNodeNum(struct Test *head)
{
	struct Test *p = head;
	int cnt = 0;
	
	while(p != NULL){
		cnt++;
		p = p->nest;
	}
	return cnt;
}

//查找链表节点
int searchLink(struct Test *head, int data)
{
	struct Test *p = head;
	
	while(p != NULL){
		if(p->data == data){
			return 1;
		}
		p = p->nest;
	}
	return 0;
}

//在指定节点后面插入新节点
int insertFromBehind2(struct Test *head, int data, struct Test *new)
{
	struct Test *p = head;
	
	while(p != NULL){
		if(p->data == data){
			new->nest = p->nest;
			p->nest = new;
			return 1;
		}
		p = p->nest;
	}
	return 0;
}

//在指定节点前方插入新节点
struct Test* insertFromfront(struct Test *head, int data, struct Test *new)
{
	struct Test *p = head;
	
	if(p->data == data){
		new->nest = p;
		printf("在第%d个节点前面插入新节点OK,链表头发生变化!\n",data);
		return new;
	}
	
	while(p->nest != NULL){
		if(p->nest->data == data){
			new->nest = p->nest;
			p->nest = new;
			printf("在指定节点%d前面插入新节点OK\n",data);
			return head;
		}
		p = p->nest;
	}
	return head;
}

//链表删除指定节点
struct Test* deleteNode(struct Test *head, int data)
{
	struct Test *p = head;
	
	if(p->data == data){
		head = p->nest;
		free(p);
		printf("链表的第%d个节点删除完毕,链表头发生变化!\n",data);
		return head;
	}
	
	while(p->nest != NULL){
		if(p->nest->data == data){
			p->nest = p->nest->nest;
			printf("链表的第%d个节点删除完毕!\n",data);
			return head;
		}
		p = p->nest;
	}
	return head;
}

//修改链表指定节点的数据
int gaiLink(struct Test *head, int data, int newData)
{
	struct Test *p = head;
	
	while(p != NULL){
		if(p->data == data){
			p->data = newData;
			return 1;
		}
		p = p->nest;
	}
	return 0;
}

int main()
{
	int cmd;
	int newData;
	struct Test *head = NULL;
	
	head = creatLink(head);
	printf("链表动态创建完成,遍历输出:\n");
	printLink(head);
	
	int ret = getLinkTotalNodeNum(head);
	printf("链表的节点个数:%d\n",ret);
	
	printf("请输入你要查找哪一个节点数据:\n");
	scanf("%d",&cmd);
	ret = searchLink(head,cmd);
	if(ret == 1){
		printf("可以找到:%d\n",cmd);
	}else{
		printf("找不到%d\n",cmd);
	}
	printf("请输入你要查找哪一个节点数据:\n");
	scanf("%d",&cmd);
	ret = searchLink(head,cmd);
	if(ret == 1){
		printf("可以找到:%d\n",cmd);
	}else{
		printf("找不到%d\n",cmd);
	}
	
	struct Test new = {100,NULL};
	printf("请输入你要插在哪一个节点后面:\n");
	scanf("%d",&cmd);
	ret = insertFromBehind2(head,cmd,&new);
	if(ret == 1){
		printf("在指定节点%d后面插入新节点OK\n",cmd);
	}else{
		printf("在指定节点%d后面插入新节点失败\n",cmd);
	}
	printf("在指定节点后面插入新节点后遍历输出链表:\n");
	printLink(head);
	
	struct Test new2 = {200,NULL};
	printf("请输入你要插在哪一个节点的前面:\n");
	scanf("%d",&cmd);
	head = insertFromfront(head,cmd,&new2);
	printf("链表在指定节点前方插入新节点OK,遍历输出:\n");
	printLink(head);
	
	printf("请输入你要删除哪一个节点:\n");
	scanf("%d",&cmd);
	head = deleteNode(head,cmd);
	printf("链表删除指定节点后,输出链表:\n");
	printLink(head);
	
	printf("请输入你要改哪一个节点data的数据:\n");
	scanf("%d",&cmd);
	printf("请输入要更改的数据:\n");
	scanf("%d",&newData);
	ret = gaiLink(head,cmd,newData);
	if(ret == 1){
		printf("指定节点的数据修改成功!\n");
	}else{
		printf("指定节点的数据修改失败!\n");
	}
	printf("链表修改指定节点data的数据后,遍历输出链表:\n");
	printLink(head);
	return 0;
}
/*
E:\code\一阶段C语言\链表>gcc demo_链表.c -g

E:\code\一阶段C语言\链表>a.exe
动态创建新节点完成,请输入新节点data的数据:
1
动态创建新节点完成,请输入新节点data的数据:
2
动态创建新节点完成,请输入新节点data的数据:
3
动态创建新节点完成,请输入新节点data的数据:
4
动态创建新节点完成,请输入新节点data的数据:
5
动态创建新节点完成,请输入新节点data的数据:
0
0 quit
链表动态创建完成,遍历输出:
1 2 3 4 5
链表的节点个数:5
请输入你要查找哪一个节点数据:
1
可以找到:1
请输入你要查找哪一个节点数据:
8
找不到8
请输入你要插在哪一个节点后面:
5
在指定节点5后面插入新节点OK
在指定节点后面插入新节点后遍历输出链表:
1 2 3 4 5 100
请输入你要插在哪一个节点的前面:
3
在指定节点3前面插入新节点OK
链表在指定节点前方插入新节点OK,遍历输出:
1 2 200 3 4 5 100
请输入你要删除哪一个节点:
2
链表的第2个节点删除完毕!
链表删除指定节点后,输出链表:
1 200 3 4 5 100
请输入你要改哪一个节点data的数据:
200
请输入要更改的数据:
1000
指定节点的数据修改成功!
链表修改指定节点data的数据后,遍历输出链表:
1 1000 3 4 5 100
*/

Guess you like

Origin blog.csdn.net/weixin_54859557/article/details/129675109
Recommended