线性表:动态链表

版权声明:Sock的blog, 可以偷看但不可以偷走哦 https://blog.csdn.net/qq_42957923/article/details/84884017
在数据结构中我们经常会用到链表来处理一些问题, 链表同顺序表一样, 包括静态链表和动态链表, 静态链表并不是很常用, 但动态链表的重要性是不言而喻的. 接下来我们看一下动态链表的基本操作, 以书上的资料为参考, 同时自己对动态链表增加了新的认识和总结

动态链表的基本操作

动态链表的定义

//定义一个动态链表
typedef int ElemType;
typedef struct LNode {
	ElemType data;
	struct LNode* next;
}LNode, *LinkList;

创建一个动态链表

//创建一个动态链表
void CreateList(LinkList* L, int len) {
	printf("请输入 %d 个数据:", len);
	//创建链表的头节点
	*L = (LinkList)malloc(sizeof(LNode));
	//定义一个指向尾节点的指针和一个指向创建结点的指针
	LinkList rear = *L, p = NULL;
	//创建指定大小的空间
	for (int i = 1; i < len + 1; ++i) {
		p = (LinkList)malloc(sizeof(LNode));
		scanf("%d", &p->data);
		//尾指针连接新结点
		rear->next = p;
		//改变尾指针位置
		rear = p;
	}
	//尾指针之后为空
	rear->next = NULL;
}

//逆序
//void CreateList(LinkList* L, int len) {
//	printf("请输入 %d 个数据:", len);
//	//创建头节点
//	*L = (LinkList)malloc(sizeof(LNode));
//	(*L)->next = NULL;
//	//定义一个指向创建结点的指针
//	LinkList p = NULL;
//	for (int i = 1; i < len; ++i) {
//		p = (LinkList)malloc(sizeof(LNode));
//		scanf("%d", &p->data);
//		p->next = (*L)->next;
//		(*L)->next = p;
//	}
//	printf("\n");
//}

求链表的长度

//链表长度
int Length(LinkList L) {
	int len = 0;
	while (L->next != NULL) {
		++len;
		L = L->next;
	}
	return len;
}

向动态链表中插入结点

//向动态链表中插入结点
void InsertList(LinkList* L, int pos, ElemType e) {
	//判断插入位置是否合理
	if (pos < 1 || pos > Length(*L) + 1) {
		printf("插入位置不合理\n");
		return;// exit(0);
	}
	LinkList adjust = *L;
	LinkList insert = (LinkList)malloc(sizeof(LNode));
	insert->data = e;
	//调整adjust的位置, 准备连接
	int i = 0;
	while (i++ < pos - 1) {
		adjust = adjust->next;
	}
	//连接右端
	insert->next = adjust->next;
	//连接左端
	adjust->next = insert;
}

从动态链表中删除结点

//从动态链表中删除结点
void DeleteList(LinkList* L, int pos) {
	//判断删除结点的位置是否合理
	if (pos < 1 || pos > Length(*L)) {
		printf("删除结点的位置不合理\n");
		return;// exit(0);
	}
	LinkList adjust = *L;
	//调整删除位置, 准备删除指定结点
	int i = 0;
	while (i++ < pos - 1) {
		adjust = adjust->next;
	}
	//保存要删除的结点
	LinkList deleted = adjust->next;
	//连接要删除结点的两端结点
	adjust->next = deleted->next;
	//释放结点
	free(deleted);
}

销毁一个动态链表

//销毁一个动态链表
void DestroyList(LinkList* L) {
	LinkList adjust = *L;
	while (*L) {
		//调整指针始终在头节点的下一个位置, 用来保存新的头节点
		adjust = (*L)->next;
		//释放头节点
		free(*L);
		//调整新头节点的位置
		*L = adjust;
	}
	printf("链表已销毁\n");
}

清空一个动态链表

//清空一个动态链表
void ClearList(LinkList* L) {
	LinkList adjust = (*L)->next;
	while ((*L)->next) {
		//调整指针始终指向被删除结点的下一个结点, 用来保存下一个要被删除的结点
		adjust = adjust->next;
		//每次释放头节点的下一个结点
		free((*L)->next);
		//更新头节点的下一个结点(调整指针指向的结点)
		(*L)->next = adjust;
	}
	printf("链表已清空\n");
}

判断链表是否为空

//判断链表是否为空
int IsEmpty(LinkList L) {
	if (L->next == NULL) {
		//printf("链表为空\n");
		return 1;
	}
	//printf("链表不为空\n");
	return 0;
}

