2022.07.13------线性表的链式表示

本文详细探讨了链表的各种操作,包括删除特定值的结点、反向输出、删除最小值结点、链表逆置、排序、删除指定范围元素、找公共结点、按值合并链表、查找链表中倒数第k个结点、共享相同后缀存储空间等。这些算法涉及单链表、循环链表和双链表等多种数据结构,旨在提升链表操作的效率和实用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

 ​​​​​​​

1.设计一个递归算法,删除不带头结点的单链表L中所有制为x的结点。​编辑

2.在带头结点的单链表L中,删除所有值为x的结点,并释放其空间。假设值为x的结点不唯一,试编写算法以实现上述操作。

 3.设L为带头结点的单链表,编写算法实现从尾到头反向输出每个结点的值。​编辑

 4.试编写在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值结点是唯一的)。​编辑

 5.试编写算法将带头结点的单链表就地逆置,所谓“就地”是指辅助空间复杂度为O(1)。​编辑

 6.有一个带头结点的单链表L,设计一个算法使其元素递增有序。​编辑

7.设在一个带表头结点的单链表中所有元素结点的数据值无序,试编写一个函数,删除表中所有介于给定的两个值(作为函数参数给出)之间的元素(若存在)。

 8.给定两个单链表,编写算法找出两个链表的公共结点。​编辑

  9.给定一个带表头结点的单链表,设head为头指针,结点的结构为(data,next),data为整型元素,next为指针,试写出算法;按递增次序输出单链表中各结点的数据元素,并释放结点所占存储空间(要求:不允许使用数组作为辅助空间)。

10.将一个带头结点的单链表A分解为两个带头结点的单链表A和B,使得A表中含有原表中序号为奇数的元素,而B表中含有原表中序号为偶数的元素,且保持其相对顺序不变。​编辑

 11.设C={a1,b1,a2,b2,...,an,bn}为线性表,采用带头结点的hc单链表存放,设计一个就地算法将其拆分为两个线性表,使得A={a1,a2,...,an},B={bn,...,b2,b1}。​编辑

  12.在一个递增有序的线性表中,有数值相同的元素存在。若存储方式为单链表,设计算法去掉数值相同的元素使表中不再有重复的元素。例如(7,10,10,21,30,42,42,42,51,70)将变作(7,10,21,30,42,51,70)。​编辑

 13.假设有两个按元素值递增次序排列的线性表,均以单链表形式存储,请编写算法将这两个单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来两个单链表的结点存放归并后的单链表。​编辑

 14.设A和B是两个单链表(带头结点),其中元素递增有序。设计一个算法从A和B中公共元素产生单链表C,要求不破坏A、B的结点。​编辑

15.已知两个链表A和B分别表示两个集合,其元素递增排列。编制函数,求A和B的交集,并存放于A链表中。​编辑

 16.两个整数序列A=a1,a2,a3,...,am和B=b1,b2,...,bn已经存入两个单链表中,设计一个算法,判断序列B是否是序列A的连续子序列。​编辑

17. 设计一个算法用于判断带头结点的循环双链表是否对称。​编辑

18.有两个循环单链表,链表头指针分别为h1和h2,编写一个函数将链表h2链接到链表h1之后,要求链接后的链表仍保持循环链表形式。​编辑

19.设有一个带头结点的循环单链表,其结点值均为正整数。设计一个算法,反复找出单链表中结点值最小的结点并输出。然后将该结点从中删除,直到单链表空为止,再删除表头结点。​编辑

20.设头指针为L的带有表头结点的非循环双链表,其每个结点中除了有pred(前驱指针)、data(数据)和next(后继指针)域外,还有一个访问频度域freq。在链表被启用前,其值均初始化为0。每当在链表中进行一次Locate(L, x)运算时,令元素值为x的结点中freq域的值增1,并使此链表中结点保持按访问频度非增(递减)的顺序排列,同时最近访问的结点排在频度相同的结点的前面,以便使频繁访问的结点总是靠近表头。试编写符合上述要求的Locate(L,x)运算的算法,该运算为函数过程,返回找到结点的地址,类型为指针型。​编辑 ​编辑

21.已知一个带有表头结点的单链表,结点结构为[data,link]。假设该链表只给出了头指针list,在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点(k为正整数)。若查找成功,算法输出该结点的data域的值,并返回1;否则,只返回0.​编辑

22.假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时,则可以共享相同的后缀存储空间,例如,“loading”和“being”的存储映像。设str1和str2分别指向两个单词所在单链表的头结点,请设计一个时间上尽可能高效的算法,找出由str1和str2所指向两个链表共同后缀的起始位置。​编辑 ​​

 23.用单链表保存m个整数,结点的结构为[data,link],且|data|<=n(n为正整数)。现要求设计一个时间复杂度尽可能高效的算法,对于链表中data的绝对值相等的结点,仅保留第一次出现的结点而删除其余绝对值相等的结点。​编辑​编辑

