数据结构之链表:建立、增、删、改、查、排序

1、链表

链表顾名思义是一种链式的存储结构,使用链表不在需要一整块连续的内存空间,这大大增加了内存空间的利用率,并且链表也是我们后续能够顺利学习其它数据结构的基础。

链表的一个节点是由两部分组成的:数据域 、指针域,数据域存放的是数据,指针域存放的是下一个节点的地址,多个节点通过指针域相连形成了一条“链”。
在这里插入图片描述
头节点后的第一个节点称为首元节点,头节点中的数据域可以存放链表节点的个数也可以不存放数据,当然头节点不是必须的,头节点的上存在可以使我们更方便的对链表进行 增、删、改、查。

节点的代码实现需要借助结构体(结构体在数据结构中无处不在)

typedef struct Node
{
	int data; //数据域
	struct Node* next; //指针域
}node;

int main()
{
	node*head = (node*)malloc(sizeof(node)); //创建了一个 head 节点
	free(head);
	return 0;
}

2、创建链表(带头节点)

2.1、创建头节点并初始化

node* headPointer()
{
	node* head = (node*)malloc(sizeof(node)); //为头节点分配空间
	if (!head)
	{
		printf("头节点创建失败");
		exit(0);
	}
	
	//初始化头节点
	head->next = NULL; 
	head->data = 0;  //链表节点个数(不包含头节点)
	printf("头节点创建成功\n");
	return head;
}

2.2、创建链表的节点并连接链表节点

链表节点的连接方式有两种:尾插法、头插法,这两种方法将在下面详细分析
在这里插入图片描述

//创建链表(有头节点)
void createLink(node* head,int*arr,int i) //这里的i是main函数中的int数组的大小
{
	//movePointer为移动指针,移动指针指向头节点
	node* move_Pointer = head;
	while (head->data!=i)
	{
		node* newNode = (node*)malloc(sizeof(node));

		if (newNode == NULL)
		{
			printf("新节点创建失败");
			exit(0);
		}
		newNode->data = arr[head->data]; //为新节点赋值

		newNode->next = NULL; //初始化新节点的指针域
		// 尾插法----------------------------------------------------
		move_Pointer->next = newNode;
		move_Pointer = newNode;
		//-----------------------------------------------------------


		//头插法------------------------------------------------------
		//newNode->next = move_Pointer->next;
		//move_Pointer->next = newNode;
		//-----------------------------------------------------------
		head->data += 1;
	}
	printf("链表创建成功\n");
}

尾插法:
核心代码

		move_Pointer->next = newNode;
		move_Pointer = newNode;

在这里插入图片描述
在这里插入图片描述
文字描述:
1、通过 node* movePointer = head; 使move_Pointer指向头节点head
2、node* newNode = (node*)malloc(sizeof(node)); 的到一个新的节点 (1号新节点)
3、执行 move_Pointer->next=newNode; 使头节点的指针域指向新节点(1号新节点),实现头节点与新节点的连接
4、执行 move_Pointer=newNode; 使move_Pointer从指向头节点变为指向新节点
5、whiel()循环得到第2个新节点(2号新节点)
6、重复第 3 步使 1号新节点与2号新节点相连
7、重复第 4 步使move_Pointer从指向1号新节点变为指向2号新节点
8、重复执行 2–4步,链表形成

头插法:
核心代码

		newNode->next = move_Pointer->next;
		move_Pointer->next = newNode;

在这里插入图片描述
在这里插入图片描述
文字描述:
1、通过 node* move_Pointer = head; 使move_Pointer指向头节点head
2、node* newNode = (node*)malloc(sizeof(node)); 的到一个新的节点 (1号新节点)
3、执行 newNode->next = move_Pointer->next; 使头节点和 1号新节点都指向 NULL
4、执行 move_Pointer->next = newNode; 使头节点的指针域指向 1号新节点
5、重复第 2 步得到 2 号新节点
6、重复第 3 步使新节点的指针域(newNode->next)指向 1号节点 使的2号新节点与一号新节点相连
7、执行第 4 步使得头指针指针域指向 2 号新节点
8、重复2–4步,链表完成

在这里我们发现,尾插法的移动指针(move_Pointer)始终始终是指向链表的最后一个节点的,而头插法的移动指针(move_Pointer)是始终指向头节点的

3、遍历链表