获取动态链表上的某个值

//获取动态链表上某个位置上的值
ElemType GetElem(LinkList L, int pos) {
	//判断获取位置是否合理
	if (pos < 1 || pos > Length(L)) {
		printf("获取位置不合理\n");
		return 0;// exit(0);
	}
	LinkList adjust = L;
	//调整获取位置
	int i = 0;
	while (i++ < pos) {
		adjust = adjust->next;
	}
	//返回获取值
	return adjust->data;
}

在动态链表中查找某个元素

//在动态链表中查找某个元素
void LocateElem(LinkList L, ElemType e) {
	LinkList adjust = L->next;
	int count = 0;
	//遍历链表
	while (adjust) {
		++count;
		if (adjust->data == e) {
			printf("找到了该元素, 它是第 %d 个元素\n", count);
			return;
		}
		adjust = adjust->next;
	}
	printf("没有找到该元素\n");
}

在动态链表中查找某个元素的前驱

//在动态链表中查找某个元素的前驱
ElemType ProriElem(LinkList L, ElemType cur_e) {
	//判断是否为第一个元素
	if (L->next->data == cur_e) {
		printf("第一个元素无前驱\n");
		return 0;
	}
	//从第二个元素开始查找
	LinkList adjust = L->next;
	while (adjust->next) {
		if (adjust->next->data == cur_e) {
			return adjust->data;
		}
		adjust = adjust->next;
	}
	printf("没有该元素\n");
	return 0;
}

在动态链表中查找某个元素的后继

//在动态链表中找某个元素的后继
ElemType NextElem(LinkList L, ElemType cur_e) {
	//从第一个元素查找, 最后一个元素要进行判断
	LinkList adjust = L->next;
	while (adjust) {
		if (adjust->data == cur_e) {
			if (adjust->next != NULL) {
				return adjust->next->data;
			}
			printf("最后一个元素没有后继\n");
			return 0;
		}
		adjust = adjust->next;
	}
	printf("没有该元素\n");
	return 0;
}

遍历链表

//遍历链表
void Traverse(LinkList L) {
	//判断链表是否为空
	if (L->next == NULL)  {
		printf("链表为空\n");
		return;
	}
	while (L->next != NULL) {
		printf("%d ", L->next->data);
		L = L->next;
	}	
	printf("\n");
}

测试

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>

//定义一个动态链表
typedef int ElemType;
typedef struct LNode {
	ElemType data;
	struct LNode* next;
}LNode, *LinkList;

//创建一个动态链表
void CreateList(LinkList* L, int len) {
	printf("请输入 %d 个数据:", len);
	//创建链表的头节点
	*L = (LinkList)malloc(sizeof(LNode));
	//定义一个指向尾节点的指针和一个指向创建结点的指针
	LinkList rear = *L, p = NULL;
	//创建指定大小的空间
	for (int i = 1; i < len + 1; ++i) {
		p = (LinkList)malloc(sizeof(LNode));
		scanf("%d", &p->data);
		//尾指针连接新结点
		rear->next = p;
		//改变尾指针位置
		rear = p;
	}
	//尾指针之后为空
	rear->next = NULL;
}

//逆序
//void CreateList(LinkList* L, int len) {
//	printf("请输入 %d 个数据:", len);
//	//创建头节点
//	*L = (LinkList)malloc(sizeof(LNode));
//	(*L)->next = NULL;
//	//定义一个指向创建结点的指针
//	LinkList p = NULL;
//	for (int i = 1; i < len; ++i) {
//		p = (LinkList)malloc(sizeof(LNode));
//		scanf("%d", &p->data);
//		p->next = (*L)->next;
//		(*L)->next = p;
//	}
//	printf("\n");
//}

//链表长度
int Length(LinkList L) {
	int len = 0;
	while (L->next != NULL) {
		++len;
		L = L->next;
	}
	return len;
}

//向动态链表中插入结点
void InsertList(LinkList* L, int pos, ElemType e) {
	//判断插入位置是否合理
	if (pos < 1 || pos > Length(*L) + 1) {
		printf("插入位置不合理\n");
		return;// exit(0);
	}
	LinkList adjust = *L;
	LinkList insert = (LinkList)malloc(sizeof(LNode));
	insert->data = e;
	//调整adjust的位置, 准备连接
	int i = 0;
	while (i++ < pos - 1) {
		adjust = adjust->next;
	}
	//连接右端
	insert->next = adjust->next;
	//连接左端
	adjust->next = insert;
}

