链表的插入、删除、修改与创建

一、链表的插入

1.1.尾插法

尾插法指在链表中特定节点的后面插入一个节点。insertFromBehide函数有三个参数,分别是struct Test *head把原来的链表首地址传过来,int data在这个数据的后面插入,struct Test *new插入这一个新的节点。

#include <stdio.h>

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

void printLink(struct Test *head)	
{
	struct Test *point;
	point= head;	//使用指针更方便看
	while(point != NULL){	//判断指针的指向是否为NULL,为NULL就结束
		printf("%d ",point->data);	//输出结构体的数据
		point= point->next;	//输出结束之后,指针指向下一个,也就是下一个结构体的首地址
	}
		puts("\n");
}

int insertFromBehide(struct Test *head, int data, struct Test *new)
{
	struct Test *point = head;
	while(point != NULL){
		if(point->data == data){
			//这两个位置不能交换,如果交换了,新节点的尾只能指向NULL
			new->next = point->next;	//先把新节点的尾巴接到data的下一个节点的头
			point->next = new;			//再让data原先指向下一个的指针,指向新节点的头
			return 1;
		}
		point = point->next;
	}
	return 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};
	struct Test t6 = {6,NULL};
	struct Test new = {100,NULL};
	
	t1.next = &t2;
	t2.next = &t3;
	t3.next = &t4;
	t4.next = &t5;
	t5.next = &t6;
	
	int data,result;
	printf("Please input which data you want to insert behind:\n");
	scanf("%d",&data);
	result = insertFromBehide(&t1,data,&new);
	if(result == 1){
		printLink(&t1);
	}
	if(result == 0){
		printf("ERROR!\n");
	}
	return 0;
}

2.2.头插法

头插法有两种情况:

  1. 在链表的表头插入一个新的节点
  2. 在链表中间,特定节点的前面插入一个新节点
#include <stdio.h>

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

void printLink(struct Test *head)	
{
	struct Test *point;
	point= head;	//使用指针更方便看
	while(point != NULL){	//判断指针的指向是否为NULL,为NULL就结束
		printf("%d ",point->data);	//输出结构体的数据
		point= point->next;	//输出结束之后,指针指向下一个,也就是下一个结构体的首地址
	}
		puts("\n");
}

struct Test *insertFromAhead(struct Test *head, int data, struct Test *new)
{
	struct Test *point = head;
	if(point->data == data){	//在该链表的头插入
		new->next = point;	//把新节点的尾巴接到链表的头
		return new;	//返回新链表的新头
	}
	while(point->next != NULL){		//这里为什么不像之前一样是(point != NULL)呢?因为上面代码已经交代了要是在链表头插入的情况了,因此,这里要在第二个开始遍历
		if(point->next->data == data){	//point->next->data指的是下一个节点的数据
			new->next = point->next;	//这里的point->next是指下一个节点的头,把新节点的尾巴接到下一个节点的头
			point->next = new;	//这里的point->next是指当前节点的尾巴接到新节点的头
			return head;	//如果成功找到该节点并且成功插入,就把该链表的头返回出去
		}
		point = point->next;
	}
	printf("Haven't this data%d\n",data);	//如果没有该节点,则打印这句话
	return head;
}

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};
	struct Test t6 = {6,NULL};
	struct Test new = {100,NULL};
	struct Test *head = NULL;
	
	t1.next = &t2;
	t2.next = &t3;
	t3.next = &t4;
	t4.next = &t5;
	t5.next = &t6;
	
	printf("Please input which data you want to insert in front of:\n");
	scanf("%d",&data);
	head = insertFromAhead(&t1, data, &new);
	printLink(head);
	return 0;
}

二、链表的删除

链表删除指定节点有两种情况:

  1. 删除头节点
  2. 删除中间节点
#include <stdio.h>

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

void printLink(struct Test *head)	
{
	struct Test *point;
	point= head;	//使用指针更方便看
	while(point != NULL){	//判断指针的指向是否为NULL,为NULL就结束
		printf("%d ",point->data);	//输出结构体的数据
		point= point->next;	//输出结束之后,指针指向下一个,也就是下一个结构体的首地址
	}
		puts("\n");
}

