数据结构之单链表

数据结构之单链表

编码文章call10242025-06-21 17:58:444A+A-

什么是链表

链表是一种常见的线性数据结构,它由一系列节点组成,每个节点包含两部分:数据域和指针域。数据域用于存储具体的数据,而指针域则用于指向下一个节点。

链表的特点如下:

  • 链表中的节点在内存中可以随机分布,不要求连续存储。
  • 每个节点通过指针将其与下一个节点连接起来,形成链式结构。
  • 链表的头节点可以作为访问整个链表的入口。

根据指针的类型和指向的节点数目,链表可以分为多种类型,包括单向链表、双向链表和循环链表等。

链表相比于顺序表有以下优势:

  • 插入和删除操作效率高,只需要修改指针的指向,不需要移动其他节点。
  • 可以动态地分配内存空间,不需要事先定义容量。
  • 适用于频繁插入和删除的场景。

然而,链表的缺点是访问元素的效率较低,需要从头节点开始遍历整个链表才能找到目标节点。此外,链表的存储空间会稍微多于顺序表,因为每个节点都需要额外的指针来连接其他节点。

链表的分类

链表可以根据指针的类型和指向的节点数目进行分类。以下是几种常见的链表有以下这些:

  • 有头链表: 固定表头节点
  • 无头链表:表头节点可改变
  • 单向链表: 一个寻址指针
  • 双向链表:两个寻址指针
  • 循环链表:首位连通

有头单链表

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <string.h>

typedef struct MM 
{
	char name[20];
	int age;
	int num;
}MM;

typedef int DataType;
typedef struct Node 
{
	DataType data;
	struct Node* next;
}Node;

Node* create_list() 
{
	Node* headNode = (Node*)calloc(1, sizeof(Node));
	assert(headNode);
	return headNode;
}

Node* create_node(DataType data) 
{
	Node* newNode = (Node*)calloc(1, sizeof(Node));
	assert(newNode);
	newNode->data = data;
	return newNode;
}
void print_list(Node* list) 
{
	if (list == NULL)
		return;
	Node* pmove = list->next;
	while (pmove != NULL) 
	{
		printf("%d\t", pmove->data);
		pmove = pmove->next;
	}
	printf("\n");
}
void push_front(Node* headNode, DataType data) 
{
	if (headNode == NULL)
		return;

	Node* newNode = create_node(data);
	newNode->next = headNode->next;
	headNode->next = newNode;
}
void push_back(Node* headNode,DataType data)
{
	if (headNode == NULL)
		return;
	Node* pmove = headNode;
	while (pmove->next != NULL) 
	{
		pmove = pmove->next;
	}
#if 0
	Node* newNode = create_node(data);
	pmove->next = newNode;
#endif
	pmove->next = create_node(data);
}

void insert(Node* headNode, DataType posData, DataType data) 
{
	if (headNode == NULL)
		return;
	Node* preNode = headNode;
	Node* posNode = headNode->next;
	while (posNode != NULL && posNode->data != posData) 
	{
#if 0
		preNode = preNode->next;
		posNode = posNode->next;
#endif
		preNode = posNode;
		posNode = preNode->next;
	}
	//分析查找结果
	if (posNode == NULL) 
	{
		printf("未找到指定节点,无法插入!!!!\n");
	}
	else 
	{
		Node* newNode = create_node(data);
		preNode->next = newNode;
		newNode->next = posNode;
	}
}
void pop_front(Node* list) 
{
	if (list == NULL)
		return;
	Node* frontNode = list->next;
	if (frontNode != NULL)
	{
		list->next = frontNode->next;
		free(frontNode);
		frontNode = NULL;
	}
}
void pop_back(Node* list) 
{
	if (list == NULL)
		return;
	Node* preNode = list;
	Node* tailNode = list->next;
	if (tailNode != NULL) 
	{
		while (tailNode->next != NULL) 
		{
			preNode = tailNode;
			tailNode = preNode->next;
		}
		free(tailNode);
		tailNode = NULL;
		preNode->next = NULL;
	}
}

void erase(Node* list, DataType posData) 
{
	if (list == NULL)
		return;
	Node* preNode = list;
	Node* posNode = list->next;
	while (posNode != NULL && posNode->data != posData) 
	{
		preNode = posNode;
		posNode = preNode->next;
	}
	if (posNode == NULL) 
	{
		printf("未找到指定节点,无法插入!\n");
	}
	else 
	{
		preNode->next = posNode->next;
		free(posNode);
		posNode = NULL;
	}
}
//其他
//按位序进行插入删除