24. 设线性表采用带头结点的单链表保存,请设计一个空间复杂度为O(1)且时间上尽可能高效的算法,重新排列L的各结点,得到线性表L'=(a1,an,a2,an-1,a3,an-2,...)。​编辑


​​​​​​​1.设计一个递归算法,删除不带头结点的单链表L中所有制为x的结点。

/*
设计一个递归算法,
删除不带头结点的单链表L中所有制为x的结点。
*/
#include <stdio.h>
#include <stdlib.h>

typedef struct LNode {
	int data;
	struct LNode* Next;
}LNode;

int a[4] = { 1,2,3,4 };
int n = 4;

void buildList(LNode* L)
{
	LNode* s, * r = L;
	r->data = a[0];

	if (n == 1)
		r->Next = NULL;
	else
	{
		for (int i = 1; i < n; i++)
		{
			s = (LNode*)malloc(sizeof(LNode));
			s->data = a[i];
			s->Next = NULL;
			r->Next = s;
			r = r->Next;
		}
	}
}

void display(LNode* L)
{
	LNode* s = L;

	while (s!=NULL)
	{
		printf("%3d", s->data);
		s = s->Next;
	}
	printf("\n");
}

void deleteNum(LNode*& L, int x)
{
	if (L == NULL)
		return;

	LNode* p;

	if (L->data == x)
	{
		p = L;
		L = L->Next;
		free(p);
		deleteNum(L, x);
	}
	else
		deleteNum(L->Next, x);
}

int main()
{
	LNode List;
	LNode* L = &List;

	buildList(L);
	display(L);
	deleteNum(L, 2);
	display(L);

	return 0;
}


2.在带头结点的单链表L中,删除所有值为x的结点,并释放其空间。假设值为x的结点不唯一,试编写算法以实现上述操作。

/*
在带头结点的单链表L中,删除所有值为x的结点,并释放其空间。
假设值为x的结点不唯一,试编写算法以实现上述操作。
*/
#include <stdio.h>
#include <stdlib.h>

typedef struct LNode {
	int data;
	struct LNode* next;
}LNode,*linkList;

int a[4] = { 1,3,6,6 };
int n = 4;

void TailInsert(linkList& L)
{
	L = (linkList)malloc(sizeof(LNode));
	LNode* s,*r=L;

	for (int i = 0; i < n; i++)
	{
		s = (LNode*)malloc(sizeof(LNode));
		s->data = a[i];
		s->next = NULL;
		r->next = s;
		r = r->next;
	}
}

void display(linkList L)
{
	LNode* s = L->next;

	while (s)
	{
		printf("%3d", s->data);
		s = s->next;
	}
	printf("\n");
}

void deleteNum(linkList& L, int x)
{
	LNode* p = L->next, * q, * r = L;

	while (p)
	{
		if (p->data != x)
		{
			r->next = p;
			r = p;
			p = p->next;
		}
		else
		{
			q = p;
			p = p->next;
			free(q);
			r->next = p;
		}
	}
}

int main()
{
	linkList L;
	
	TailInsert(L);
	display(L);
	deleteNum(L, 3);
	display(L);

	return 0;
}


 3.设L为带头结点的单链表,编写算法实现从尾到头反向输出每个结点的值。

/*
设L为带头结点的单链表,编写算法实现从尾到头反向输出每个结点的值。
*/
#include <stdio.h>
#include <stdlib.h>

typedef struct LNode {
	int data;
	struct LNode* next;
}LNode;

int a[4] = { 1,2,3,4 };
int n = 4;

void buildList(LNode *L)
{
	LNode* r = L, * s;

	r->data = a[0];

	if (n == 1)
		r->next = NULL;
	else
	{
		for (int i = 1; i < n; i++)
		{
			s = (LNode*)malloc(sizeof(LNode));
			s->data = a[i];
			r->next = s;
			r = r->next;
		}
		r->next = NULL;
	}
}

void display(LNode* L)
{
	if (L != NULL)
	{
		display(L->next);
		printf("%3d", L->data);
	}
	else
		return;
}

int main()
{
	LNode Head;
	LNode* L = &Head;
	
	buildList(L);
	display(L);

	return 0;
}


 4.试编写在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值结点是唯一的)。

/*
试编写在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值结点是唯一的)
*/
#include <stdio.h>
#include <stdlib.h>

