单链表

单链表

一、什么是链表

链表是数据结构中线性表的一种,其中的每个元素实际上是一个单独的结构体对象,而所有对象都通过每个元素中的指针域连接在一起。链表是以结构体为节点,将一个结构体看成数据域和指针域两个部分,数据域用于存储数据,指针域用于连接下一个节点。链表中每个结构体对象叫做节点,其中第一个数据节点叫做链表的首元节点。如果第一个节点不用于存储数据,只用于代表链表的起始点,则这个节点称为链表的头节点。

二、链表的特点

1、链表没有固定长度,可以自由增加节点。

2、链表能够实现快速的插入删除数据,也就是可以快速的插入和删除链表中的节点。

3、与数组类似,链表也是一种线性数据结构。

4、链表的尾节点的后继必定指向空。

链表和数组的区别:

数组和顺序表是顺序存储的,也就是内存是连续的;而链表是通过指针将不连续的内存连接起来,实现链式存储的。

三、单链表结构体声明

//定义链表节点的声明
typedef struct Node		//取别名为Node
{
	int data;	//数据域
	Node* next;	//指针域,指向下一个节点

}Node;

//整个链表的结构的声明
typedef struct LinkList
{
	Node* head;	//链表头节点指针
	Node* End;	//链表尾节点指针
	int length;	//链表长度
}linklist;

四、单链表的结构示意图

五、单链表的设计与功能实现

5.1、创建单链表

//1、创建单链表
linklist* link_init()
{
	//开辟单链表空间
	linklist* temp = (LinkList*)malloc(sizeof(LinkList));
	if (temp == nullptr)
	{
		return nullptr;
	}
	temp->head = nullptr;
	temp->End = nullptr;
	temp->length = 0;
	return temp;
}

5.2、创建单链表节点

//2、创建单链表节点
Node* node_init(int val)
{
	Node* temp = (Node*)malloc(sizeof(Node));
	if (temp == nullptr)
	{
		return nullptr;
	}
	temp->data = val;
	temp->next = nullptr;
	return temp;
}

5.3、单链表的打印输出

//3、单链表的打印输出
void list_print(linklist* list)
{
	for (Node* temp = list->head; temp != nullptr; temp = temp->next)
	{
		printf("%d", temp->data);
	}
	printf("\n");
}

5.4、单链表节点的插入(尾插法)

//4、单链表节点的插入
void list_insert_end(linklist* list, int val)	//尾插法
{
	if (list == nullptr)
	{
		printf("链表为空,插入错误");
	}
	Node* temp = node_init(val);	//创建一个新的节点
	if (list->head == nullptr)	//如果头指针为空,则是空链表
	{
		list->head = list->End = temp;	//头,尾指针都指向一个节点
		list->length++;					//链表长度+1
	}
	else  //链表不为空
	{
		list->End->next = temp;		//将新节点连接到链表尾部
		list->End = list->End->next;//将尾指针重新指向最后一个节点
		list->length++;		
	}
}

5.5、指定位置插入

//5、指定位置插入
void list_insert(linklist* list, int index, int val)
{
	if (list == nullptr)
	{
		printf("链表为空,插入失败");
		return;
	}
	if (index > list->length+1 || index <= 0)
	{
		printf("插入位置错误");
		return;
	}
	if (index == list->length + 1)	//插入位置比链表大小大一,尾插
	{
		list_insert_end(list, val);
		return;
	}
	if (index == 1)	//在头节点之前插入,头插
	{
		Node* New = node_init(val);
		New->next = list->head;	//把新节点连接到头部
		list->head = New;	//新节点成为新的头部
		list->length++;
		return;
	}

	Node* temp = list->head;
	for (int i = 1; i < index - 1; i++)
	{
		temp = temp->next;
	}
	Node* New = node_init(val);		//将要插入的节点
	New->next = temp->next;		//新节点连接插入位置之后的节点
	temp->next = New;			//插入位置之前的节点连接上新节点
	list->length++;
}

5.6、单链表节点的删除

//6、单链表节点的删除
int list_delete(linklist* list, int index)
{
	if (list == nullptr)
	{
		printf("链表为空,删除失败");
		return 0;
	}
	if (index > list->length + 1 || index <= 0)
	{
		printf("插入位置错误");
		return 0;
	}
	if (index == 1)
	{
		Node* temp = list->head;	//记住当前头部
		list->head = temp->next;	//第二个节点成为新的头部
		int val = temp->data;
		free(temp);
		list->length--;
		return val;
	}
	if (index == list->length)
	{
		Node* temp = list->head;
		Node* temp2 = list->End;
		for (int i = 1; i < index - 1; i++)
		{
			temp = temp->next;
		}
		int val = temp2->data;
		temp->next = nullptr;	//倒数第二个节点指向空
		list->End = temp;		//倒数第二个成为新的尾节点
		free(temp2);
		list->length--;
		return val;
	}

	Node* temp = list->head;
	for (int i = 1; i < index - 1; i++)
	{
		temp = temp->next;	//找到删除位置的前一个节点
	}
	Node* temp2 = temp->next;	//记住删除位置的节点
	temp->next = temp2->next;	//删除位置前的节点跳过被删除的节点指向下一个节点
	int val = temp2->data;	//记录被删除数据
	free(temp2);
	list->length--;
	return val;
}

5.7获取单链表指定位置上的数据

//7、获取单链表指定位置上的数据
int list_get(linklist* list, int index)
{
	if (list == nullptr)
	{
		printf("链表为空,删除失败");
		return 0;
	}
	if (index > list->length + 1 || index <= 0)
	{
		printf("获取位置错误");
		return 0;
	}
	Node* temp = list->head;
	for (int i = 1; i < index - 1; i++)
	{
		temp = temp->next;
	}
	int val = temp->next->data;
	return val;
}
posted @ 2022-01-22 22:16  宣哲  阅读(75)  评论(0编辑  收藏  举报