数据结构及单链表例题(下)

news2024/12/24 0:24:26

上次我们已经了解了单链表的数据结构定义以及创建单链表的两种方法,这节介绍几道例题.

文章目录

前言

一、已知L为带头结点的单链表,请依照递归思想实现下列运算

二、单链表访问第i个数据节点

三、在第i个元素前插入元素e

四、删除第i个结点

五、查找带头结点单链表倒数第m个结点并输出(m<链的长度)

六、设单链表表头指针为L,节点数据域为数字(0~9)(字符的思想一样),设计时间复杂度最低的算法判断前n/2个数字是否与后n/2数字一次相同(说人话就是是否前后一样)

 七、从非递减有序的单链表中删除值相同的多余元素

八、设有一个非递减正整数单链表(有重复数)设计算法确定比x小的节点数量

九、删除非递减单链表La中La与Lb相同元素(算法实现了但没验证)

十、已知La,Lb,Lc是三个链表,且他们已经初始化,其元素按递增顺序排序每个表中均无重复数据,设计算法在表Lc中,删除同时出现在La和Lb中的所有元素.(算法实现了但没验证)

十一、带头节点单链表中的所有元素的数据按递增顺序排列,删除链表中大于min且小于max的元素

十二、对链表进行冒泡排序

十三、设L为单链表头节点地址,其数据节点都是正整数可能存在相同的数值的节点,设计一个空间复杂度最低的算法利用直接插入排序把该链表按递增排序,并将重复点删除.

十四、给定两个单链表,编写算法找出两个链表的公共节点(算法实现没验证)

总代码与测试结果

总结


前言

这节课介绍的几道例题是考试中常考的大家应好好理解,我将注释写清楚点.单链表的数据结构定义与头插法和尾插法创建单链表在上节已经实现这节课主要做几道例题,但要想测试例题需要建立单链表,所以大家可以在最后的总代码和结果中查看.其中文章中备注的算法实现了但未验证不代表算法是错的,只是由于实现的前提条件比较困难.

一、已知L为带头结点的单链表,请依照递归思想实现下列运算

  1. 求链表中的最大整数
  2. 求表中的节点数
  3. 求链表所有元素的平均值

求链表中的最大整数

//(1)求链表中的最大整数
int getmax(Linklist L) {
	if (L == NULL) {
		return MIN;//宏定义MIN为一个很小的数例如-999999
	}
	int tmp = getmax(L->next);//获得下一个元素
	return tmp > L->data ? tmp : L->data;//比较两个元素大小
}

这道题要熟悉了解递归

求表中的节点数

//(2)求表中的节点数
int getnodes(Linklist L) {
	if (L == NULL) {
		return 0;//没有节点了返回0
	}
	return 1 + getnodes(L->next);//求和
}

求链表所有元素的平均值

//定义求链表所有元素之和函数
float sum(Linklist L) {//递归求和函数
	if (L == NULL) {
		return 0;
	}
	return L->data + sum(L->next);
}
void operation(Linklist L) {
	int max = getmax(L->next);//带头节点传入第一个数据域
	printf("链表中的最大值为:%d\n", max);
	int num = getnodes(L->next);//带头节点传入第一个数据域
	printf("链表中的节点个数为:%d\n", num);
	float sumnum = sum(L->next);
	printf("链表中元素的和为:%f\n", sumnum);
	float avg = sumnum / num;//总和除以总结点个数
	printf("链表元素的平均值为:%.4lf\n", avg);
}

二、单链表访问第i个数据节点

void getElem(Linklist L, int i, int& e) {
	int j = 0;//计数器
	LNode* p = L;
	while (NULL != p->next) {
		j++;
		if (j == i) {//到第i个节点将值赋给e返回
			e = p->next->data;
			break;
		}
		p = p->next;
	}
}

三、在第i个元素前插入元素e

//例5:在第i个元素前插入元素e
void insertElem(Linklist L, int i, int e) {
	int j = 0;
	LNode* p = L->next;
	LNode* pre = L;//前驱指针
	while (p != NULL) {
		j++;
		if (j == i) {
			LNode* pNode = (LNode*)malloc(sizeof(LNode));
			assert(pNode);
			pNode->data = e;
			pNode->next = pre->next;
			pre->next = pNode;
			break;
		}
		pre = p;
		p = p->next;
	}

}

在单链表插入元素,需要找到插入位置元素的前驱.

核心代码

pNode->next = pre->next;
pre->next = pNode;

四、删除第i个结点

//删除第i个结点
void deleteElem(Linklist L, int i, int &e) {
	int j = 0;
	LNode* p = L->next;
	LNode* pre = L;
	while (p != NULL) {
		j++;
		if (j == i) {
			e = p->data;
			LNode* tmp = p;
			pre->next = p->next;//断链,删除元素的前驱节点指向删除节点的后驱
			free(tmp);//释放结点
			tmp = NULL;
			break;
		}
		pre = p;
		p = p->next;
	}
}

