王道考研2020练习题 第二章 2.3 链表 C++实现

#include "pch.h"
#include "iostream"
#include "stdio.h"
#include "queue"
#include "math.h"
#include "stack"
#include "string"

using namespace std; 

#define ElemType int
#define VOID	-999999
/*
单链表特点:
它是一种动态的储存结构,链表中每个节点占用的储存空间不是预先分配的,而是运行时系统根据需求生成的
*/
typedef struct LNode
{
	ElemType data;
	struct LNode *next;
}LNode, *LinkList;
/*
	双链表
*/
typedef struct DLNode {
	ElemType data;
	struct DLNode *prior, *next;
	int Freq = 0;
}DLNode, *Double_LinkList;
/*
	循环双链表
*/
typedef struct CDLNode {
	ElemType data;
	struct CDLNode *prior,*next;
}CDLNode,*Circular_Double_LinkList;

struct Result
{
	LinkList head;
	LNode* tail;
};
//结点定义
/*
	创建空双链表(仅有头节点)
*/
void Double_LinkList_VoidHeadCreate(Double_LinkList &L) {
	DLNode s, *p = NULL; int x;
	L = new DLNode;
	p = L;
	L->data = VOID;
	L->next = NULL;
	L->prior = NULL;
}
/*
	双链表头插法
*/
void Double_LinkList_HeadInsert(Double_LinkList &L, ElemType e) {
	DLNode *s;
	s = new DLNode;
	s->data = e;
	s->next = L->next;
	if(L->next!=NULL)
		L->next->prior = s;
	L->next = s;
	s->prior = L;
}
/*
	创建空循环双链表(仅有头节点)
*/
void Circular_Double_LinkList_VoidHeadCreate(Circular_Double_LinkList &L) {
	CDLNode s,*p = NULL; int x;
	L = new CDLNode;
	p = L;
	L->data = VOID;
	L->next = L;
	L->prior = L;
}
/*
	循环双链表头插法
*/
void Circular_Double_LinkList_HeadInsert(Circular_Double_LinkList &L, ElemType e) {
	CDLNode *s;
	s = new CDLNode;
	s->data = e;
	s->next = L->next;
	L->next->prior = s;
	L->next = s;
	s->prior = L;
}
/*
	循环双链表尾插法
*/
void Circular_Double_LinkList_TailInsert(Circular_Double_LinkList &L, ElemType e) {
	CDLNode *s;
	s = new CDLNode;
	s->data = e;
	s->prior = L->prior;
	L->prior->next = s;
	L->prior = s;
	s->next = L;
}
/*
	创建循环单链表(仅有头节点)
*/
void Circular_List_VoidHeadCreate(LinkList &L, LNode *&tail) {
	struct LNode s; int x;
	L = new LNode;;
	L->data = VOID;
	L->next = L;
	tail = L;
}
/*
	循环头插法
*/
void Circular_List_HeadInsert(LinkList &L, ElemType e, LNode *&tail) {
	LNode *s;
	s = new LNode;;
	s->data = e;
	if (L->data == VOID) {
		if (tail == L) {
			tail = s;
		}
		s->next = L->next;
		L->next = s;
	}
	else {
		s->next = L;
		L = s;
	}
}
/*
	创建空单链表(仅有头节点)
*/
void List_VoidHeadCreate(LinkList &L, LNode *&tail) {
	struct LNode s; int x;
	L = new LNode;;
	L->data = VOID;
	L->next = NULL;
	tail = L;
}
/*
	头插创表法
*/
void List_HeadCreate(LinkList &L,LNode *&tail) {
	LNode *s; int x;
	bool tailCatch = true;
	L = new LNode;
	L->data = VOID;
	L->next = NULL;
	cin >> x;
	while (x != 9999) {
		s = new LNode;
		if (tailCatch) {
			tail = s;
			tailCatch = false;
		}
		s->data = x;
		s->next = L->next;
		L->next = s;
		cin >> x;
	}
}
/*
	无头节点头插创表法
*/
void List_HeadlessCreate(LinkList &L, LNode *&tail) {
	LNode *s; int x;
	bool tailCatch = true;
	cin >> x;
	if (x == 9999)
		return;
	L = new LNode;
	L->data = x;
	L->next = NULL;
	cin >> x;
	while (x != 9999) {
		s = new LNode;
		if (tailCatch) {
			tail = s;
			tailCatch = false;
		}
		s->data = x;
		s->next = L;
		L = s;
		cin >> x;
	}
}
/*
	无头节点头插创表法,仅初始化
*/
void List_HeadlessCreate_NoInput(LinkList &L, LNode *&tail,ElemType e) {
	if (e == 9999)
		return;
	L = new LNode;
	L->data = e;
	L->next = NULL;
	tail = L;
}
/*
	尾插创表法(参数传tail)
*/
Result List_TailCreate(LinkList L, LNode * tail) {
	Result ret;
	LNode *s, *r = L; int x;
	L = (LinkList)malloc(sizeof(LNode));
	L->next = NULL;
	cin >> x;
	while (x != 9999) {
		s = (LNode*)malloc(sizeof(LNode));
		s->data = x;
		r->next = s;
		r = s;
		cin >> x;
	}
	r->next = NULL;
	tail = r;
	ret.head = L;
	ret.tail = tail;
	return ret;
}
/*
	按序号获取元素
*/
LNode* GetElem(LinkList L, int i) {
	int j = 1;
	LNode *p = L->next;
	if (i == 0)
		return L;
	if (i < 1)
		return NULL;
	while (p&&j < i) {
		p = p->next;
		j++;
	}
	return p;

}
/*
	根据值查找元素
*/
LNode* LocateElem(LinkList L, ElemType e) {
	LNode *p = L->next;
	while (p != NULL && p->data != e) {
		p = p->next;
	}
	return p;
}