Node* search(Node* list, DataType posData) 
{
	if (list == NULL)
		return NULL;
	Node* pmove = list->next;
	while (pmove != NULL && pmove->data != posData) 
	{
		pmove = pmove->next;
	}
	return pmove;
}
void destory(Node* list) 
{
	if (list == NULL)
		return;
	while (list->next != NULL) 
	{
		pop_front(list);
	}
	free(list);

}

int main() 
{
	Node* list = create_list();
	push_front(list, 1);
	push_front(list, 2);
	push_front(list, 3);
	print_list(list);
	push_back(list, 4);
	push_back(list, 5);
	push_back(list, 6);
	print_list(list);
	insert(list, 4, 888);
	print_list(list);
	pop_front(list);
	pop_front(list);
	print_list(list);
	pop_back(list);
	pop_back(list);
	print_list(list);
	erase(list, 888);
	print_list(list);
	
	destory(list);
	list = NULL;
	return 0;
}

无头单链表

  • 再封装写法
  • 二级指针写法
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <string.h>

typedef struct MM 
{
	char name[20];
	int age;
	int num;
}MM;

typedef int DataType;
typedef struct Node 
{
	DataType data;
	struct Node* next;
}Node;

Node* create_list() 
{
	Node* headNode = (Node*)calloc(1, sizeof(Node));
	assert(headNode);
	return headNode;
}

Node* create_node(DataType data) 
{
	Node* newNode = (Node*)calloc(1, sizeof(Node));
	assert(newNode);
	newNode->data = data;
	return newNode;
}
void print_list(Node* list) 
{
	if (list == NULL)
		return;
	Node* pmove = list->next;
	while (pmove != NULL) 
	{
		printf("%d\t", pmove->data);
		pmove = pmove->next;
	}
	printf("\n");
}
void push_front(Node* headNode, DataType data) 
{
	if (headNode == NULL)
		return;

	Node* newNode = create_node(data);
	newNode->next = headNode->next;
	headNode->next = newNode;
}
void push_back(Node* headNode,DataType data)
{
	if (headNode == NULL)
		return;
	Node* pmove = headNode;
	while (pmove->next != NULL) 
	{
		pmove = pmove->next;
	}
#if 0
	Node* newNode = create_node(data);
	pmove->next = newNode;
#endif
	pmove->next = create_node(data);
}

void insert(Node* headNode, DataType posData, DataType data) 
{
	if (headNode == NULL)
		return;
	Node* preNode = headNode;
	Node* posNode = headNode->next;
	while (posNode != NULL && posNode->data != posData) 
	{
#if 0
		preNode = preNode->next;
		posNode = posNode->next;
#endif
		preNode = posNode;
		posNode = preNode->next;
	}
	//分析查找结果
	if (posNode == NULL) 
	{
		printf("未找到指定节点,无法插入!!!!\n");
	}
	else 
	{
		Node* newNode = create_node(data);
		preNode->next = newNode;
		newNode->next = posNode;
	}
}
void pop_front(Node* list) 
{
	if (list == NULL)
		return;
	Node* frontNode = list->next;
	if (frontNode != NULL)
	{
		list->next = frontNode->next;
		free(frontNode);
		frontNode = NULL;
	}
}
void pop_back(Node* list) 
{
	if (list == NULL)
		return;
	Node* preNode = list;
	Node* tailNode = list->next;
	if (tailNode != NULL) 
	{
		while (tailNode->next != NULL) 
		{
			preNode = tailNode;
			tailNode = preNode->next;
		}
		free(tailNode);
		tailNode = NULL;
		preNode->next = NULL;
	}
}

void erase(Node* list, DataType posData) 
{
	if (list == NULL)
		return;
	Node* preNode = list;
	Node* posNode = list->next;
	while (posNode != NULL && posNode->data != posData) 
	{
		preNode = posNode;
		posNode = preNode->next;
	}
	if (posNode == NULL) 
	{
		printf("未找到指定节点,无法插入!\n");
	}
	else 
	{
		preNode->next = posNode->next;
		free(posNode);
		posNode = NULL;
	}
}
//其他
//按位序进行插入删除