typedef struct lnode {
	int data;
	struct lnode* next;
}lnode, * linklist;

int a[4] = { 23,12,5,34 };
int n = 4;

void buildList(linklist& L)
{
	L = (linklist)malloc(sizeof(lnode));
	lnode* r = L, * s;

	for (int i = 0; i < n; i++)
	{
		s = (lnode*)malloc(sizeof(lnode));
		s->data = a[i];
		r->next = s;
		r = r->next;
	}
	r->next = NULL;
}

void display(linklist L)
{
	lnode* s = L->next;
	
	while (s)
	{
		printf("%3d", s->data);
		s = s->next;
	}
	printf("\n");
}

void deleteMin(linklist& L)
{
	//s是要删除结点的前驱结点
	lnode* p = L->next, * q, * r = L, * s;
	q = p;
	s = r;

	while (p)
	{
		if (p->data < q->data)
		{
			q = p;
			s = r;
		}
		r = p;
		p = p->next;
	}
	s->next = q->next;
	free(q);
}
int main()
{
	linklist L;

	buildList(L);
	display(L);
	deleteMin(L);
	display(L);

	return 0;
}


 5.试编写算法将带头结点的单链表就地逆置,所谓“就地”是指辅助空间复杂度为O(1)。

/*
试编写算法将带头结点的单链表就地逆置,
所谓“就地”是指辅助空间复杂度为O(1)
*/
#include <stdio.h>
#include <stdlib.h>

typedef struct lnode {
	int data;
	struct lnode* next;
}lnode, *linklist;

int a[4] = { 1,2,3,4 };
int n = 4;

void bulidList(linklist& L)
{
	L = (linklist)malloc(sizeof(lnode));
	lnode* r = L, * s;

	for (int i = 0; i < n; i++)
	{
		s = (lnode*)malloc(sizeof(lnode));
		s->data = a[i];
		r->next = s;
		r = r->next;
	}
	r->next = NULL;
}

void display(linklist L)
{
	lnode* s = L->next;

	while (s)
	{
		printf("%3d", s->data);
		s = s->next;
	}
	printf("\n");
}

void reverseList(linklist& L)
{
	lnode* p = L->next, * r;
	L->next = NULL;

	while (p)
	{
		r = p->next;
		p->next = L->next;
		L->next = p;
		p = r;
	}
}

int main()
{
	linklist L;
	
	bulidList(L);
	printf("逆置之前:\n");
	display(L);
	printf("逆置之后:\n");
	reverseList(L);
	display(L);

	return 0;
}

 6.有一个带头结点的单链表L,设计一个算法使其元素递增有序。

/*
有一个带头结点的单链表L,
设计一个算法使其元素递增有序
*/
#include <stdio.h>
#include <stdlib.h>

typedef struct lnode {
	int data;
	struct lnode* next;
}lnode, *linklist;

int a[4] = { 3,7,1,5 };
int n = 4;

void buildList(linklist& L)
{
	L = (linklist)malloc(sizeof(lnode));
	lnode* r = L, * s;

	for (int i = 0; i < n; i++)
	{
		s = (lnode*)malloc(sizeof(lnode));
		s->data = a[i];
		r->next = s;
		r = r->next;
	}
	r->next = NULL;
}

void display(linklist L)
{
	lnode* s = L->next;

	while (s)
	{
		printf("%3d", s->data);
		s = s->next;
	}
	printf("\n");
}

void sortList(linklist& L)
{
	lnode* p = L->next, * r = p->next, * f;
	p->next = NULL;
	p = r;

	while (p)
	{
		r = p->next;
		f = L;
		while (f->next != NULL && f->next->data < p->data)
			f = f->next;
		p->next = f->next;
		f->next = p;
		p = r;
	}
}
int main()
{
	linklist L;
	
	buildList(L);
	printf("递增排序之前:\n");
	display(L);

	sortList(L);
	printf("递增排序之后:\n");
	display(L);

	return 0;
}


7.设在一个带表头结点的单链表中所有元素结点的数据值无序,试编写一个函数,删除表中所有介于给定的两个值(作为函数参数给出)之间的元素(若存在)。

/*
设在一个带表头结点的单链表中所有元素结点的数据值无序,
试编写一个函数,删除表中所有介于给定的两个值(作为函数参数给出)之间的元素(若存在)。
*/
#include <stdio.h>
#include <stdlib.h>

typedef struct lnode {
	int data;
	struct lnode* next;
}lnode, * linklist;

int a[5] = { 1,5,3,4,2 };
int n = 5;

