单链表汇总<C语言版>

单链表概述

单链表

  线性表的链式存储是指用组任意的存储单元(可以连续,也可以不连续)存储线性表中的数据元素。数据元素在存储空间中表示时通常称为结点。因为数据元素可能不连续,为了能够反映数据元素之间的相邻逻辑关系,每个结点不仅要存放数据元素本身,还需要一些额外的存储空间,用于存放和它有关系的数据元素的地址,即需要存放指向其他元素的指针。我们称指向第一个结点的指针 为头指针,一但知道头指针,就可以沿着指针依次访问其他数据元素。

  单链表中每个结点由两部分组成:数据域和指针域。数据域用于存放数据元素,指针域用于存放数据元素之间的关系,通常用于存放直接后继的地址。由于每个结点中只有一个,故称为单链表。

单链表的特征

 1.单链表不要求逻辑上相邻的两个元素在物理位置上也相邻,因此不需要连续的存储空间。

 2.单链表是顺序存储,即不能直接找到表中某个特定的结点。查找某个特定的结点时,需要从表头开始遍历,依次查找。

单链表结点的定义

对于每个链表结点,除了存放元素自身的信息外,还需要存放一个指向其后继的指针。描述如下:

typedef struct LinkList {
	int data;
	struct LinkList* next;
}LNode,*LinkLink;

单链表基本算法

单链表初始化

算法描述:传入单链表的头指针,分配相应的内存空间,将头指针指向NULL。

void InitLink(LinkLink &L){
	L = (LinkLink)malloc(sizeof(LNode));
	L->next = NULL;
	return;}

单链表查空

算法描述:传入单链表,如果单链表不存在,输出“No exist!”,如果头指针的next指向NULL,输出“Empty”,反之,输出“No empty!”。

void CheckLinkEmpty(LinkLink L) {
	if (L == NULL) {printf("No exist\n");}
	else if (L->next == NULL) {printf("Empty!\n");}
	else {printf("No empty!\n");}
	return;}

单链表销毁

算法描述:定义一个LNode类型的指针p,指针指向传入的单链表头结点L,利用while循环判断L是否为空,不为空,p=L,L=L->next,然后释放p,以此循环,直到L为空,停止循环,链表被销毁。

void DestroyLink(LinkLink& L) {
	LNode* p = L;
	while (L)
	{		p = L;
		L = L->next;
		free(p);}
	printf("Destroy success!\n");}

单链表清空

算法描述:定义两个LNode类型的指针p,q。p指向首结点,利用while循环判断p是否为空,不为空让q指向p下一个结点,释放p,再让p等于q,以此循环,直到p为空,停止循环,让头指针L->next=NULL。

void ClearLink(LinkLink& L) {
	LNode* p = (LinkLink)malloc(sizeof(LNode));
	LNode* q = (LinkLink)malloc(sizeof(LNode));
	p = L->next;
	while (p) {
		q = p->next;
		free(p);
		p = q;}
	L->next = NULL;
	printf("Clear success!\n");}

单链表求表长

算法描述:定义一个LNode类型的指针p指向单链表首结点,定义一个整数i=0。利用while循环判断p是否为空,如果不为空,p指向下一个结点,i加1,以此循环,直到p为空,返回i。

int LinkLength(LinkLink L) {
	int i = 0;
	LNode* p = L->next;
	while (p) {
		p = p->next;
		i++;
	}
	printf("The length of the Link is %d\n", i);
	return i;
}

单链表按值查找

(假定链表中存在该值)

算法描述:设查找的值为e,定义一个LNode类型的指针指向单链表首结点,定义一个整数i=0(用来计算结点位数)。利用while循环判断p是否为空,不为空,i加1,如果p->data等于e,则结束循环。反之,p指向下一个结点,以此循环。

void SearchLink(LinkLink L,int e) {
	LNode* p = L->next;
	int i =0 ;
	while (p) {
		i++;
		if (p->data == e) {
			printf("This is %d\n", i);
			break;}
		else {p = p->next;}}
	return;
}

单链表按位查找

(假定位数存在)

算法描述:定义一个LNode类型的指针指向单链表头结点,定义一个整数i=0(用来计算结点位数)。利用while循环,如果i不等于位数r,则i++,p指向下一个结点,直到i等于r,输出p->data的值,结束循环。

void LookLink(LinkLink L,int r) {
	LNode* p = L;
	int i = 0;
	while (i!=r)
	{		i++;
		p = p->next;}
	printf("%d\n", p->data);
	return;}

单链表添加结点

算法描述:定义两个LNode类型的指针p,q。p指向单链表头结点,另q->data等于e,利用for循环使p指向所需添加结点(r)的上一个结点(r-1),另q->next等于p->next。再让让p->next指向q。