//从动态链表中删除结点
void DeleteList(LinkList* L, int pos) {
	//判断删除结点的位置是否合理
	if (pos < 1 || pos > Length(*L)) {
		printf("删除结点的位置不合理\n");
		return;// exit(0);
	}
	LinkList adjust = *L;
	//调整删除位置, 准备删除指定结点
	int i = 0;
	while (i++ < pos - 1) {
		adjust = adjust->next;
	}
	//保存要删除的结点
	LinkList deleted = adjust->next;
	//连接要删除结点的两端结点
	adjust->next = deleted->next;
	//释放结点
	free(deleted);
}

//销毁一个动态链表
void DestroyList(LinkList* L) {
	LinkList adjust = *L;
	while (*L) {
		//调整指针始终在头节点的下一个位置, 用来保存新的头节点
		adjust = (*L)->next;
		//释放头节点
		free(*L);
		//调整新头节点的位置
		*L = adjust;
	}
	printf("链表已销毁\n");
}

//清空一个动态链表
void ClearList(LinkList* L) {
	LinkList adjust = (*L)->next;
	while ((*L)->next) {
		//调整指针始终指向被删除结点的下一个结点, 用来保存下一个要被删除的结点
		adjust = adjust->next;
		//每次释放头节点的下一个结点
		free((*L)->next);
		//更新头节点的下一个结点(调整指针指向的结点)
		(*L)->next = adjust;
	}
	printf("链表已清空\n");
}

//判断链表是否为空
int IsEmpty(LinkList L) {
	if (L->next == NULL) {
		//printf("链表为空\n");
		return 1;
	}
	//printf("链表不为空\n");
	return 0;
}

//获取动态链表上某个位置上的值
ElemType GetElem(LinkList L, int pos) {
	//判断获取位置是否合理
	if (pos < 1 || pos > Length(L)) {
		printf("获取位置不合理\n");
		return 0;// exit(0);
	}
	LinkList adjust = L;
	//调整获取位置
	int i = 0;
	while (i++ < pos) {
		adjust = adjust->next;
	}
	//返回获取值
	return adjust->data;
}

//在动态链表中查找某个元素
void LocateElem(LinkList L, ElemType e) {
	LinkList adjust = L->next;
	int count = 0;
	//遍历链表
	while (adjust) {
		++count;
		if (adjust->data == e) {
			printf("找到了该元素, 它是第 %d 个元素\n", count);
			return;
		}
		adjust = adjust->next;
	}
	printf("没有找到该元素\n");
}

//在动态链表中查找某个元素的前驱
ElemType ProriElem(LinkList L, ElemType cur_e) {
	//判断是否为第一个元素
	if (L->next->data == cur_e) {
		printf("第一个元素无前驱\n");
		return 0;
	}
	//从第二个元素开始查找
	LinkList adjust = L->next;
	while (adjust->next) {
		if (adjust->next->data == cur_e) {
			return adjust->data;
		}
		adjust = adjust->next;
	}
	printf("没有该元素\n");
	return 0;
}

//在动态链表中找某个元素的后继
ElemType NextElem(LinkList L, ElemType cur_e) {
	//从第一个元素查找, 最后一个元素要进行判断
	LinkList adjust = L->next;
	while (adjust) {
		if (adjust->data == cur_e) {
			if (adjust->next != NULL) {
				return adjust->next->data;
			}
			printf("最后一个元素没有后继\n");
			return 0;
		}
		adjust = adjust->next;
	}
	printf("没有该元素\n");
	return 0;
}

//遍历链表
void Traverse(LinkList L) {
	//判断链表是否为空
	if (L->next == NULL)  {
		printf("链表为空\n");
		return;
	}
	while (L->next != NULL) {
		printf("%d ", L->next->data);
		L = L->next;
	}	
	printf("\n");
}

int main() {
	LinkList L1;
	CreateList(&L1, 5);
	Traverse(L1);
	InsertList(&L1, 4, 100);
	Traverse(L1);
	int value = GetElem(L1, 4);
	printf("%d\n", value);
	LocateElem(L1, 100);
	int prori_e = ProriElem(L1, 100);
	printf("%d\n", prori_e);
	int next_e = NextElem(L1, 100);
	printf("%d\n", next_e);
	DeleteList(&L1, 4);
	Traverse(L1);
	system("pause");
	return 0;
}

效果图
在这里插入图片描述
希望能得到大家的指点和支持

猜你喜欢

转载自blog.csdn.net/qq_42957923/article/details/84884017