删除节点要释放节点使用free()

五、查找带头结点单链表倒数第m个结点并输出(m<链的长度)

//例6:查找带头结点单链表倒数第m个结点并输出(m<链的长度)
void getData(int m, Linklist L) {
	int j = 0;
	LNode* p = L->next;
	LNode* q = L->next;
	while (p != NULL) {
		j++;
		if (j == m) {
			break;
		}
		p = p->next;
	}
	if (p != NULL) {
		p = p->next;//指向下一个m+1个节点
	}
	while (p != NULL) {
		p = p->next;
		q = q->next;
	}
	if (q != NULL) {
		printf("倒数第%d个元素为:%d\n", m, q->data);
	}
}

查找倒数第m个节点挺常考的,但是也比较简单,知道思想问题就迎刃而解了.

算法思想:定义一个p指针和q指针同时指向首元素,使用指针p寻找第m+1个元素,这样就保证了p指针到q指针之间有m个元素,之后将p,q指针同时往后移这样当p指针为空时,q正好指向倒数第m个元素.

六、设单链表表头指针为L,节点数据域为数字(0~9)(字符的思想一样),设计时间复杂度最低的算法判断前n/2个数字是否与后n/2数字一次相同(说人话就是是否前后一样)

int isSym(Linklist L,int n) {
	int j = 0;
	LNode* p = L->next;
	LNode* q = L->next;
	while (p != NULL) {
		j++;
		if (j == n / 2) {
			break;
		}
		p = p->next;
	}
	if (n % 2 == 0) {//偶数移一位
		p = p->next;
	}
	else {//奇数移两位
		p = p->next->next;
	}
	while (p != NULL) {
		if (q->data != p->data) {
			return 0;
		}
		p = p->next;
		q = q->next;
	}
	return 1;
}

算法思想:前一半和后一半是否一样只需找到后一半的首元素,找到后只需将前一半与后一般元素一一比较即可.但中间有个细节就是链表的长度是奇数还是偶数,分情况讨论.这里我画个图方便大家理解.

 七、从非递减有序的单链表中删除值相同的多余元素

//例8:从非递减有序的单链表中删除值相同的多余元素
void deletesimilar(Linklist L) {
	LNode* preNode = L->next;
	while (preNode!=NULL && NULL != preNode->next) {
		if (preNode->next->data == preNode->data) {
			LNode* p = preNode->next;
			preNode->next = p->next;
			free(p);
			p = NULL;
		}
		else {
			preNode = preNode->next;
		}

	}
}

这道题也非常静经典.

算法思想:从非递减链表中删除重复元素只需遍历元素与前驱元素比较,如果相等就删除节点.大家只要知道思想代码就可以灵活多变.

八、设有一个非递减正整数单链表(有重复数)设计算法确定比x小的节点数量

//例9:设有一个非递减正整数单链表(有重复数)设计算法确定比x小的节点数量
//L:{1,2,2,2,4,6}比4小的节点有2个
int lessNodes(Linklist L, int x) {
	int i = 0;
	LNode* preCur = L;
	LNode* pCur = L->next;
	while (pCur != NULL && pCur->data < x) {
		if (pCur->data != preCur->data) {
			i++;
		}
		preCur = pCur;
		pCur = pCur->next;
	}
	return i;
}

这道题与上道题类似.

算法思想:非递减有重复数,查找比x节点有几个(去掉重复),遍历元素只要当前元素小于x且不等于前驱元素,也就是说出现了新的值,计数器i就++,最后返回i,这道题也就是上道题的变形,思想很重要,可以帮助你解决很多问题.

九、删除非递减单链表La中La与Lb相同元素(算法实现了但没验证)

//例10:删除非递减单链表La中La与Lb相同元素(算法实现了但没验证)
void delsimilar(Linklist La, Linklist Lb) {//在A表上进行修改
	LNode* preCurA = La;
	LNode* pCurA = La->next;
	LNode* pCurB = Lb->next;
	while (pCurA && pCurB) {
		if (pCurA->data < pCurB->data) {//说明与B相等元素在后面,移动A指针
			preCurA = pCurA;//因为在A表上修改记录前驱
			pCurA = pCurA->next;
		}
		else if (pCurA->data > pCurB->data) {说明与A相等元素在后面,移动B指针
			pCurB = pCurB->next;
		}
		else {//相等删除A中当前元素
			preCurA = pCurA->next;
			free(pCurA);
			pCurA = preCurA->next;
		}
	}
}

这道题也比较经典.

