链表的基本操作C/c++

#include 
#include 
#include 
using namespace std;

struct ListNode{
	int data;
	ListNode* next;
};
typedef ListNode List;

struct dListNode{
	int data;
	dListNode* next;
	dListNode* previous;
};
typedef dListNode dList;

//头插法建立双向链表,与单链表类似
void createDListHead(dList* &L){
	L = new dList;
	L->next = L->previous = NULL;
	int val;
	cin >> val;
	while (val != -1)
	{
		dListNode* p = new dList;
		p->next = L->next;
		p->previous = L;
		p->data = val;
		L->next = p;
		cin >> val;
	}
}

//尾插法建立双向链表,与尾插法类似
void createDListRear(dList* &L){
	L = new dList;
	L->next = L->previous = NULL;
	int val;
	cin >> val;
	dListNode* q = L;
	while (val != -1)
	{
		dListNode* p = new dList;
		p->data = val;
		p->previous = q;
		p->next = NULL;
		q->next = p;
		q = p;
		cin >> val;
	}
}

//删除指定值的节点,例如3->1->2->3->3->4->3,输入3,结果为1->2->4;
void deleteDLNode(dList* L){
	int val;
	cout << "Please input the val you want to delete:  ";
	cin >> val;
	dListNode* p = L;
	dListNode* q = NULL;
	while (p->next != NULL)
	{
		if (p->next->data == val)
		{
			q = p->next;
			if (p->next->next!=NULL)				//与单向链表不同之处,不要忘记加判断是否为空指针
				p->next->next->previous = p;
			p->next = q->next;
			delete q;
		}
		else
			p = p->next;
	}
}

//尾插法建立单链表
void createListRear(List* &L){
	L = new List;
	L->next = NULL;
	ListNode* q = L;
	int val;
	cin >> val;
	while (val != -1)
	{
		ListNode * p = new List;
		p->data = val;
		p->next = NULL;
		q->next = p;
		q = p;
		cin >> val;
	}
	return;
}

//头插法建立单链表
void createListHead(List* &L){
	L = new List;
	L->next = NULL;
	int val;
	cin >> val;
	while (val != -1)
	{
		ListNode* p = new List;
		p->data = val;
		p->next = L->next;
		L->next = p;
		cin >> val;
	}
	return;
}

//打印链表
template
void printList(T *L){
	T* p = L->next;
	while (p != NULL)
	{
		cout << p->data << " -> ";
		p = p->next;
	}
	cout << "NULL" << endl;
	return;
}

//反转单链表,遍历链表,依次头插
void reverseList(List* L){
	ListNode* p = L->next;
	ListNode* r = p;						//不要忘记记录头结点,循环结束后将它的next置为NULL 否则会形成环;
	if (p == NULL) return;					//同时不要忘记判断链表是否为空,否则r=L->next;r->next=NULL;会使程序崩溃;
	while (p != NULL)
	{
		ListNode* q = p->next;
		p->next = L->next;
		L->next = p;
		p = q;
	}
	r->next = NULL;
	return;
}

//删除倒数第k个节点,快指针先走k,慢指针再走,快指针到达链表尾部时,慢指针到达倒数第K个节点
void getKthFromRear(List* L,int k){
	ListNode* fast = L->next;
	ListNode* slow = L->next;
	if (L->next == NULL||k<=0) return;
	int i = 1;
	while (i < k)								//此处可借可k=1考虑;
	{
		fast = fast->next;
		if (fast == NULL)						//当K大于链表长度时,为K%Len;
			fast = L->next;
		++i;
	}
	while (fast->next != NULL)					//判断条件为fast->next==NULL,若为fast==NULL,则上个while条件为i<=k
	{
		fast = fast->next;
		slow = slow->next;
	}
	cout << "The Kth from rear is: " << slow->data << endl;
	return;
}

//获取中间节点
void getMid(List* L){
	if (L->next == NULL) return;
	ListNode* fast = L->next;
	ListNode* slow = L->next;
	while (fast->next!= NULL&&fast->next->next!=NULL)		//fast fast->next当Len为奇数时返回Len/2+1;fast->next,fast->next->next返回Len/2;
	{
		fast = fast->next->next;
		slow = slow->next;
	}
	cout << "Mid element is: " << slow->data << endl;
}

//逆序打印,采用栈
void printFromRear(List* L){
	stack iSak;
	ListNode* p = L->next;
	cout << "NULL" << " <- ";
	while (p != NULL)
	{
		iSak.push(p->data);
		p = p->next;
	}
	while (!iSak.empty())
	{
		cout << iSak.top() << " <- ";
		iSak.pop();
	}
	cout << "Head" << endl;

}

//删除data=val的节点
void deleteElementK(List* L){
	if (L->next == NULL) return;
	cout << "Plese input the value you want to delete: ";
	int val;
	cin >> val;
	ListNode* p = L;
	ListNode* r = L;
	while (p->next!= NULL)						//要记录前一个节点,故要用p->next来判断;
	{
		
		if (p->next->data == val)
		{
			r = p->next;
			p->next = r->next;
			delete r;
			//continue;
		}
		else									//不要忽略else,否则出现连续的值得时候不能完全删除
			p = p->next;
		//p = p->next;
	}
}