struct Test *deleteNode(struct Test *head, int data)
{
	struct Test *point = head;
	if(point->data == data){	//如果删除头节点
		return point->next;	//把第二个节点当作头节点返回去
	}
	while(point->next != NULL){
		if(point->next->data == data){
			point->next = point->next->next;	//让当前节点的尾巴,指向下下个节点的头,也就是被删除节点的尾巴
			return head;
		}
		point = point->next;
	}
	printf("There is no this data%d!\n",data);
	return head;
}

int main()
{
	struct Test *p = 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};
	struct Test t6 = {6,NULL};

	t1.next = &t2;
	t2.next = &t3;
	t3.next = &t4;
	t4.next = &t5;
	t5.next = &t6;
	
	printf("Please input which data you want to delete:\n");
	scanf("%d",&data);
	p = deleteNode(&t1,data);
	printLink(p);
	return 0;
}

三、链表的修改

在查找的基础上只是添加了这一行代码即可实现point->data = newData;

int changeLink(struct Test *head, int data, int newData)
{
	struct Test *point = head;
	while(point != NULL){
		if(point->data == data){	//与链表里的值做对比
			point->data = newData;	//让之前的数据直接变成新数据
			return 1;
		}
		point = point->next;	//指针指向下一个首地址
	}
	return 0;	
}

四、动态创建链表

4.1.头插法

每来一次新的数据,就放在链表的头里,先到后出,类似栈,也类似弹匣压子弹的方式。

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

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

void printLink(struct Test *head)	
{
	struct Test *point;
	point= head;	//使用指针更方便看
	while(point != NULL){	//判断指针的指向是否为NULL,为NULL就结束
		printf("%d ",point->data);	//输出结构体的数据
		point= point->next;	//输出结束之后,指针指向下一个,也就是下一个结构体的首地址
	}
	puts("\n");
}

struct Test *insertFromHead(struct Test *head, struct Test *new)
{
	if(head == NULL){	//如果指向NULL的话,直接让最新的节点变成表头
		head = new;
	}else{
		new->next = head;	//如果不是就把新节点的尾巴接到链表的头
		head = new;	//新的节点就变成链表的头
	}
	return head;
}

struct Test *createLink(struct Test *head)
{
	struct Test *new;
	while(1){
		new = (struct Test *)malloc(sizeof(struct Test));
		printf("Please input your node:\n");
		scanf("%d",&(new->data));
		if(new->data == 0){
			printf("quit\n");
			free(new);	
			return head;	//输入0结束后,把链表的头返回出去
		}
		head = insertFromHead(head, new);
	}
}

int main()
{
	struct Test *head = NULL;
	struct Test t1 = {999,NULL};
	head = createLink(head);
	printLink(head);
	head = insertFromHead(head,&t1);
	printLink(head);	//在链表头插入t1之后
	return 0;
}

4.2.尾插法

尾插法讲究先来后出,按顺序输入,按顺序输出。

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

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

void printLink(struct Test *head)	
{
	struct Test *point;
	point= head;	//使用指针更方便看
	while(point != NULL){	//判断指针的指向是否为NULL,为NULL就结束
		printf("%d ",point->data);	//输出结构体的数据
		point= point->next;	//输出结束之后,指针指向下一个,也就是下一个结构体的首地址
	}
	puts("\n");
}

struct Test *insertFromBehind(struct Test *head, struct Test *new)
{
	struct Test *point = head;
	if(point == NULL){
		head = new;	//如果指向NULL,直接返回链表头
		return head;
	}
	while(point->next != NULL){
		point = point->next;
	}
	point->next = new;	//如果是在最后一个数据插入,new的头接在最后一个节点
	return head;
}

struct Test *createLink(struct Test *head)
{
	struct Test *new;
	while(1){
		new = (struct Test *)malloc(sizeof(struct Test));
		printf("Please input your node:\n");
		scanf("%d",&(new->data));
		if(new->data == 0){
			printf("quit\n");
			free(new);	
			return head;	//输入0结束后,把链表的头返回出去
		}
		head = insertFromBehind(head, new);
	}
}

int main()
{
	struct Test *head = NULL;
	struct Test t1 = {999,NULL};
	head = createLink(head);
	printLink(head);
	head = insertFromBehind(head,&t1);
	printLink(head);	//在链表最后插入t1
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值