算法思想:LA非递减删除LB相同元素,设定两个指针p和q,p指向表A中元素,q指向表B中元素,如果有一方的当前指针指向的元素比另一方小则移动该链表的指针,因为如果想要找到相等的只能在后面元素里面找.

十、已知La,Lb,Lc是三个链表,且他们已经初始化,其元素按递增顺序排序每个表中均无重复数据,设计算法在表Lc中,删除同时出现在La和Lb中的所有元素.(算法实现了但没验证)

//例11:已知La,Lb,Lc是三个链表,且他们已经初始化,其元素按递增顺序排序每个表中均无重复数据,设计算法在表Lc中
//删除同时出现在La和Lb中的所有元素.(算法实现了但没验证)
void deleteOper(LNode*& preCur, LNode*& pCur, ElemType e) {
	while (NULL != pCur && pCur->data < e) {//找到第一个>=e的元素
		preCur = pCur;
		pCur = pCur->next;
	}
	if (pCur!=NULL && e == pCur->data) {//如果等于该元素删除
		preCur = pCur->next;
		free(pCur);
		pCur = preCur->next;
	}
}
void delsimilar2(Linklist La, Linklist Lb, Linklist Lc) {
	LNode* pCurA = La->next;
	LNode* pCurB = Lb->next;
	LNode* preCurC = Lc;
	LNode* pCurC = Lc->next;
	while (pCurA && pCurB) {//寻找LA与LB中相同的元素
		if (pCurA->data < pCurB->data) {
			pCurA = pCurA->next;
		}
		else if(pCurA->data > pCurB->data){
			pCurB = pCurB->next;
		}
		else {
			deleteOper(preCurC, pCurC, pCurA->data);
			pCurB = pCurB->next;
			pCurA = pCurA->next;
		}
	}
}

算法思想:这道题是上一道题的增强版,但是也是比较简单的,就是找LA与LB中相同的元素再去LC表中查找并删除即可.注意一个细节,由于不想从头开始找,所以Lc记录的前驱节点为引用传递,这其实是c++的语法,你可以改为指针,进行址传递,但考试时写伪代码即可.

十一、带头节点单链表中的所有元素的数据按递增顺序排列,删除链表中大于min且小于max的元素

//例12:带头节点单链表中的所有元素的数据按递增顺序排列,删除链表中大于min且小于max的元素
void deleteNodes(Linklist L,int min ,int max) {
	LNode* preCur = L;
	LNode* pCur = L->next;
	while (pCur) {//找到第一个大于min的节点
		if (min < pCur->data) {
			break;
		}
		preCur = pCur;
		pCur = pCur->next;
	}
	while (pCur && pCur->data < max) {//一直删除到大于max
		preCur->next = pCur->next;
		free(pCur);
		pCur = preCur->next;
	}
}

这个比较简单了遍历一次链表就可以了,但要记住删除单链表节点一定要记录前驱节点.

十二、对链表进行冒泡排序

//例13:对链表进行冒泡排序
void bubleSort(Linklist L) {
	while (1) {//每次都从第一个元素开始遇到大于的就交换
		int isExchange = 0;//记录是否元素发生交换
		LNode* p = L->next;
		while (p && p->next) {
			if (p->data > p->next->data) {//交换元素
				ElemType tmp = p->data;
				p->data = p->next->data;
				p->next->data = tmp;
				isExchange = 1;
			}
			p = p->next;
		}
		if (isExchange == 0) {//当前这一次排序没发生交换说明排序已经完成
			break;
		}
	}
}

算法思想:就是冒泡排序的思想这里不用交换节点直接交换数据即可.要注意与数组的冒泡排序不同由于链表在开始前无法知道元素个数,所以用while(1),结束条件就是当链表中不在发生交换说明排序以完成.后续我们在排序算法时还会提及.

十三、设L为单链表头节点地址,其数据节点都是正整数可能存在相同的数值的节点,设计一个空间复杂度最低的算法利用直接插入排序把该链表按递增排序,并将重复点删除.

//例14:设L为单链表头节点地址,其数据节点都是正整数可能存在相同的数值的节点,设计一个空间复杂度最低的算法利用直接插入排序
//把该链表按递增排序,并将重复点删除.
void insertsort(Linklist L) {
	LNode* p = L->next;//先把表提出来
	L->next = NULL;
	while (p != NULL) {
		LNode* preCur = L;
		LNode* pCur = L->next;
		while (pCur && pCur->data < p->data) {//寻找插入位置
			preCur = pCur;
			pCur = pCur->next;
		}
		LNode* tmp = p;//先记录元素节点
		p = p->next;//指针向后
		if (pCur!=NULL && pCur->data == tmp->data) {//如果第一个不小于该元素等于该元素删除节点
			free(tmp);
			tmp = NULL;
		}
		else {//插入节点
			tmp->next = preCur->next;
			preCur->next = tmp;
		}
	}
}

