无重合并两无序链表

  1. 先分别对两个链表MergeSort(), 再merge两个链表 Merge负责去重
#include<iostream>
#include<vector>
#include<string>
#include<sstream>

using namespace std;
struct LinkNode {
public:
	int val;
	LinkNode* next;
	LinkNode() :next(nullptr) {};
	LinkNode(int val) :val(val), next(nullptr) {};
};
struct LinkList {
public:
	LinkNode* head; //首结点
	LinkList() {
		head = nullptr;
	}
	void createList(vector<int>& v);
};
LinkNode* FindTheMiddle(LinkNode* head) {
	//保证 至少 大小为2  
	LinkNode* slow = head, * fast = head; //从0开始编号
	while (fast != nullptr) {
		if (fast->next == nullptr || fast->next->next == nullptr) return slow;
		slow = slow->next;
		fast = fast->next->next;
	}
	return nullptr;
}

LinkNode* Merge(LinkNode* l, LinkNode* r) {

	LinkNode* head = l->val <= r->val ? l : r;
	LinkNode* curr = head;
	if (l->val < r->val) l = l->next;
	else if (l->val > r->val) r = r->next;
	else {
		l = l->next; r = r->next;
	}
	while (l && r) {
		int a = l->val;
		int b = r->val;
		if (a < b) {
			curr->next = l;
			l = l->next;
		}
		else if (a > b) {
			curr->next = r;
			r = r->next;
		}
		else {
			curr->next = l;
			l = l->next;
			r = r->next;
		}
		curr = curr->next;
	}
	while (l != nullptr) {
		curr->next = l;
		curr = curr->next;
		l = l->next;
	}
	while (r != nullptr) {
		curr->next = r;
		curr = curr->next;
		r = r->next;
	}
	//看似没考虑某个链表之间重复元素的问题 如 1 2 3 3 3
	//注意上面的去重虽然看上去不完备,但Merge在每一个被分解的小过程都进行的不完备的去重,
	//实际效果相当于一个完备的去重
	return head;
}
void MergeSort(LinkNode*& head) {
	if (head == nullptr || head->next == nullptr) return; //之后递归均不会出现空表 
	LinkNode* mid = FindTheMiddle(head);
	LinkNode* nexhead = mid->next;
	mid->next = nullptr;
	MergeSort(head);
	MergeSort(nexhead);
	head = Merge(head, nexhead);

}
vector<int> getData(string& in);
int main() {
	string a, b;
	getline(cin, a); getline(cin, b);
	vector<int> p = getData(a);
	vector<int> q = getData(b);
	LinkList x, y;
	x.createList(p); y.createList(q);
	MergeSort(x.head); MergeSort(y.head);
	LinkNode* tmp = Merge(x.head, y.head);
	while (tmp != nullptr) {
		cout << tmp->val << " ";
		tmp = tmp->next;
	}
	cout << endl;
	return 0;
}
vector<int> getData(string& in) {
	istringstream iss(in); int t;
	vector<int>res;
	while (iss >> t) {
		res.push_back(t);
	}
	return res;
}
void LinkList::createList(vector<int>& v) {
	head = new LinkNode(v[0]);
	LinkNode* tmp = head, * curr = nullptr;
	for (int i = 1; i < v.size(); i++) {
		curr = new LinkNode(v[i]);
		tmp->next = curr;
		tmp = curr;
	}
}

  1. 先对两个链表进行插入排序, 再进行完备的Merge() 易漏易错
#include<iostream>
#include<vector>
#include<string>
#include<sstream>

using namespace std;
struct LinkNode {
public:
	int val;
	LinkNode* next;
	LinkNode() :next(nullptr) {};
	LinkNode(int val) :val(val), next(nullptr) {};
};
struct LinkList {
public:
	LinkNode* head; //头结点
	LinkList() {
		head = new LinkNode();
	}
	void createList(vector<int>& v);
	void sort();
	void print();
};

vector<int> getData(string& in);
LinkNode* Merge(LinkList x, LinkList y, LinkList z);