//合并两个有序链表,到L1
void mergeSortList(List *L1, List* L2){
	if (L1->next == NULL)
	{
		L1->next = L2->next;
		return;
	}
	if (L2->next == NULL) return;
	ListNode* p1 = L1->next;
	ListNode* p2 = L2->next;
	ListNode* q = NULL;
	if (p1->data < p2->data)		//先找到两个链表中第一个较小的节点,让q指向它,不要忘记q=p1后面一句
	{
		q = p1;
		p1 = p1->next;
	}
	else
	{
		q = p2;
		p2 = p2->next;
	}
	L1->next = q;
	while (p1 != NULL&&p2 != NULL)
	{
		if (p1->data < p2->data)
		{
			q->next = p1;
			q = p1;
			p1 = p1->next;
		}
		else
		{
			q->next = p2;
			q = p2;
			p2 = p2->next;
		}
	}
	if (p1 != NULL)
		q->next = p1;
	else if (p2 != NULL)
		q->next = p2;
}

//用于测试,构造有环链表,输入一个链表中的节点数据,形成环,例如1->4->6->8->5,输入6,会使5的下一个节点为6,形成环
void makeListWithCircle(List* L){
	ListNode* p = L->next;
	ListNode* c = NULL;
	cout << "Please input the value to be circle:";
	int val;
	cin >> val;
	while (p->next != NULL)
	{
		if (p->data == val&&c==NULL)
			c = p;
		p = p->next;		
	}
	p->next = c;
}

//判断链表是否有环
bool hasCircle(List *L){
	ListNode* p = L->next;
	ListNode* q = L->next;
	while (p->next != NULL&&p->next->next != NULL)
	{
		p = p->next->next;
		q = q->next;
		if (p == q)
			return true;
	}
	return false;
}

//找到环的起点,用set容器存储已经遍历过的节点,每次遍历一个新节点就检查是否存在于set里,实现较简单
void findTheCircleBegin(List *L){
	ListNode* p = L->next;
	set listSet;
	while (p != NULL)
	{
		if (listSet.count(p) == 0)
			listSet.insert(p);
		else
		{
			cout << p->data << endl;
			return;
		}
		p = p->next;
	}
	cout << "Has No Crcle!" << endl;
}

//找到两个相交链表的第一个交点,若链表相交,则尾节点必相同,求出两个链表长度的差k,让长的链表先走k步,然后连个链表再一起走,相等时即为第一个节点
void findIntersectPos(List* L1, List* L2){
	ListNode* p1 = L1->next;
	ListNode* p2 = L2->next;
	int lenth1 = 1;
	int lenth2 = 1;
	while (p1->next != NULL)
	{
		p1 = p1->next;
		++lenth1;
	}
	while (p2->next!=NULL)
	{
		p2 = p2->next;
		++lenth2;
	}
	if (p1 != p2)
	{
		cout << "Not Intersect!" << endl;
		return;
	} 
	p1 = L1->next;
	p2 = L2->next;
	int k = abs(lenth1 - lenth2);
	int i = 1;
	if (lenth1 >= lenth2)
	{
		while (i <= k)
		{
			p1 = p1->next;
			++i;
		}
	}
	else
	{
		while (i <= k)
		{
			p2 = p2->next;
			++i;
		}			
	}

	while (p2 != p1)
	{
		p2 = p2->next;
		p1 = p1->next;
	}
	cout << p1->data << endl;
}

//构造用于测试的相交链表,让L2的尾节点指向L1的某一节点
void makeIntersect(List* L1, List* L2){
	ListNode* p1 = L1->next;
	ListNode* p2 = L2->next;
	while (p2->next != NULL)
		p2 = p2->next;
	int val;
	cout << "Please input the value of the intersect:  ";
	cin >> val;
	while (p1 != NULL)
	{
		if (p1->data == val)
			break;
		p1 = p1->next;
	}
	p2->next = p1;
}
/*int main(){
	char q;
	//cin >> q;
	cout << "please input the datas of list, -1 to end" << endl;
	while (1)
	{
		//List *L1 = NULL;
		//List* L2 = NULL;
		//createListRear(L1);
		//createListRear(L2);

		dList* dL1 = NULL;
		dList* dL2 = NULL;
		createDListHead(dL1);
		createDListRear(dL2);

	//	mergeSortList(L1, L2);
	//	getKthFromRear(L1, 1);
	//	getMid(L1);
	//	reverseList(L1);
		//printList(L1);
		//printList(L2);
		//deleteElementK(L1);
		//deleteElementK(L2);

		printList(dL1);
		printList(dL2);
		deleteDLNode(dL1);
		deleteDLNode(dL2);
		printList(dL1);
		printList(dL2);

		//cout << hasCircle(L1) << endl;
		//findTheCircleBegin(L1);
		//makeListWithCircle(L1);
		//cout << hasCircle(L1) << endl;
		//findTheCircleBegin(L1);
	//	printFromRear(L1);
		//findIntersectPos(L1, L2);
		//makeIntersect(L1, L2);
	//	createDListRear(dL1);
	//	deleteDLNode(dL1);
		//createDListRear(dL2);
	//	printList(dL1);
		//printList(dL2);
		
		//printList(L2);
		//findIntersectPos(L1, L2);
		cout << "Do you want to quit? (y/n)" << endl;
		cin >> q;
		if (q == 'y') break;
		else 
			cout << "please input the datas of list, -1 to end" << endl;
	}
	
	//printList(L2);
	return 0;
}*/

你可能感兴趣的:(数据结构学习,单链表,链表)