算法思想:采用直接插入排序,这里对直接插入排序不理解的直接跳过即可,这题主要一个思想就是对链表操作时可以将链表断开之后一个元素一个元素的进行操作.

十四、给定两个单链表,编写算法找出两个链表的公共节点(算法实现没验证)

//例15:给定两个单链表,编写算法找出两个链表的公共节点(算法实现没验证)
//定义求链表长度函数
int Length(Linklist L) {
	LNode* p = L->next;
	int length = 0;
	while (p!=NULL) {
		length++;
		p = p->next;
	}
	return length;
}
//寻找公共节点函数
//思想:公共节点只可能在短链的后面节点出现,故长链前的节点不用比较
LNode* search(Linklist La, Linklist Lb) {
	int Lalength = Length(La);
	int Lblength = Length(Lb);
	int dist = 0;
	LNode* shortlist = NULL;
	LNode* longlist = NULL;
	if (Lalength > Lblength) {
		longlist = La->next;
		shortlist = Lb->next;
		dist = Lalength - Lblength;
	}
	else {
		longlist = Lb->next;
		shortlist = La->next;
		dist = Lblength - Lalength;
	}
	while (dist--) {//寻找可能出现公共节点的第一个节点
		longlist = longlist->next;
	}
	while (longlist!=NULL) {//节点依次比较
		if (longlist == shortlist) {
			return longlist;
		}
		else {
			longlist = longlist->next;
			shortlist = shortlist->next;
		}
	}
	return NULL;
}

这道题王道辅导书上的课后题也有.

算法思想:要寻找两个链表的公共节点,第一个公共节点只能在长链中长链长度减短链长度之后.这里简单画个图帮助大家理解.

总代码与测试结果

测试结果有标注对应好.

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<malloc.h>

#define MIN -999999;
typedef int ElemType;