Node* search(Node* list, DataType posData) 
{
	if (list == NULL)
		return NULL;
	Node* pmove = list->next;
	while (pmove != NULL && pmove->data != posData) 
	{
		pmove = pmove->next;
	}
	return pmove;
}
void destory(Node* list) 
{
	if (list == NULL)
		return;
	while (list->next != NULL) 
	{
		pop_front(list);
	}
	free(list);

}

int main() 
{
	Node* list = create_list();
	push_front(list, 1);
	push_front(list, 2);
	push_front(list, 3);
	print_list(list);
	push_back(list, 4);
	push_back(list, 5);
	push_back(list, 6);
	print_list(list);
	insert(list, 4, 888);
	print_list(list);
	pop_front(list);
	pop_front(list);
	print_list(list);
	pop_back(list);
	pop_back(list);
	print_list(list);
	erase(list, 888);
	print_list(list);
	
	destory(list);
	list = NULL;
	return 0;
}

链表其他操作

  • 有序链表的构建
  • 链表归并
  • 链表的反转问题
  • 链表的冒泡排序
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <string.h>
typedef struct Node 
{
	int data;
	struct Node* next;
}Node;

Node* create_list() 
{
	Node* headNode = (Node*)calloc(1, sizeof(Node));
	assert(headNode);
	return headNode;
}

Node* create_node(int data)
{
	Node* newNode = (Node*)calloc(1, sizeof(Node));
	assert(newNode);
	newNode->data = data;
	return newNode;
}

void print_list(Node* list)
{
	Node* pmove = list->next;
	while (pmove != NULL) 
	{
		printf("%d\t", pmove->data);
		pmove = pmove->next;
	}
	printf("\n");
}
//有序链表构建
void push_sort(Node* list, int data) 
{
	Node* newNode = create_node(data);
	Node* preNode = list;
	Node* posNode = preNode->next;
	while (posNode != NULL && posNode->data <= data) 
	{
		preNode = posNode;
		posNode = preNode->next;
	}
	if (posNode == NULL && preNode == list) 
	{
		list->next = newNode;
	}
	if (posNode == NULL && preNode != list) 
	{
		preNode->next = newNode;
	}
	else 
	{
		preNode->next = newNode;
		newNode->next = posNode;
	}
}

//冒泡排序
void bubble_sort(Node* list) 
{
	for (Node* p = list->next; p != NULL; p=p->next)
	{
		for (Node* q = list->next; q != NULL; q = q->next) 
		{
			if (q->next != NULL && q->data < q->next->data) 
			{
				int data = q->data;
				q->data = q->next->data;
				q->next->data = data;
			}
		}
	}
}

//链表的归并
void mergeList(Node* result, Node* list1, Node* list2) 
{
	Node* first = list1->next;
	Node* second = list2->next;
	Node* tailNode = result;
	while (first != NULL && second != NULL) 
	{
		if (first->data < second->data) 
		{
			tailNode->next = first;
			tailNode = first;
			first = first->next;
		}
		else 
		{
			tailNode->next = second;
			tailNode = second;
			second = second->next;
		}
	}
	if (first != NULL) 
	{
		tailNode->next = first;
	}
	if (second != NULL) 
	{
		tailNode->next = second;
	}
}

//链表反转
void  reverse_list(Node* list) 
{
	if (list == NULL || list->next == NULL || list->next->next == NULL)
		return;
	Node* preNode = NULL;
	Node* curNode = list->next;
	Node* surNode = curNode->next;
	while (surNode != NULL) 
	{
		curNode->next = preNode;
		preNode = curNode;
		curNode = surNode;
		surNode = surNode->next;
	}
	curNode->next = preNode;
	list->next = curNode;
}


int main() 
{
	Node* s = create_list();
	push_sort(s, 9);
	push_sort(s, 2);
	push_sort(s, 4);
	push_sort(s, 3);
	print_list(s);
	bubble_sort(s);
	print_list(s);


	Node* result = create_list();
	Node* first = create_list();
	push_sort(first, 1);
	push_sort(first, 5);
	push_sort(first, 3);
	push_sort(first, 7);
	Node* second = create_list();
	push_sort(second, 2);
	push_sort(second, 6);
	push_sort(second, 4);
	mergeList(result, first, second);
	print_list(result);

	reverse_list(s);
	print_list(s);
	return 0;
}

相关

如果阁下正好在学习C/C++,看文章比较无聊,不妨关注下关注下小编的视频教程,通俗易懂,深入浅出,一个视频只讲一个知识点。视频不深奥,不需要钻研,在公交、在地铁、在厕所都可以观看,随时随地涨姿势。

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4