//遍历链表
void travLink(node* head)
{
	node* move_Pointer = head->next; //移动指针指向首元节点
	while (move_Pointer!=NULL)
	{
		printf("%d\n", move_Pointer->data);
		move_Pointer = move_Pointer->next; //移动指针指向当前节点的后继节点
	}
}

4、查找节点

查找节点是链表后续操作的基础,链表的增、删、改,都需要找到需要操作的节点的位置。

//查找链表的节点(本次查找不是通过节点中的数据查找的,而是通过节点的序号进行查找)
node* findNode(node* head)
{
	int i;
	int j = 1;
	node* move_Pointer = head->next; //移动指针指向首元节点
	//printf("你要查找第几个节点\n");
	scanf_s("%d", &i);
	if (i <= head->data)
	{
		while (move_Pointer!= NULL)
		{
			if (i == 0) //在头节点后插入新节点
				return head;
			if (i == j) //在第i个节点后面添加节点
			{
				return move_Pointer;
			}
			else
			{
				move_Pointer = move_Pointer->next; //move_Pointer指向当前节点的后继节点
				j += 1;
			}
		}
	}
	else
	{
		printf("没有你要查找的节点");
		exit(0);
	}
}

5、添加节点

//添加链表的节点
void addNode(node*head)
{
	int i;
	printf("你要在第几个节点后添加新节点:");
	node* tarNode = findNode(head); //节点查找
	node* P;
	P = tarNode->next; //P指向添加的位置
	node* newNode = (node*)malloc(sizeof(node)); //要添加的新节点
	if (!newNode)
	{
		printf("新添加的节点创建失败\n");
		exit(0);
	}
	printf("你要添加的数据是:");
	scanf_s("%d", &i);
	//初始化新节点--------
	newNode->next = NULL; 
	newNode->data = i;
	//------------------
	tarNode->next = newNode;
	newNode->next = P;
	head->data += 1; //节点数加一
}

在这里插入图片描述
在这里插入图片描述

6、删除节点

//删除节点
void delNode(node* head)
{
	printf("你要删除第几个节点:");
	node* tarNode = findNode(head); //查找链表的节点
	node* P; //过渡指针
	if (!tarNode)
	{
		printf("没有找到删除的位置\n");
		exit(0);
	}
	if (tarNode->next == NULL) //删除最后一个节点
	{
		free(tarNode); //释放被删除节点的存储空间
		head->data -= 1; //节点数减一
		printf("删除完成\n");
	}
	else
	{
		P = tarNode->next->next;
		free(tarNode->next); //释放被删除节点的存储空间
		tarNode->next = P;
		head->data -= 1; //节点数减一
		printf("删除完成\n");
	}

}

在这里插入图片描述
在这里插入图片描述

7、更改节点数据

//更改节点数据
void chanData(node* head)
{
	node* tarNode = findNode(head);
	printf("你要将 %d 更改为:", tarNode->data);
	scanf_s("%d", &(tarNode->data));
	printf("数据更改完成\n");
}

8、排序(冒泡排序,只交换节点数据)

//排序(冒泡排序)
void sortNode(node* head)
{
	if (head->data == 0)
		exit(0);
	int i = 0;
	int j = 0;
	int elem;
	node* P;
	node* P1;
	node* P2;
	if (head->data == 0)
		exit(0);
	for (i = 0; i < head->data - 1; i++)
	{
		P = head->next;
		for (j = 0; j < head->data - i - 1; j++)
		{
			P1 = P;
			P2 = P1->next;
			if (P1->data > P2->data)
			{
				elem = P2->data;
				P2->data = P1->data;
				P1->data = elem;
			}
			P = P->next;
		}
	}
}

9、完整代码

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


typedef struct Node
{
	int data; //数据域
	struct Node* next; //指针域
}node;


node* headNode(); //创建头节点,并初始化
void createLink(node* head, int* arr); //创建链表(有头节点)
node* findNode(node* head); //查找链表的节点
void addNode(node* head); //添加节点
void travLink(node* head); //遍历链表
void delNode(node* head); //删除节点
void chanData(node* head); //更改节点数据
void sortNode(node* head); //排序(冒泡排序)