/*
	头插法
*/
void List_HeadInsert(LinkList &L, ElemType e, LNode *&tail) {
	LNode *s;
	s = new LNode;;
	s->data = e;
	if(L->data == VOID){
		if (tail == L) {
			tail = s;
		}
		s->next = L->next;
		L->next = s;
	}
	else {
		s->next = L;
		L = s;
	}
}
/*
	尾插法
*/
void List_TailInsert(ElemType e, LNode *&tail) {
	LNode *s;
	s = new LNode;;
	s->data = e;
	tail->next = s;
	tail = s;
	tail->next = NULL;
}
/*
	打印单链表
*/
void PrintList(LinkList L) {
	if (L == NULL)
		return;
	LNode* p = L->next; int count = 0;
	cout << ("单链表数据为:");
	if (L->data != VOID) {//如果无头节点
		cout << "[" << count++ << "]" << L->data << " " ;
	}
	while (p != NULL) {
		cout << "[" << count++ << "]" << p->data << " ";
		p = p->next;
	}
	cout << endl;
}
/*
	打印双链表
*/
void PrintList(Double_LinkList &L) {
	if (L == NULL)
		return;
	DLNode* p = L->next; int count = 0;
	cout << ("单链表数据为:");
	if (L->data != VOID) {//如果无头节点
		cout << "[" << count++ << "]" << L->data << " ";
	}
	while (p != NULL) {
		cout << "[" << count++ << "]" << p->data << " ";
		p = p->next;
	}
	cout << endl;
}
/*
	打印循环双链表
*/
void PrintList(Circular_Double_LinkList &L) {
	if (L == NULL)
		return;
	CDLNode* p = L->next; int count = 0;
	cout << ("单链表数据为:");
	if (L->data != VOID) {//如果无头节点
		cout << "[" << count++ << "]" << L->data << " ";
	}
	while (p!=L) {
		cout << "[" << count++ << "]" << p->data << " ";
		p = p->next;
	}
	cout << endl;
}
/*
	对链表进行排序,正序s
*/
void SoftList(LinkList &L,LNode *&LTail) {
	LNode *p = L->next, *pre = NULL;
	LNode *r = p->next;
	p->next = NULL;
	p = r;
	while (p != NULL) {
		r = p->next;
		pre = L;
		/*扫描pre的A组,如果P->data < p->data,则将pre往后移扫描下一个,直到发现当前指针的值>=需要插入
		的值时,将需要插入的值插入到这个大于插入值的元素之前,如果下一个指针为空,则代表需要插入的值
		大于整个A组,将该值插入到末尾*/
		while (pre->next != NULL && pre->next->data < p->data)
			pre = pre->next;
		p->next = pre->next;		//插入到pre与pre->next之间(pre->next==NULL时,插入到最后一个)
		pre->next = p;
		p = r;
	}
	LTail = pre;
}
/*
	清空双链表,仅留头节点
*/
void ClearList(Double_LinkList &L) {
	DLNode *p = L->next, *r;
	while (p != NULL) {
		r = p->next;
		free(p);
		p = r;
	}
	L->data = VOID;
	L->next = NULL;
	L->prior = NULL;
}
/*
	清空循环双链表,仅留头节点
*/
void ClearList(Circular_Double_LinkList &L) {
	CDLNode *p = L->next, *r;
	while (p != L) {
		r = p->next;
		free(p);
		p = r;
	}
	L->data = VOID;
	L->next = L;
	L->prior = L;
}
/*
	清空链表,仅留头节点
*/
void ClearList(LinkList &L, LNode *&LTail) {
	LNode *p = L->next,*r;
	while (p != NULL) {
		r = p->next;
		free(p);
		p = r;
	}
	L->data = VOID;
	L->next = NULL;
	LTail = L;
}
/*
	反回单链表长度
*/
int GetLength(LinkList &L) {
	int count = 0;
	LNode* p = L;
	while (p->next != NULL) {
		count++;
		p = p->next;
	}
	return count;
}
/*
	递归删除不带头节点的单链表L中所有X的节点

	时间复杂度O(n) 空间复杂度O(1)
*/
void Mos_2_3_1(LinkList &L,ElemType x) {
	LNode* p;
	if (L == NULL)
		return;
	if (L->data == x) {
		p = L;
		L = L->next;	//此处L是引用,所以改变L的值,会改变原L的前驱的next的值
		free(p);
		Mos_2_3_1(L, x);
	}
	else
		Mos_2_3_1(L->next, x);
}
/*
	递归删除带头节点的单链表L中所有X的节点

	时间复杂度O(n) 空间复杂度O(1)
*/
void Mos_2_3_2(LinkList &L, ElemType x) {
	LNode* p;
	if (L == NULL)
		return;
	if (L->data == VOID) //跳过头节点
		Mos_2_3_2(L->next, x);
	if (L->data == x) {
		p = L;
		L = L->next;
		free(p);
		Mos_2_3_2(L, x);
	}else
		Mos_2_3_2(L->next, x);
}
/*
	反向输出带头节点的单链表L

	算法思想:
	利用递归思想,先获取到最后一个节点进行输出

	时间复杂度O(n) 空间复杂度O(1)
*/
void Mos_2_3_3(LinkList &L) {
	if (L->data == VOID)		//头节点位置做前置输出,可省略
		cout << "该链表数据逆置后为:";
	if (L == NULL)
		return;
	if (L->next != NULL)
		Mos_2_3_3(L->next);		//先递归
	if (L->data != VOID)
		cout << L->data << " ";	//再输出
	else						//头节点位置做后置输出,可省略
		cout << endl;
}
/*
	找到带头节点单链表L中最小的节点,并删除

	算法思想:
	用一个指针纪录最小的节点,在扫描结束后删除该节点
	注这个指针最好是纪录最小节点的前一个节点,方便在扫描后直接删除
*/
void Mos_2_3_4(LinkList &L) {
	LNode* p = L,*q = L->next,*n;
	while (p->next != NULL) {
		if (p->next->data < q->next->data) {
			q = p;
		}
		p = p->next;
	}
	n = q->next;
	q->next = q->next->next;
	free(n);
}
/*
	将带头节点的单链表L逆置

	算法思想:
	用指针纪录前一个元素与后一个元素,然后使自己的next等于前一个元素,然后到下一个元素重复该过程,
	直到当前元素为空,代表已经全部逆置,将头节点指向当前元素(原本的最后一个元素)
	注:第一个元素的前置为NULL

	时间复杂度O(n) 空间复杂度O(1)

*/
void Mos_2_3_5(LinkList &L,LNode *&tail/*该部分用于保存尾指针,可去掉*/) {
	if (!L->next)
		return;
	LNode* p = L->next,*q,*r = NULL;
	tail = p;/*该部分用于保存尾指针,可去掉*/
	while (p != NULL) {
		q = p->next;
		p->next = r;
		r = p;
		p = q;
	}
	L->next = r;
}
/*
	使一个带头节点的单链表L递增有序

	算法思路:
	1、将原链表分成两个链表(充分利用空间),使头节点的下一指针为NULL作A链表
	2、扫描剩下的B链表(外循环),利用指针Pre将B链表的第一个元素依次与A链表中的元素比较,进入内循环
	3、比较结果分三种情况
	(1)、如果该元素小于A链表的值(pre->next),则使指针向后跳,比较下一个元素
	(2)、如果该元素大于等于A链表的值,则代表找到了插入的位置,跳出内循环
	到A链表对应位置中
	(3)、如果A链表空了(即pre->next==NULL)代表该值在A链表中为最大的值,跳出内循环
	4、跳出内循环后,将B链表的第一个值插入到对应位置,将B链表的头指针往后跳
	5、判断B链表是否为空,若为空,则跳出外循环,若不为空,则继续插入

	时间复杂度O(n^2) 空间复杂度O(1)
*/
void Mos_2_3_6(LinkList &L) {
	LNode *p = L->next, *pre;
	LNode *r = p->next;
	p->next = NULL;
	p = r;
	while (p != NULL) {
		r = p->next;
		pre = L;
		/*扫描pre的A组,如果P->data < p->data,则将pre往后移扫描下一个,直到发现当前指针的值>=需要插入
		的值时,将需要插入的值插入到这个大于插入值的元素之前,如果下一个指针为空,则代表需要插入的值
		大于整个A组,将该值插入到末尾*/
		while (pre->next != NULL && pre->next->data < p->data)	
			pre = pre->next;
		p->next = pre->next;		//插入到pre与pre->next之间(pre->next==NULL时,插入到最后一个)
		pre->next = p;
		p = r;
	}
}
/*
	部分修改
*/
void Mos_2_3_6_1(LinkList &L) {
	LNode *p = L->next,*pre,*r;
	L->next = NULL;
	while (p != NULL) {
		r = p->next;
		pre = L;
		/*扫描pre的A组,如果P->data < p->data,则将pre往后移扫描下一个,直到发现当前指针的值>=需要插入
		的值时,将需要插入的值插入到这个大于插入值的元素之前,如果下一个指针为空,则代表需要插入的值
		大于整个A组,将该值插入到末尾*/
		while (pre->next != NULL && pre->next->data < p->data) {
			pre = pre->next;
		}
		p->next = pre->next;	//插入到pre与pre->next之间(pre->next==NULL时,插入到最后一个)
		pre->next = p;
		p = r;
	}
}
/*
	删除带头节点的单链表中值在left与right范围内的元素

	时间复杂度O(n) 空间复杂度O(1)
*/
void Mos_2_3_7(LinkList &L, ElemType left, ElemType right,LNode *&tail/*该部分用于保存尾指针,可去掉*/) {
	LNode* r, *p = L->next,*q = L;
	while (p->next != NULL) {
		r = p->next;
		if (p->data > left&&p->data < right) {
			q->next = r;
			free(p);
		}
		else {
			q = q->next;
		}
		p = r;
	}
	tail = p;/*该部分用于保存尾指针,可去掉*/
}
/*
	将BL的第BLoc(从0开始)元素的next变为AL的第ALoc元素的next
	即将AL的第ALoc以后的元素拼接到BL的BLoc之后,为2-3-8题做准备

	时间复杂度O(ALoc+BLoc) 空间复杂度O(1)
*/
bool Mos_2_3_8_1(LinkList &AL, LinkList &BL,int ALoc,int BLoc) {
	LNode *ap = AL, *bp =BL;
	for (int i = 0; i < ALoc; i++) {
		if (ap->next != NULL)
			ap = ap->next;
		else
			return false;
	}
	for (int i = 0; i < BLoc; i++) {
		if (bp->next != NULL)
			bp = bp->next;
		else
			return false;
	}
	bp->next = ap->next;
}
/*
	找出AL与BL相同的第一个节点(地址相同)

	算法思想:
	由于如果AL与BL如果有节点相同,则后继节点皆相同,且相同节点的长度相同,所以
	len(AL)= len(AL不同节点)+len(相同节点)
	len(BL)= len(BL不同节点)+len(相同节点)
	若len(AL)>len(BL),则代表len(AL不同节点)>len(BL不同节点),且len(AL)-len(BL)=len(AL不同节点)-len(BL不同节点),
	BL同理,所以先让len更大的链表先向后推abs(len(AL)-len(BL))个,则len(长的链表所剩不同节点)=len(短的链表不同节点)
	同时向后推,找到第一个相同节点,则为AL与BL的共同节点

	时间复杂度O(len(AL)+len(BL))(需要算出AL与BL长度) 空间复杂度O(1)
*/
LNode* Mos_2_3_8(LinkList &AL, LinkList &BL) {
	int len1 = GetLength(AL), len2 = GetLength(BL);
	LNode *p1 =AL, *p2 = BL;
	if (len1 < len2) {
		for (int i = 0; i < len2 - len1; i++) {
			p2 = p2->next;
		}
	}
	else {
		for (int i = 0; i < len1 - len2; i++) {
			p1 = p1->next;
		}
	}
	for (int i = 0; i < abs(len1 - len2); i++) {
		if (p1->next == p2->next) {
			return p1->next;
		}
		p1 = p1->next;
		p2 = p2->next;
	}
	return NULL;
}
/*
	按次序输出L中的元素,并释放节点的空间

	算法思想:
	双重遍历输出,并释放

	时间复杂度O(n^2) 空间复杂度O(1)
*/
void Mos_2_2_9(LinkList &L) {
	LNode *p = L->next, *pre = L;
	cout <<  "按顺序输出L:";
	while (L->next != NULL) {
		p = L->next;
		pre = L;
		while (p->next != NULL) {
			if (p->next->data < pre->next->data) {
				pre = p;
			}
			p = p->next;
		}
		cout << pre->next->data << " ";
		p = pre->next;
		pre->next = pre->next->next;
		free(p);
	}
	cout << endl;
}
/*
	将一个带头节点的A单链表拆分成A B两表,A存放序号为奇数的元素,B存放序号为偶数的元素

	算法思想:
	四个指针一个代表分类后的A一个代表分类后的B,一个代表当前扫描位置,一个保存下一个位置
	结束循环后要p->next =NULL,q->next = NULL,将A B的末尾断链

	时间复杂度O(len(AL)) 空间复杂度O(1)
*/
void Mos_2_2_10(LinkList &AL, LNode *&ALTail, LinkList &BL, LNode *&BLTail) {
	LNode *p = AL, *q = BL,*r,*s = AL->next;
	int count = 0;
	while (s != NULL) {
		if (s->next != NULL)
			r = s->next;
		else
			r = NULL;
		if (count++ % 2 == 0) {
			q->next = s;
			q = q->next;
		}
		else {
			p->next = s;
			p = p->next;
		}
		s = r;
	}
	p->next = NULL;
	q->next = NULL;
	ALTail = p;
	BLTail = q;
}
/*
	将AL分成两个链表,其中偶数位归于AL,奇数位置归于BL,但是BL需要逆置

	算法思想:
	与10题类似,仅在插入BL时倒着插
	在结尾时,让BL->next = q,最后一位为第一位

	时间复杂度O(len(AL)) 空间复杂度O(1)
*/
void Mos_2_2_11(LinkList &AL, LNode *&ALTail, LinkList &BL) {
	LNode *p = AL, *q = NULL, *r, *s = AL->next;
	int count = 0;
	while (s != NULL) {
		r = s->next;
		if (count++ % 2 == 0) {
			p->next = s;
			p = p->next;
		}
		else {
			s->next = q;
			q = s;
		}
		s = r;
	}
	p->next = NULL;
	BL->next = q;
	ALTail = p;
}
/*
	对一个有序链表去重

	算法思想:
	对比当前指针数据和下一个指针数据是否相同,相同则p->next = 下一个指针的next,并释放下一个指针

	时间复杂度O(n) 空间复杂度O(1)
*/
void Mos_2_2_12(LinkList &L, LNode *&LTail) {
	LNode *p = L,*pre;
	while (p->next!=NULL) {
		if(p->next->data == p->data){
			pre = p->next;
			p->next = pre->next;
			free(pre);
		}
		else {
			p = p->next;
		}
	}
	LTail = p;
}
/*
	将有序链表AL与BL,按从大到小的顺序放回AL

	算法思想:
	一个指针指向新AL,一个指向AL的扫描值,一个指向BL的扫描值,
	如果BL的扫描值不为空,且AL扫描值为空,或者AL的值大于BL的值,则反向将BL的节点指向新AL的最后一个节点,
	注意保存下一个扫描值,反之亦然
	当AL与BL都为空时跳出

	时间复杂度O(len(AL)+Len(BL)) 空间复杂度O(1)
*/
void Mos_2_2_13(LinkList &AL,  LinkList &BL) {
	LNode *p = AL->next, *q = BL->next,*s = NULL,*r = NULL;
	while (p != NULL || q != NULL) {
		if (q != NULL && (p == NULL || p->data >  q->data)) {
			r = q->next;
			q->next = s;
			s = q;
			q = r;
		}
		if (p != NULL && (q == NULL || q->data >= p->data)) {
			r = p->next;
			p->next = s;
			s = p;
			p = r;
		}
	}
	AL->next = s;
}
/*
	将两个递增有序链表A与B中的公共元素提出新建到C表

	算法思想:
	不停滚动AL与BL的扫描指针,发现相同置入C表

	时间复杂度O(len(AL)+len(BL)) 空间复杂度(len(AL)+len(BL))(需要新建一个表接AL与BL的结果)
*/
void Mos_2_2_14(LinkList &AL, LinkList &BL,LinkList &CL,LNode *&CLTail) {
	CL = new LNode;
	CL->data = VOID;
	LNode *p = AL->next, *q = BL->next, *r = CL;
	while(p!=NULL&&q!=NULL){
		if (p->data == q->data) {
			r->next = new LNode;
			r->next->data = p->data;
			r = r->next;
			p = p->next;
			q = q->next;
		}
		else {
			if (p->data < q->data) {
				p = p-> next;
			}
			else {
				q = q-> next;
			}
		}
	}
	r->next = NULL;
	CLTail = r;
}
/*
	求A与B链表的交集(对应位置相同的元素)放回A

	算法思想:
	依次扫描,并放回A,同时清除A链表不是交集的节点

	时间复杂度O(len(AL)+len(BL)) 空间复杂度(1)
*/
void Mos_2_2_15(LinkList &AL, LNode *&aLTail, LinkList &BL) {
	LNode *p = AL->next, *q = BL->next,*r = NULL,*s = AL;
	while (p != NULL && q != NULL) {
		r = p->next;
		if (p->data == q->data) {
			s->next = p;
			s = s->next;
		}
		else {
			free(p);
		}
		p = r;
		q = q->next;
	}
	s->next = NULL;
	aLTail = s;
	while (p != NULL) {
		r = p->next;
		free(p);
		p = r;
	}

}
/*
	判断BL是不是AL的连续子序列

	算法思想:
	双循环,外部纪录AL的指针,然后每次内循环结束pre = pre->next
	内循环判断BL的指针q是否为空,不是则比较下一个p和q,若q为空代表时连续子序列
	当pre为空时,代表没有连续子序列

	时间复杂度O(len(AL)*len(BL)) 空间复杂度O(1)
*/
bool Mos_2_2_16(LinkList &AL, LinkList &BL) {
	LNode *p = AL->next, *q = BL->next,*pre = AL->next;
	bool b = true;
	while (pre != NULL ) {
		p = pre;
		q = BL->next;
		b = true;
		while (q != NULL) {
			if (p == NULL) {
				b = false;
				break;
			}
			if (p->data != q->data){
				b = false;
				break;
			}
			p = p->next;
			q = q->next;
		}
		if (b) {
			return true;
		}
		else {
			pre = pre->next;
		}
	}
	return false;
}
/*
	判断循环双链表CL是否对称

	算法思想:
	两个指针分别从头尾(除开头指针)出发(方向相反),如果头不等于尾则代表该位置不对称,一直找到两个指针相等或者
	从头出发的指针的下一个等于从尾出发的指针为止

	时间复杂度O(n) 空间复杂度O(1)
*/
bool Mos_2_2_17(CDLNode *&CL) {
	CDLNode *p = CL->next,*q = CL->prior;
	if (p == CL)
		return false;
	while (p != q ) {
		if (p->data != q->data) {
			return false;
		}
		if (p->next == q)
			return true;
		p = p->next;
		q = q->prior;
	}
	return true;
}
/*
	将BL拼接到AL上
*/
void Mos_2_2_18(CDLNode *&CAL, CDLNode *&CBL) {
	CBL->prior->next = CAL;
	CAL->prior->next = CBL->next;
	CBL->next->prior = CAL->prior;
	CAL->prior = CBL->prior;
	CBL->next = CBL;
	CBL->prior = CBL;
}
/*
	按顺序输出循环双链表的元素,输出后删除

	时间复杂度O(n) 空间复杂度O(1)
*/
void Mos_2_2_19(CDLNode *&CL) {
	CDLNode *p = CL->next, *min = p,*r=NULL,*leftMin = NULL;
	int count = 0;
	cout << "按大小顺序输出CL:";
	while (CL->next != CL) {
		p = CL->next;
		min = p;
		leftMin = CL;
		while (p != CL) {
			if (min->data > p->data) {
				min = p;
				leftMin = r;
			}
			r = p;
			p = p->next;
		}
		cout << "[" << count++ << "]" << min->data << " ";
		leftMin->next = min->next;
		min->next->prior = leftMin;
		free(min);
	}
	free(CL);
}
void Mos_2_2_20(DLNode *&DL,ElemType x) {
	DLNode *p = DL->next,*r;
	while (p != NULL) {
		r = p->next;
		if (p->data == x) {
			p->Freq += 1;
			DLNode *q = p->prior;
			while (q != DL) {
				if (q->Freq <= p->Freq) {
					q->prior->next = p;
					p->next->prior = q;
					q->next = p->next;
					p->prior = q->prior;
					p->next = q;
					q->prior = p;
					q = p->prior;
				}
				else {
					break;
				}
			}
		}
		p = r;
	}
}
/*
	输出L的倒数第k个元素,若有返回1,无返回0

	算法思想:
	设有p与q两个指针,p自头向尾遍历,当p=尾指针的NULL时,可知倒数第k个指针与p之间的距离为k
	于是,当p指向第k个元素(正着数)时,令q同步自头向尾遍历,当p指向尾指针的NULL时,q刚好指向倒数第k个指针

	时间复杂度O(n) 空间复杂度O(1)
*/
int Mos_2_2_21(LNode *&L, int k) {
	int count = 1;
	LNode *p = L->next, *q=L;
	while (p != NULL) {
		if (count < k) {
			count++;
		}
		else {
			q = q->next;
		}
		p = p->next;
	}
	if (count < k) {
		return 0;
	}
	else {
		cout << "倒数第" << k << "个元素为" << q->data << endl;
		return 1;
	}

}
/*
	找出A链表与B链表的第一个共同元素

	算法设计:
	同2-3-8算法

	时间复杂度O(Max(len(AL),len(BL)) 空间复杂度O(1)
*/
LNode* Mos_2_2_22(LNode *&AL, LNode *&BL) {
	LNode *p = AL->next, *q = BL->next;
	int len1 = GetLength(AL), len2 = GetLength(BL),count = 0;
	if (len1 < len2) {
		for (int i = 0; i < len2 - len1; i++) {
			q = q->next;
		}
	}
	else {
		for (int i = 0; i < len1 - len2; i++) {
			p = p->next;
		}
	}
	while (p != NULL) {
		if (p->data == q->data) {
			return p;
		}
		p = p->next;
		q = q->next;
		count++;
	}
	return NULL;

}
/*
	删除L的所有绝对值重复的元素

	算法设计:
	利用空间换时间,用数组来判断这个链表元素是否出现过,出现则删除

	空间复杂度O(n) 空间复杂度O(n)
*/
void Mos_2_2_23(LNode *&L,int n) {
	ElemType *integer = new int[n+1];
	for (int i = 0; i < n + 1; i++) {
		integer[i] = 0;
	}
	LNode *p = L->next,*pre = L,*r;
	while (p != NULL) {
		r = p->next;
		if (integer[abs(p->data)] == 0) {
			integer[abs(p->data)]++;
			pre = p;
		}
		else {
			pre->next = p->next;
			free(p);
		}
		p = r;
	}
}
int main() {
	LinkList AL = NULL;
	LNode* ALTail = NULL;
	LinkList BL = NULL;
	LNode* BLTail = NULL;
	LinkList CL = NULL;
	LNode* CLTail = NULL;
	LinkList DL = NULL;
	LNode* DLTail = NULL;
	LinkList EL = NULL;
	LNode* ELTail = NULL;
	Circular_Double_LinkList CAL = NULL;
	Circular_Double_LinkList CBL = NULL;
	Double_LinkList DAL = NULL;
	Circular_Double_LinkList_VoidHeadCreate(CAL);
	Circular_Double_LinkList_VoidHeadCreate(CBL);
	Double_LinkList_VoidHeadCreate(DAL);
	//List_HeadCreate(BL, BLTail);
	List_VoidHeadCreate(BL, BLTail);
	//List_VoidHeadCreate(EL, ELTail);
	List_HeadlessCreate_NoInput(AL, ALTail,3);
	//PrintList(l);
	for (int i = 2; i < 4; i++) {
		List_HeadInsert(AL, i, ALTail);
		List_HeadInsert(BL, i, BLTail);
	}
	for (int i = 2; i < 4; i++) {
		List_TailInsert(i, ALTail);
		List_TailInsert(i, BLTail);
	}

	/*						练习题2-3-1						*/
	//cout << endl << "练习题2-3-1" << endl;
	//PrintList(AL);
	//Mos_2_3_1(AL, 3);//会丢失尾指针 影响后续结果 使用时去掉注释
	//PrintList(AL);
	//cout << endl;

	/*						练习题2-3-2						*/
	//cout << endl << "练习题2-3-2" << endl;
	//PrintList(BL);
	//Mos_2_3_2(BL, 3);//会丢失尾指针 影响后续结果 使用时去掉注释
	//PrintList(BL);
	//cout << endl;

	/*						练习题2-3-3						*/
	cout << endl << "练习题2-3-3" << endl;
	for (int i = 2; i < 4; i++) {
		List_TailInsert(i, BLTail);
	}
	List_TailInsert(1, BLTail);
	PrintList(BL);
	Mos_2_3_3(BL);
	cout << endl;

	/*						练习题2-3-4						*/
	//cout << endl << "练习题2-3-4"<< endl;
	//for (int i = 2; i < 4; i++) {
	//	List_TailInsert(i, BLTail);
	//}
	//PrintList(BL);
	//Mos_2_3_4(BL);//会丢失尾指针 影响后续结果 使用时去掉注释
	//PrintList(BL);
	//cout << endl;

	/*						练习题2-3-5						*/
	cout << endl << "练习题2-3-5" << endl;
	for (int i = 4; i < 7; i++) {
		List_TailInsert(i, BLTail);
	}
	PrintList(BL);
	Mos_2_3_5(BL,BLTail);
	PrintList(BL);
	cout << endl;

	/*						练习题2-3-6					*/
	//cout << endl << "练习题2-3-6" << endl;
	//PrintList(BL);
	//Mos_2_3_6_1(BL);//会丢失尾指针 影响后续结果 使用时去掉注释
	//PrintList(BL);
	//cout << endl;

	/*						练习题2-3-7					*/
	cout << endl << "练习题2-3-7" << endl;
	PrintList(BL);
	Mos_2_3_7(BL, 2, 4, BLTail);
	PrintList(BL);
	cout << endl;

	/*						练习题2-3-8					*/
	cout << endl << "练习题2-3-8" << endl;
	List_VoidHeadCreate(CL, CLTail);
	for (int i = 2; i < 4; i++) {
		List_HeadInsert(CL, i, CLTail);
	}
	cout <<  "BL,CL拼接前:" << endl;
	PrintList(BL);
	PrintList(CL);
	cout << "BL,CL拼接后:" << endl;
	Mos_2_3_8_1(BL, CL, 3, 1);//会丢失CL的尾指针 影响后续结果 后续使用CL时加上注释
	PrintList(BL);
	PrintList(CL);
	LNode *mos_2_3_8_var = Mos_2_3_8(BL, CL);
	if (mos_2_3_8_var != NULL)
		cout << "第一个相同的节点为:地址{" << mos_2_3_8_var << "} 值{" << mos_2_3_8_var->data << "}" << endl;
	else
		cout << "没有相同的节点" << endl;
	cout << endl;

	/*						练习题2-3-9					*/
	//cout << endl << "练习题2-3-9" << endl;
	//Mos_2_2_9(CL);//会清空CL 若2-2-8开启,会同时清空BL后续  影响后续结果 后续使用BL与CL时加上注释
	//cout << endl;

	/*						练习题2-3-10				*/
	cout << endl << "练习题2-3-10" << endl;
	PrintList(BL);
	PrintList(CL);
	Mos_2_2_10(BL, BLTail, CL, CLTail);//会重新添加上CL的尾指针
	PrintList(BL);
	PrintList(CL);
	cout << endl;

	/*						练习题2-3-11				*/
	cout << endl << "练习题2-3-11" << endl;
	for (int i = 2; i < 6; i++) {
		List_HeadInsert(BL, i, BLTail);
	}
	PrintList(BL);
	PrintList(CL);
	Mos_2_2_11(BL, BLTail, CL);//会丢失CL的尾指针 影响后续结果 后续使用CL时加上注释
	PrintList(BL);
	PrintList(CL);
	cout << endl;

	/*						练习题2-3-12				*/
	cout << endl << "练习题2-3-12" << endl;
	for (int i = 3; i < 9; i++) {
		List_HeadInsert(BL, i, BLTail);
	}
	SoftList(BL, BLTail);//对BL进行排序,做前置工作
	PrintList(BL);
	Mos_2_2_12(BL, BLTail);
	PrintList(BL);
	cout << endl;

	/*						练习题2-3-13				*/
	//cout << endl << "练习题2-3-13" << endl;
	//for (int i = 3; i < 9; i++) {
	//	List_HeadInsert(BL, i, BLTail);
	//	List_HeadInsert(CL, i, BLTail);
	//}
	//SoftList(BL, BLTail);//对BL进行排序,做前置工作
	//SoftList(CL, CLTail);//对CL进行排序,做前置工作	
	//PrintList(BL);
	//PrintList(CL);
	//Mos_2_2_13(BL,CL);	//会丢失BL与CL的尾指针 影响后续结果 后续使用BL,CL时加上注释
	//PrintList(BL);
	//cout << endl;

	/*						练习题2-3-14				*/
	cout << endl << "练习题2-3-14" << endl;
	for (int i = 3; i < 6; i++) {
		List_HeadInsert(BL, i, BLTail);
		List_HeadInsert(CL, i, BLTail);
	}
	SoftList(BL, BLTail);//对BL进行排序,做前置工作
	SoftList(CL, CLTail);//对BL进行排序,做前置工作
	PrintList(BL);
	PrintList(CL);
	Mos_2_2_14(BL, CL,EL,ELTail);
	PrintList(EL);
	cout << endl;

	/*						练习题2-3-15				*/
	//cout << endl << "练习题2-3-15" << endl;
	//PrintList(BL);
	//PrintList(CL);
	//SoftList(BL, BLTail);//对BL进行排序,做前置工作
	//SoftList(CL, CLTail);//对BL进行排序,做前置工作
	//Mos_2_2_15(BL, BLTail ,CL);//会导致BL与CL元素重叠,使用时取消注释
	//PrintList(BL);
	//PrintList(CL);
	//cout << endl;

	/*						练习题2-3-16				*/
	cout << endl << "练习题2-3-16" << endl;
	ClearList(BL, BLTail);
	ClearList(CL, ALTail);
	for (int i = 1; i < 4; i++) {
		List_HeadInsert(BL, i, ALTail);
	}
	for (int i = 3; i < 6; i++) {
		List_HeadInsert(BL, i, ALTail);
		List_HeadInsert(CL, i, BLTail);
	}
	for (int i = 2; i < 4; i++) {
		List_HeadInsert(BL, i, BLTail);
	}
	cout << "BL" << (Mos_2_2_16(BL, CL)?"是":"不是") << "AL的连续子序列。" << endl;
	cout << endl;

	/*						练习题2-3-17				*/
	cout << endl << "练习题2-3-17" << endl;
	for (int i = 2; i < 7; i++) {
		Circular_Double_LinkList_HeadInsert(CAL, i);
		Circular_Double_LinkList_TailInsert(CAL, i);
	}
	/*for (int i = 1; i < 2; i++) {
		Circular_Double_LinkList_TailInsert(CAL, i);
	}*/
	PrintList(CAL);
	cout << "CAL" << (Mos_2_2_17(CAL) ? "是" : "不是") << "对称的循环双链表。" << endl;
	cout << endl;

	/*						练习题2-3-18				*/
	cout << endl << "练习题2-3-18" << endl;
	ClearList(CAL);
	ClearList(CBL);
	for (int i = 2; i < 7; i++) {
		Circular_Double_LinkList_HeadInsert(CAL, i);
		Circular_Double_LinkList_TailInsert(CBL, i);
	}
	PrintList(CAL);
	PrintList(CBL);
	Mos_2_2_18(CAL, CBL);
	ClearList(CBL);
	PrintList(CAL);
	cout << endl;

	/*						练习题2-3-19				*/
	cout << endl << "练习题2-3-19" << endl;
	for (int i = 4; i < 7; i++) {
		Circular_Double_LinkList_TailInsert(CBL, i);
		Circular_Double_LinkList_HeadInsert(CBL, i);
	}
	for (int i = 2; i < 3; i++) {
		Circular_Double_LinkList_TailInsert(CBL, i);
		Circular_Double_LinkList_HeadInsert(CBL, i);
	}
	for (int i = 2; i < 6; i++) {
		Circular_Double_LinkList_TailInsert(CBL, i);
	}
	PrintList(CBL);
	Mos_2_2_19(CBL);
	cout << endl;

	/*						练习题2-3-20				*/
	cout << endl << "练习题2-3-20" << endl;
	ClearList(DAL);
	for (int i = 2; i < 6; i++) {
		Double_LinkList_HeadInsert(DAL, i);
	}
	Double_LinkList_HeadInsert(DAL, 4);
	PrintList(DAL);
	Mos_2_2_20(DAL, 3);
	PrintList(DAL);
	Mos_2_2_20(DAL, 4);
	PrintList(DAL);
	cout << endl;

	/*						练习题2-3-21				*/
	cout << endl << "练习题2-3-21" << endl;
	ClearList(BL,BLTail);
	for (int i = 1; i < 7; i++) {
		List_HeadInsert(BL, i,BLTail);
	}
	PrintList(BL);
	Mos_2_2_21(BL, 5);
	cout << endl;

	/*						练习题2-3-22				*/
	cout << endl << "练习题2-3-22" << endl;
	ClearList(BL, BLTail);
	ClearList(CL, CLTail);
	for (int i = 1; i < 7; i++) {
		List_HeadInsert(BL, i, BLTail);
	}
	for (int i = 2; i < 8; i++) {
		List_HeadInsert(CL, i, CLTail);
	}
	Mos_2_3_8_1(BL, CL, 3, 2);
	PrintList(BL);
	PrintList(CL);
	cout << "AL与BL在" << Mos_2_2_22(BL, CL)->data << "相同" << endl;
	cout << endl;

	/*						练习题2-3-23				*/
	cout << endl << "练习题2-3-23" << endl;
	ClearList(BL, BLTail);
	for (int i = 1; i < 7; i++) {
		List_HeadInsert(BL, i, BLTail);
		List_HeadInsert(BL, i, BLTail);
	}
	for (int i = -8; i < -2; i++) {
		List_HeadInsert(BL, i, BLTail);
	}
	PrintList(BL);
	Mos_2_2_23(BL, 9);
	PrintList(BL);
	cout << endl;
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值