int main() {

	string a, b;
	getline(cin, a); getline(cin, b);
	vector<int> p = getData(a);
	vector<int> q = getData(b);

	LinkList x, y, z;
	x.createList(p); y.createList(q);

	x.sort();
	y.sort(); //sort不处理重复元素
	x.print(); 
	y.print();

	LinkNode* head = Merge(x, y, z);


	LinkNode* tmp = head->next;
	while (tmp != nullptr) {
		cout << tmp->val << " ";
		tmp = tmp->next;
	}
	cout << endl;


	system("pause");
	return 0;
}

vector<int> getData(string& in) {
	istringstream iss(in); int t;
	vector<int>res;
	while (iss >> t) {
		res.push_back(t);
	}
	return res;
}

LinkNode* Merge(LinkList x, LinkList y, LinkList z)
{
	LinkNode* newx = x.head->next;//分别用xy来记录指针指向
	LinkNode* newy = y.head->next;
	LinkNode* newz = z.head;
	while (newx != NULL && newy != NULL)
	{
		if (newx->val == newy->val)//用x的头结点来记录新链表
		{
			//优先选用x的节点
			newz->next = newx;
			int pastval = newx->val;
			//newx = newx->next;//x,y,z节点后移
			while (newx != NULL && newx->val == pastval) {
				newx = newx->next;
			}
			pastval = newy->val;
			while (newy != NULL && newy->val == pastval) {
				newy = newy->next;
			}
			newz = newz->next;
		}
		else if (newx->val > newy->val)
		{
			newz->next = newy;
			int pastval = newy->val;
			while (newy != NULL && newy->val == pastval) {
				newy = newy->next;
			}
			newz = newz->next;
		}
		else
		{
			newz->next = newx;
			//x,z节点后移
			int pastval = newx->val;
			//newx = newx->next;//x,y,z节点后移
			while (newx != NULL && newx->val == pastval) {
				newx = newx->next;
			}
			newz = newz->next;
		}
		/*if (newx == NULL || newy == NULL)
			break;*/
	}
	while (newx != NULL)
	{
		newz->next = newx;

		int pastval = newx->val; //拿出这个已插入元素的值
		//newy->next 有值且值相等
		while (newx->next != NULL && newx->next->val == pastval) {
			newx = newx->next; //要找的是 newy->next
		}
		// newy 最后一个节点 or newy->next 是下一个要访问的节点
		newx = newx->next;

		newz = newz->next;
	}

	// newy 待插入的节点
	while (newy != NULL)
	{
		newz->next = newy;

		int pastval = newy->val; //拿出这个已插入元素的值
		//newy->next 有值且值相等
		while (newy->next != NULL && newy->next->val == pastval) {
			newy = newy->next; //要找的是 newy->next
		}
		// newy 最后一个节点 or newy->next 是下一个要访问的节点
		newy = newy->next;

		newz = newz->next;
	}
	
	return z.head;
}

void LinkList::createList(vector<int>& v) {

	LinkNode* tmp = head, * curr = nullptr;
	for (int i = 0; i < v.size(); i++) {
		curr = new LinkNode(v[i]);
		tmp->next = curr;
		tmp = curr;
	}
}

void LinkList::sort()
{
	LinkNode* curr = head->next;
	if (curr == nullptr || curr->next == nullptr) { //
		return;
	}
	
	LinkNode* nxt = curr->next; //下一个待插入的节点
	curr->next = nullptr;  // head curr nullptr
	while (nxt != nullptr) {
		curr = nxt; //curr 该轮待插入
		nxt = nxt->next;
		LinkNode* tmp = head;
		while (tmp->next!=nullptr && tmp->next->val < curr->val) {
			tmp = tmp->next; 
		}
		// tmp下一个是比待插入节点值大 / 最大元素
		curr->next = tmp->next; //两种处理一样
		tmp->next = curr;


}

void LinkList::print()
{
	LinkNode* tmp = head->next;
	while (tmp != nullptr) {
		cout << tmp->val << " ";
		tmp = tmp->next;
	}
	cout << endl;
}


被第二种方式坑了很久,记录一下

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雾影林深

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值