1、插入排序
借助一个结点,将有序的链表挂在这个辅助结点后面
遍历待排序链表,将结点插入到有序链表的合适位置
注意:每次从辅助结点开始找插入点
2、归并排序
分解:找中间结点mid(快慢指针),然后断开链表
head为左边链表的头结点
mid为右边链表的头结点
合并:两个有序链表的合并
0 创建链表
#include<iostream>
using namespace std;
#include<vector>
struct Node
{
int val;
Node* next;
Node(int x) :val(x),next(NULL) {}
};
//创建链表
Node* create()
{
//带头结点的链表
Node* head = new Node(0);
Node* p = head;
vector<int> lists = { 1,4,3,2,1 };
for (int i = 0; i < lists.size(); i++)
{
Node* pNewNode = new Node(lists[i]);
p->next = pNewNode;
p = pNewNode;//更新p
}
return head;
}
//打印链表
void printL(Node* L)
{
Node* p = L;
while (p)
{
cout << p->val << " ";
p = p->next;
}
cout << endl;
}
int main()
{
//创建链表
Node* head = create();
printL(head->next);
//插入排序
Node* sHead = insertSort(head->next); //带头结点的链表
printL(sHead);
//归并排序
Node* mHead = mergeSortList(head->next);
printL(mHead);
return 0;
}
1、插入排序
//插入排序
Node* insertSort(Node* head)
{
//插入排序, 排序组 待排序组 待排序组找插入位置
//每次从头结点开始找插入位置
if (head == NULL || head->next == NULL)
return head;
Node* p = head;
Node* helper = new Node(0); //借助一个节点,指向头节点 结果链接在helper之后
Node* pre = NULL; //p插入点的前一个节点
Node* temp = NULL; //每次记录p之后的节点
while (p)
{
temp = p->next; //记录p的下一个节点
pre = helper;//从头节点开始找插入点
//找p的插入点 升序 //找第一个q小于p的位置则插入点在pre->next前面
while (pre->next && pre->next->val < p->val)
pre = pre->next;
// pre p pre->next
p->next = pre->next; //插入
pre->next = p;
p = temp;//更新p
}
return helper->next;
}
2、 归并排序
//合并两个有序链表
Node* mergeTwoLists(Node* L1, Node* L2)
{
//检查输入条件
if (L1 == NULL)
return L2;
if (L2 == NULL)
return L1;
if (L1 == NULL && L2 == NULL)
return NULL;
//链接在新链表后
Node* retHead = new Node(-1);
Node* retP = retHead;
while (L1 && L2)
{
if (L1->val <= L2->val)
{
retP->next = L1;
L1 = L1->next;
}
else
{
retP->next = L2;
L2 = L2->next;
}
retP = retP->next;
}
//若有剩余,直接连在retP后面
if (L1)
retP->next = L1;
if (L2)
retP->next = L2;
return retHead -> next;
}
//找链表的中间结点,快慢指针
Node* findMid(Node* head)
{
//快慢指针 fast走两步 slow走一步
//fast走到尾部,slow恰好走到中间
Node* fast = head;
Node* slow = head;
Node* tail = NULL; //tail尾部需要断开链表
while (fast && fast->next)
{
tail = slow;
fast = fast->next->next;
slow = slow->next;
}
//要断开链表
tail->next = NULL;
return slow;
}
//归并排序,将链表分解,直到分解为2个结点 然后两两合并
Node* mergeSortList(Node* head)
{
//检查输入条件 处理含0或1个结点的链表
if (head == NULL || head->next == NULL)
return head;
//分解 找中间mid结点,然后断开链表
Node* mid = findMid(head);
//两两合并
Node* L1 = mergeSortList(head); //左边链表头结点为head
Node* L2 = mergeSortList(mid); //右边链表头结点为mid
return mergeTwoLists(L1,L2);
}