void AddLink(LinkLink &L, int r, int e) {
	LNode* p = L;
	LNode *q= (LinkLink)malloc(sizeof(LNode));
	q->data = e;
	for (int i = 1; i < r; i++) {
		p = p->next;
	}
	q->next = p->next;
	p->next = q;
	return;
}

单链表删除结点

算法描述:定义两个LNode类型的指针p,q。p指向单链表头结点。利用for循环使p指向所需删除结点(r)的上一个结点(r-1),另q->next等于p->next。再让让p->next指向删除结点下一个结点。释放q

void DeleteLink(LinkLink &L, int r) {
	LNode* p = L;
	LNode* q = (LinkLink)malloc(sizeof(LNode));
	for (int i = 1; i < r; i++) {
		p = p->next;
	}
	q->next = p->next;
	p->next = p->next->next;
	free(q);
	return;
}

两种创建单链表的方法

头插法

算法描述:初始化单链表L,假定创造n个结点,利用for循环,每次循环,定义一个LNode的指针p,输入p->data的值,使p->next=L->next。L->next指向p。利用头插法输入{1,2,3}则会储存为{3,2,1}。

void CreateLinkHead(LinkLink& L, int n) {
	InitLink(L);
	for (int i = 0; i < n; i++) {
		LNode *p= (LinkLink)malloc(sizeof(LNode));
			scanf_s("%d", &(p->data));
			p->next = L->next;
			L->next = p;}
	return;}

尾插法

算法描述:初始化单链表L,假定创造n个结点,定义一个LinkList的指针r指向头结点,利用for循环,每次循环,定义一个LNode的指针p,使p->next=NULL。输入p->data的值。让r->next指向p。r指向p。利用尾插法输入{1,2,3}则会储存为{1,2,3}。

void CreateLinkTail(LinkLink& L, int n) {
	InitLink(L);
	LinkList* r = (LinkLink)malloc(sizeof(LNode));
	r = L;
	for (int i = 0; i < n; i++) {
		LNode* p= (LinkLink)malloc(sizeof(LNode));
		p->next = NULL;
		scanf_s("%d", &(p->data));
		r->next = p;
		r = p;
	}
	return;
}

调试

利用尾插法创建一个带头结点的9结点单链表,输入{9,8,7,6,5,4,3,2},进行一系列操作调试。

int main() {
	LinkLink List;
	CreateLinkTail(List, 8);
	CheckLinkEmpty(List);
	int a = LinkLength(List);
	SearchLink(List, 6);
	LookLink(List,5);
	DeleteLink(List, 4);
	a = LinkLength(List);
	ClearLink(List);
	CheckLinkEmpty(List);
	DestroyLink(List);
	CheckLinkEmpty(List);
	return 0;
}

结果图:

单链表归并排序的C语言实现步骤如下: 1. 定义单链表结构体和归并排序函数 2. 实现归并排序函数,其中包括以下步骤: a. 如果链表为空或只有一个节点,直接返回 b. 使用快慢指针将链表分成两个子链表 c. 递归调用归并排序函数对两个子链表进行排序 d. 合并两个已排序的子链表 下面是单链表归并排序的C语言代码实现: ``` #include <stdio.h> #include <stdlib.h> // 定义单链表结构体 typedef struct ListNode { int val; struct ListNode *next; } ListNode; // 归并排序函数 ListNode* mergeSortList(ListNode* head) { if (head == NULL || head->next == NULL) { return head; } // 使用快慢指针将链表分成两个子链表 ListNode *slow = head, *fast = head->next; while (fast != NULL && fast->next != NULL) { slow = slow->next; fast = fast->next->next; } ListNode *mid = slow->next; slow->next = NULL; // 递归调用归并排序函数对两个子链表进行排序 ListNode *left = mergeSortList(head); ListNode *right = mergeSortList(mid); // 合并两个已排序的子链表 ListNode *dummy = (ListNode*)malloc(sizeof(ListNode)); ListNode *cur = dummy; while (left != NULL && right != NULL) { if (left->val < right->val) { cur->next = left; left = left->next; } else { cur->next = right; right = right->next; } cur = cur->next; } cur->next = (left != NULL) ? left : right; ListNode *newHead = dummy->next; free(dummy); return newHead; } // 测试代码 int main() { // 创建链表 ListNode *head = (ListNode*)malloc(sizeof(ListNode)); head->val = 4; head->next = (ListNode*)malloc(sizeof(ListNode)); head->next->val = 2; head->next->next = (ListNode*)malloc(sizeof(ListNode)); head->next->next->val = 1; head->next->next->next = (ListNode*)malloc(sizeof(ListNode)); head->next->next->next->val = 3; head->next->next->next->next = NULL; // 归并排序 ListNode *newHead = mergeSortList(head); // 输出排序后的链表 while (newHead != NULL) { printf("%d ", newHead->val); newHead = newHead->next; } printf("\n"); return 0; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值