void buildList(linklist& L)
{
	L = (linklist)malloc(sizeof(lnode));
	lnode* s, * r = L;

	for (int i = 0; i < n; i++)
	{
		s = (lnode*)malloc(sizeof(lnode));
		s->data = a[i];
		r->next = s;
		r = r->next;
	}
	r->next = NULL;
}

void display(linklist L)
{
	lnode* s = L->next;

	while (s)
	{
		printf("%3d", s->data);
		s = s->next;
	}
	printf("\n");
}

void deleteNum(linklist& L, int left, int right)
{
	lnode* p = L->next, * r = L;

	while (p)
	{
		if (p->data > left && p->data < right)
		{
			r->next = p->next;
			free(p);
			p = r->next;
		}
		else
		{
			r = p;
			p = p->next;
		}			
	}
}
int main()
{
	linklist L;

	buildList(L);
	printf("删除之前:\n");
	display(L);

	deleteNum(L, 2, 5);
	printf("删除之后:\n");
	display(L);

	return 0;
}


 8.给定两个单链表,编写算法找出两个链表的公共结点。

/*
 给定两个单链表,编写算法找出两个链表的公共结点。
*/
#include <stdio.h>
#include <stdlib.h>

typedef struct lnode {
	int data;
	struct lnode* next;
}lnode, * linklist;

int a[5] = { 2,4,3,7,8 };
int b[4] = { 1,3,7,8 };
int n1 = 5, n2 = 4;

void buildList(linklist& L,int aa[],int n)
{
	L = (linklist)malloc(sizeof(lnode));
	L->data = 0;

	lnode* s, * r = L;

	for (int i = 0; i < n; i++)
	{
		s = (lnode*)malloc(sizeof(lnode));
		s->data = aa[i];
		r->next = s;
		r = r->next;
	}
	r->next = NULL;
}

int lengthList(linklist L)
{
	int len = 0;
	lnode* s = L->next;

	while (s)
	{
		len++;
		s = s->next;
	}
	return len;
}

linklist commonNode(linklist L1, linklist L2)
{
	int len1 = lengthList(L1);
	int len2 = lengthList(L2);
	int dist = 0;
	linklist Long, Short;

	if (len1 > len2)
	{
		Long = L1->next;
		Short = L2->next;
		dist = len1 - len2;
	}
	else
	{
		Long = L2->next;
		Short = L1->next;
		dist = len2 - len1;
	}
	/*
	while(dist--) Long=Long->next;
	*/
	while (dist)
	{
		Long = Long->next;
		dist--;
	}
	while (Long)
	{
		if (Short->data == Long->data&&\
			Long->next->data==Short->next->data)
			return Short;
		else
		{
			Short = Short->next;
			Long = Long->next;
		}
	}
	return NULL;
}

linklist commonNode1(linklist L1, linklist L2)
{
	lnode* s1 = L1->next;

	while (s1)
	{
		lnode* s2 = L2->next;
		while (s2)
		{
			if (s1->data == s2->data && \
				s1->next->data == s2->next->data)
				return s1;
			else
				s2 = s2->next;
		}
		s1 = s1->next;
	}
	return NULL;
}
void display(linklist L)
{
	lnode* s;

	if (L->data == 0)
		s = L->next;
	else
		 s = L;

	while (s)
	{
		printf("%3d", s->data);
		s = s->next;
	}
	printf("\n");
}

int main()
{
	linklist L1, L2;

	buildList(L1, a, n1);
	buildList(L2, b, n2);
	
	printf("L1:");
	display(L1);
	printf("L2:");
	display(L2);
	//两个commonNode都可以实现复杂度不同
	linklist L3 = commonNode1(L1, L2);
	printf("共同结点是:%3d\n", L3->data);
	printf("L3:");
	display(L3);

	return 0;
}


  9.给定一个带表头结点的单链表,设head为头指针,结点的结构为(data,next),data为整型元素,next为指针,试写出算法;按递增次序输出单链表中各结点的数据元素,并释放结点所占存储空间(要求:不允许使用数组作为辅助空间)。

/*
给定一个带表头结点的单链表,
按递增次序输出单链表中各结点的数据元素,
并释放结点所占存储空间(要求:不允许使用数组作为辅助空间)
*/
#include <stdio.h>
#include <stdlib.h>

typedef struct lnode {
	int data;
	struct lnode* next;
}lnode, * linklist;

int a[5] = { 2,5,3,8,1 };
int n = 5;

void buildList(linklist& L)
{
	L = (linklist)malloc(sizeof(lnode));
	lnode* s, * r = L;

	for (int i = 0; i < n; i++)
	{
		s = (lnode*)malloc(sizeof(lnode));
		s->data = a[i];
		r->next = s;
		r = r->next;
	}
	r->next = NULL;
}

void dele
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值