- 先分别对两个链表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;
}
}
- 先对两个链表进行插入排序, 再进行完备的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;
}
被第二种方式坑了很久,记录一下