int main()
{
	int i = 0;
	int arr[] = { 23,34,45,56,67,78,89 };
	node* head = headPointer(); //创建头节点,并初始化
	createLink(head, arr); //创建链表(有头节点)
	addNode(head); //添加新的节点
	delNode(head); //删除节点
	sortNode(head); //排序(冒泡排序)
	travLink(head); //遍历链表
	free(head);
	return 0;
}

//创建头节点,并初始化
node* headNode()
{
	node* head = (node*)malloc(sizeof(node)); //查找链表的节点
	if (!head)
	{
		printf("头节点创建失败");
		exit(0);
	}
	head->next = NULL;
	head->data = 0;
	printf("头节点创建成功\n");
	return head;
}


//创建链表(有头节点)
void createLink(node* head,int*arr)
{
	node* move_Pointer = head; //移动指针指向头节点
	while (head->data!=7)
	{
		node* newNode = (node*)malloc(sizeof(node));

		if (newNode == NULL)
		{
			printf("新节点创建失败");
			exit(0);
		}
		newNode->data = arr[head->data]; //为新节点赋值

		newNode->next = NULL; //初始化新节点的指针域
		// 尾插法----------------------------------------------------
		move_Pointer->next = newNode;
		move_Pointer = newNode;
		//-----------------------------------------------------------


		//头插法------------------------------------------------------
		//newNode->next = move_Pointer->next;
		//move_Pointer->next = newNode;
		//-----------------------------------------------------------
		head->data += 1;
	}
	printf("链表创建成功\n");
}


//遍历链表
void travLink(node* head)
{
	node* move_Pointer = head->next;
	while (move_Pointer!=NULL)
	{
		printf("%d\n", move_Pointer->data);
		move_Pointer = move_Pointer->next;
	}
}


//更改节点数据
void chanData(node* head)
{
	node* tarNode = findNode(head);
	printf("你要将 %d 更改为:", tarNode->data);
	scanf_s("%d", &(tarNode->data));
	printf("数据更改完成\n");
}

//删除节点
void delNode(node* head)
{
	printf("你要删除第几个节点:");
	node* tarNode = findNode(head); //查找链表的节点
	node* P;
	if (!tarNode)
	{
		printf("没有找到删除的位置\n");
		exit(0);
	}
	if (tarNode->next == NULL)
	{
		free(tarNode);
		head->data -= 1;
		printf("删除完成\n");
	}
	else
	{
		P = tarNode->next->next;
		free(tarNode->next);
		tarNode->next = P;
		head->data -= 1;
		printf("删除完成\n");
	}

}


//查找链表的节点
node* findNode(node* head)
{
	int i;
	int j = 1;
	node* move_Pointer = head->next;
	//printf("你要查找第几个节点\n");
	scanf_s("%d", &i);
	if (i <= head->data)
	{
		while (move_Pointer!= NULL)
		{
			if (i == 0)
				return head;
			if (i == j)
			{
				return move_Pointer;
			}
			else
			{
				move_Pointer = move_Pointer->next;
				j += 1;
			}
		}
	}
	else
	{
		printf("没有你要查找的节点");
		exit(0);
	}
}


//排序(冒泡排序)
void sortNode(node* head)
{
	if (head->data == 0)
		exit(0);
	int i = 0;
	int j = 0;
	int elem;
	node* P;
	node* P1;
	node* P2;
	if (head->data == 0)
		exit(0);
	for (i = 0; i < head->data - 1; i++)
	{
		P = head->next;
		for (j = 0; j < head->data - i - 1; j++)
		{
			P1 = P;
			P2 = P1->next;
			if (P1->data > P2->data)
			{
				elem = P2->data;
				P2->data = P1->data;
				P1->data = elem;
			}
			P = P->next;
		}
	}	
}


//添加链表的节点
void addNode(node*head)
{
	int i;
	printf("你要在第几个节点后添加新节点:");
	node* tarNode = findNode(head);
	node* P;
	if (!tarNode)
	{
		printf("没有查找到添加位置\n");
		exit(0);
	}
	P = tarNode->next;
	node* newNode = (node*)malloc(sizeof(node));
	if (!newNode)
	{
		printf("新添加的节点创建失败\n");
		exit(0);
	}
	printf("你要添加的数据是:");
	scanf_s("%d", &i);
	newNode->next = NULL;
	newNode->data = i;
	tarNode->next = newNode;
	newNode->next = P;
	head->data += 1;
}


博客

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值