//单链表的数据结构定义
typedef struct LNode {
	ElemType data;//数据
	struct LNode* next;//下一个节点
}LNode,*Linklist;
//使用头插法建立单链表
void CreateLinklist1(Linklist &L,int arr[],int arrlength) {
	L = (LNode*)malloc(sizeof(LNode));//申请一个头节点
	assert(L);
	L->next = NULL;
	for (int i = 0; i < arrlength; i++) {
		LNode*pNode = (LNode*)malloc(sizeof(LNode));
		assert(pNode);
		pNode->data = arr[i];
		pNode->next = L->next;
		L->next = pNode;
	}
}
//使用尾插法建立单链表
void CreateLinklist2(Linklist& L,int arr[],int arrlength) {
	L = (LNode*)malloc(sizeof(LNode));//申请一个头节点
	assert(L);
	L->next = NULL;
	LNode* pTail = L;
	for (int i = 0; i < arrlength; i++) {
		LNode* pNode = (LNode*)malloc(sizeof(LNode));
		assert(pNode);
		pNode->data = arr[i];
		pNode->next = pTail->next;
		pTail->next = pNode;
		pTail = pNode;
	}
}
//打印单链表函数
void print(Linklist L) {
	LNode* p = L->next;
	while (NULL != p) {
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}
//例3:已知L为带头结点的单链表,请依照递归思想实现下列运算
//(1)求链表中的最大整数
int getmax(Linklist L) {
	if (L == NULL) {
		return MIN;
	}
	int tmp = getmax(L->next);
	return tmp > L->data ? tmp : L->data;
}
//(2)求表中的节点数
int getnodes(Linklist L) {
	if (L == NULL) {
		return 0;
	}
	return 1 + getnodes(L->next);
}
//(3)求链表所有元素的平均值
//定义求链表所有元素之和函数
float sum(Linklist L) {
	if (L == NULL) {
		return 0;
	}
	return L->data + sum(L->next);
}
void operation(Linklist L) {
	int max = getmax(L->next);//带头节点传入第一个数据域
	printf("链表中的最大值为:%d\n", max);
	int num = getnodes(L->next);//带头节点传入第一个数据域
	printf("链表中的节点个数为:%d\n", num);
	float sumnum = sum(L->next);
	printf("链表中元素的和为:%f\n", sumnum);
	float avg = sumnum / num;
	printf("链表元素的平均值为:%.4lf\n", avg);
}
//例4:单链表访问第i个数据节点
void getElem(Linklist L, int i, int& e) {
	int j = 0;
	LNode* p = L;
	while (NULL != p->next) {
		j++;
		if (j == i) {
			e = p->next->data;
			break;
		}
		p = p->next;
	}
}
//例5:在第i个元素前插入元素e
void insertElem(Linklist L, int i, int e) {
	int j = 0;
	LNode* p = L->next;
	LNode* pre = L;
	while (p != NULL) {
		j++;
		if (j == i) {
			LNode* pNode = (LNode*)malloc(sizeof(LNode));
			assert(pNode);
			pNode->data = e;
			pNode->next = pre->next;
			pre->next = pNode;
			break;
		}
		pre = p;
		p = p->next;
	}

}
//删除第i个结点
void deleteElem(Linklist L, int i, int &e) {
	int j = 0;
	LNode* p = L->next;
	LNode* pre = L;
	while (p != NULL) {
		j++;
		if (j == i) {
			e = p->data;
			LNode* tmp = p;
			pre->next = p->next;//断链
			free(tmp);//释放结点
			tmp = NULL;
			break;
		}
		pre = p;
		p = p->next;
	}
}
//例6:查找带头结点单链表倒数第m个结点并输出
void getData(int m, Linklist L) {
	int j = 0;
	LNode* p = L->next;
	LNode* q = L->next;
	while (p != NULL) {
		j++;
		if (j == m) {
			break;
		}
		p = p->next;
	}
	if (p != NULL) {
		p = p->next;//指向下一个m+1个节点
	}
	while (p != NULL) {
		p = p->next;
		q = q->next;
	}
	if (q != NULL) {
		printf("倒数第%d个元素为:%d\n", m, q->data);
	}
}
//例7:设单链表表头指针为L,节点数据域为数字(0~9)(字符的思想一样),设计时间复杂度最低的算法判断前n/2
//个数字是否与后n/2数字一次相同(说人话就是是否前后一样)
int isSym(Linklist L,int n) {
	int j = 0;
	LNode* p = L->next;
	LNode* q = L->next;
	while (p != NULL) {
		j++;
		if (j == n / 2) {
			break;
		}
		p = p->next;
	}
	if (n % 2 == 0) {
		p = p->next;
	}
	else {
		p = p->next->next;
	}
	while (p != NULL) {
		if (q->data != p->data) {
			return 0;
		}
		p = p->next;
		q = q->next;
	}
	return 1;
}
//例8:从非递减有序的单链表中删除值相同的多余元素
void deletesimilar(Linklist L) {
	LNode* preNode = L->next;
	while (preNode!=NULL && NULL != preNode->next) {
		if (preNode->next->data == preNode->data) {
			LNode* p = preNode->next;
			preNode->next = p->next;
			free(p);
			p = NULL;
		}
		else {
			preNode = preNode->next;
		}

	}
}
//例9:设有一个非递减正整数单链表(有重复数)设计算法确定比x小的节点数量
//L:{1,2,2,2,4,6}比4小的节点有2个
int lessNodes(Linklist L, int x) {
	int i = 0;
	LNode* preCur = L;
	LNode* pCur = L->next;
	while (pCur != NULL && pCur->data < x) {
		if (pCur->data != preCur->data) {
			i++;
		}
		preCur = pCur;
		pCur = pCur->next;
	}
	return i;
}
//例10:删除非递减单链表La中La与Lb相同元素(算法实现了但没验证)
void delsimilar(Linklist La, Linklist Lb) {
	LNode* preCurA = La;
	LNode* pCurA = La->next;
	LNode* pCurB = Lb->next;
	while (pCurA && pCurB) {
		if (pCurA->data < pCurB->data) {
			preCurA = pCurA;
			pCurA = pCurA->next;
		}
		else if (pCurA->data > pCurB->data) {
			pCurB = pCurB->next;
		}
		else {
			preCurA = pCurA->next;
			free(pCurA);
			pCurA = preCurA->next;
		}
	}
}
//例11:已知La,Lb,Lc是三个链表,且他们已经初始化,其元素按递增顺序排序每个表中均无重复数据,设计算法在表Lc中
//删除同时出现在La和Lb中的所有元素.(算法实现了但没验证)
void deleteOper(LNode*& preCur, LNode*& pCur, ElemType e) {
	while (NULL != pCur && pCur->data < e) {
		preCur = pCur;
		pCur = pCur->next;
	}
	if (pCur!=NULL && e == pCur->data) {
		preCur = pCur->next;
		free(pCur);
		pCur = preCur->next;
	}
}
void delsimilar2(Linklist La, Linklist Lb, Linklist Lc) {
	LNode* pCurA = La->next;
	LNode* pCurB = Lb->next;
	LNode* preCurC = Lc;
	LNode* pCurC = Lc->next;
	while (pCurA && pCurB) {
		if (pCurA->data < pCurB->data) {
			pCurA = pCurA->next;
		}
		else if(pCurA->data > pCurB->data){
			pCurB = pCurB->next;
		}
		else {
			deleteOper(preCurC, pCurC, pCurA->data);
			pCurB = pCurB->next;
			pCurA = pCurA->next;
		}
	}
}
//例12:带头节点单链表中的所有元素的数据按递增顺序排列,删除链表中大于min且小于max的元素
void deleteNodes(Linklist L,int min ,int max) {
	LNode* preCur = L;
	LNode* pCur = L->next;
	while (pCur) {//找到第一个大于min的节点
		if (min < pCur->data) {
			break;
		}
		preCur = pCur;
		pCur = pCur->next;
	}
	while (pCur && pCur->data < max) {//一直删除到大于max
		preCur->next = pCur->next;
		free(pCur);
		pCur = preCur->next;
	}
}
//例13:对链表进行冒泡排序
void bubleSort(Linklist L) {
	while (1) {//每次都从第一个元素开始遇到大于的就交换
		int isExchange = 0;
		LNode* p = L->next;
		while (p && p->next) {
			if (p->data > p->next->data) {
				ElemType tmp = p->data;
				p->data = p->next->data;
				p->next->data = tmp;
				isExchange = 1;
			}
			p = p->next;
		}
		if (isExchange == 0) {
			break;
		}
	}
}
//例14:设L为单链表头节点地址,其数据节点都是正整数可能存在相同的数值的节点,设计一个空间复杂度最低的算法利用直接插入排序
//把该链表按递增排序,并将重复点删除.
void insertsort(Linklist L) {
	LNode* p = L->next;
	L->next = NULL;
	while (p != NULL) {
		LNode* preCur = L;
		LNode* pCur = L->next;
		while (pCur && pCur->data < p->data) {//寻找插入位置
			preCur = pCur;
			pCur = pCur->next;
		}
		LNode* tmp = p;
		p = p->next;
		if (pCur!=NULL && pCur->data == tmp->data) {//如果第一个不小于该元素等于该元素删除节点
			free(tmp);
			tmp = NULL;
		}
		else {//插入节点
			tmp->next = preCur->next;
			preCur->next = tmp;
		}
	}
}
//例15:给定两个单链表,编写算法找出两个链表的公共节点(算法实现没验证)
//定义求链表长度函数
int Length(Linklist L) {
	LNode* p = L->next;
	int length = 0;
	while (p!=NULL) {
		length++;
		p = p->next;
	}
	return length;
}
//寻找公共节点函数
//思想:公共节点只可能在短链的后面节点出现,故长链前的节点不用比较
LNode* search(Linklist La, Linklist Lb) {
	int Lalength = Length(La);
	int Lblength = Length(Lb);
	int dist = 0;
	LNode* shortlist = NULL;
	LNode* longlist = NULL;
	if (Lalength > Lblength) {
		longlist = La->next;
		shortlist = Lb->next;
		dist = Lalength - Lblength;
	}
	else {
		longlist = Lb->next;
		shortlist = La->next;
		dist = Lblength - Lalength;
	}
	while (dist--) {//寻找可能出现公共节点的第一个节点
		longlist = longlist->next;
	}
	while (longlist!=NULL) {//节点依次比较
		if (longlist == shortlist) {
			return longlist;
		}
		else {
			longlist = longlist->next;
			shortlist = shortlist->next;
		}
	}
	return NULL;
}
int main() {
	Linklist L=NULL;
	int arr[10] = { 1,50,88,49,66,13,12,17,19,44 };
	int arrlength = sizeof(arr) / sizeof(arr[0]);
	//使用头插法建立单链表
	CreateLinklist2(L, arr, arrlength);
	printf("输出尾插法链中序列L:");
	print(L);
	printf("**************************************\n");
	printf("对例3进行测试!\n");
	operation(L);
	printf("**************************************\n");
	printf("对例4进行测试!\n");
	int e = 0;
	getElem(L, 4, e);
	printf("e的值为:%d\n", e);
	int a = 777;
	printf("**************************************\n");
	printf("对例5进行测试!\n");
	insertElem(L, 4, a);
	print(L);
	printf("删除第i个节点!\n");
	int b = 0;
	deleteElem(L, 4, b);
	printf("b的值为:%d\n", b);
	print(L);
	printf("**************************************\n");
	printf("对例6进行测试!\n");
	getData(4,L);
	printf("**************************************\n");
	printf("对例7进行测试!\n");
	Linklist La;
	int arr1[11] = { 1,2,3,4,5,6,1,2,3,4,5 };
	int arrlength1 = sizeof(arr1) / sizeof(arr1[0]);
	//使用头插法建立单链表
	CreateLinklist2(La, arr1, arrlength1);
	print(La);
	printf("判断单链表是否对称(是返回1不是为0):%d\n", isSym(La, 11));
	printf("**************************************\n");
	printf("对例8进行测试!\n");
	Linklist Lb;
	int arr2[10] = { 1,1,2,2,3,3,4,4,5,6};
	int arrlength2 = sizeof(arr2) / sizeof(arr2[0]);
	//使用头插法建立单链表
	CreateLinklist2(Lb, arr2, arrlength2);
	printf("删除前:");
	print(Lb);
	deletesimilar(Lb);
	printf("删除后:");
	print(Lb);
	printf("**************************************\n");
	printf("对例9进行测试!\n");
	CreateLinklist2(Lb, arr2, arrlength2);
	printf("比4小的节点个数为:%d\n", lessNodes(Lb, 4));
	printf("**************************************\n");
	printf("对例12进行测试!\n");
	print(Lb);
	deleteNodes(Lb,2,6);
	print(Lb);
	printf("**************************************\n");
	printf("对例13进行测试!\n");
	print(L);
	bubleSort(L);
	print(L);
	printf("**************************************\n");
	printf("对例14进行测试!\n");
	CreateLinklist2(L, arr, arrlength);
	print(L);
	insertsort(L);
	print(L);
	printf("**************************************\n");
	printf("对例15进行测试!\n");
	printf("链表长度为:%d",Length(L));
	return 0;
}


总结

几道关于单链表的题目,希望可以帮助大家,本人制作不易,麻烦点点赞,谢谢家人们.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1372679.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vivado开发FPGA使用流程、教程 verilog(建立工程、编译文件到最终烧录的全流程)

目录 一、概述 二、工程创建 三、添加设计文件并编译 四、线上仿真 五、布局布线 六、生成比特流文件 七、烧录 一、概述 vivado开发FPGA流程分为创建工程、添加设计文件、编译、线上仿真、布局布线&#xff08;添加约束文件&#xff09;、生成比特流文件、烧录等步骤&a…

公司内部核心文件数据\资料防泄密软件系统,防止未经授权文件、文档、图纸、源代码、音视频...等数据资料外泄,自动智能透明加密保护!

为了保护公司内部的核心文件和数据资料&#xff0c;防止未经授权的外泄&#xff0c;使用自动智能透明加密保护软件系统是非常重要的。 这样的系统可以通过以下方式实现防泄密&#xff1a; 自动智能加密&#xff1a;该系统可以对公司内部的核心文件和数据资料进行自动智能加密&…

夏目友人帐OVA:和猫咪老师的初次跑腿、曾几何时下雪之日 2013.12.15

夏目友人帐OVA 1、和猫咪老师的初次跑腿 / ニャンコ先生とはじめてのおつかい2、曾几何时下雪之日 / いつかゆきのひに 1、和猫咪老师的初次跑腿 / ニャンコ先生とはじめてのおつかい 和夏目一起外出的途中&#xff0c;猫咪老师因追蜻蜓遇到了一对迷路的龙凤胎兄妹。猫咪老师不…

僵尸毁灭工程手动存档工具

介绍 这是一个可以对僵毁游戏存档进行备份的小工具&#xff0c;其基本原理是对僵毁存档中数以万计的小文件做哈希值计算并保存下来&#xff0c;下一次备份时再对存档文件进行哈希值计算&#xff0c;每次备份只对两次计算结果中存在差异的文件进行复制与替换从而忽略掉大部分未…

汽车IVI中控开发入门及进阶(十二):手机投屏

前言: 汽车座舱有车载中控大屏、仪表/HUD多屏的显示能力,有麦克风/喇叭等车载环境更好的音频输入输出能力,有方控按键、旋钮等方便的反向控制输入能力,还有高精度的车辆数据等。但汽车座舱中控主机硬件计算能力升级迭代周期相对较长,汽车的应用和服务不够丰富。现在很多汽…

电脑USB接口不同颜色的含义

当你看到笔记本电脑或台式机的USB端口时&#xff0c;你会发现USB端口的颜色很多&#xff1b;这些颜色可不只是为了好看&#xff0c;实际上不同颜色代表着不同的性能&#xff0c;那么这些带颜色的USB端口都是什么含义呢&#xff0c;下面就具体介绍下不同颜色代表的含义。-----吴…

Oracle regexp_substr

select regexp_substr(123|456|789, [^|], 1, 2) from dual;

高性能、可扩展、支持二次开发的企业电子招标采购系统源码

在数字化时代&#xff0c;企业需要借助先进的数字化技术来提高工程管理效率和质量。招投标管理系统作为企业内部业务项目管理的重要应用平台&#xff0c;涵盖了门户管理、立项管理、采购项目管理、采购公告管理、考核管理、报表管理、评审管理、企业管理、采购管理和系统管理等…

固乔快递查询助手:批量、快速、全面的快递信息查询软件

在快递行业飞速发展的今天&#xff0c;如何高效、准确地掌握快递信息成为了很多人的需求。而固乔快递查询助手正是解决这一难题的利器。 固乔快递查询助手是一款专注于快递信息查询的软件&#xff0c;支持多家主流快递公司查询。用户只需输入单号&#xff0c;即可快速查询到实时…

BitMap解析之RoaringBitMap

文章目录 BitMap计算的问题Roaring BitMap原理解析Container 介绍1. ArrayContainer2. BitmapContainer3. RunContainer小结 Roaring BitMap的集合运算1. 两个ArrayContainer的and过程2. 两个BitmapContainer的and过程时空分析 Container的创建与转换为什么说Roaring Bitmap压缩…

关于Django字段类型DateTimeField默认是不是不能为空的测试【DateTimeField学习过程记录】

chatgpt说这个字段默认情况下&#xff1a; blankFalse&#xff0c;nullFalse&#xff0c;也就是在数据库层面和表单层面都不能为空&#xff0c;我们不妨来测试一下在数据库层面是不是这样。 沿用博文 https://blog.csdn.net/wenhao_ir/article/details/135499962的配置。 模型…

科大讯飞星火大模型加持数字员工系列产品发布

面对时代浪潮&#xff0c;基业长青的企业总会率先拥抱变化&#xff0c;在时代交替中创造新的增长空间。当数字化浪潮涌入千行百业&#xff0c;企业掌舵者如何选择转型&#xff1f; 从数字员工到灯塔工厂&#xff0c;愈发成熟的人工智能技术已深入企业管理&#xff0c;持续提高…

Python3 安装教程(windows)

Python &#xff08;官网&#xff09;是这两年来比较流行的一门编程语言。相对简单的语法以及丰富的第三方库。 步骤有三步&#xff1a; 1.下载 Python 安装包 2.安装 Python 3.查验是否安装成功 一.下载 Python 安装包 &#xff08;Python、Sublime 官方下载地址是外国的服…

「超级细菌」魔咒或将打破,MIT 利用深度学习发现新型抗生素

作者&#xff1a;加零 编辑&#xff1a;李宝珠、三羊 MIT 利用图神经网络 Chemprop 识别潜在抗生素&#xff0c;特异性杀死鲍曼不动杆菌。 自然界中充满了各种各样的微生物&#xff0c;例如结核杆菌&#xff08;导致肺结核&#xff09;、霍乱弧菌&#xff08;导致霍乱&#…

1991-2022年A股上市公司股价崩盘风险指标数据

1991-2022年A股上市公司股价崩盘风险指标数据 1、时间&#xff1a;1991-2022年 2、来源&#xff1a;整理自csmar 3、指标&#xff1a;证券代码、交易年度、NCSKEW(分市场等权平均法)、NCSKEW(分市场流通市值平均法)、NCSKEW(分市场总市值平均法)&#xff1b; NCSKEW(综合市…

Android开发基础(一)

Android开发基础&#xff08;一&#xff09; 本篇主要是从Android系统架构理解Android开发。 Android系统架构 Android系统的架构采用了分层的架构&#xff0c;共分为五层&#xff0c;从高到低分别是Android应用层&#xff08;System Apps&#xff09;、Android应用框架层&a…

最新GPT4、AI绘画、DALL-E3文生图模型教程,GPT语音对话使用,ChatFile文档对话总结

一、前言 ChatGPT3.5、GPT4.0、GPT语音对话、Midjourney绘画&#xff0c;文档对话总结DALL-E3文生图&#xff0c;相信对大家应该不感到陌生吧&#xff1f;简单来说&#xff0c;GPT-4技术比之前的GPT-3.5相对来说更加智能&#xff0c;会根据用户的要求生成多种内容甚至也可以和…

Vue 自定义仿word表单录入之单选按钮组件

因项目需要&#xff0c;要实现仿word方式录入数据&#xff0c;要实现鼠标经过时才显示编辑组件&#xff0c;预览及离开后则显示具体的文字。 鼠标经过时显示 正常显示及离开时显示 组件代码 <template ><div class"pager-input flex border-box full-width fl…

006集 正则表达式 re 应用实例—python基础入门实例

正则表达式指预先定义好一个 “ 字符串模板 ” &#xff0c;通过这个 “ 字符串模 板” 可以匹配、查找和替换那些匹配 “ 字符串模板 ” 的字符串。 Python的中 re 模块&#xff0c;主要是用来处理正则表达式&#xff0c;还可以利用 re 模块通过正则表达式来进行网页数据的爬取…

monocle2 fibroblast silicosis inmt

gc() #####安装archr包##别处复制 .libPaths(c("/home/data/t040413/R/x86_64-pc-linux-gnu-library/4.2","/home/data/t040413/R/yll/usr/local/lib/R/site-library", "/usr/local/lib/R/library","/home/data/refdir/Rlib/")).libPa…