一、题目解析
如下题目所示,对单项链表进行排序,因为是单项链表,所以只能使用单向的排序算法,如冒泡排序、快速排序、归并排序等。
二、算法代码
下面分别使用快速排序算法和归并排序算法。
#include <iostream>
#include <vector>
#include <algorithm> //sort()排序函数的头文件
using namespace std;
/* 链表的结构体 */
struct ListNode {
int val;
ListNode* next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode* next) : val(x), next(next) {}
};
/* 快速排序法对链表的排序 */
class Solution2 {
public:
ListNode* sortList(ListNode* head) {
if (head == NULL) return head; //递归退出的条件,递归到最后一个节点
int minVal = head->val, maxVal = head->val; //用于求最大值、最小值的变量
ListNode *P1 = head, *P2 = NULL; //用于对链表中间操作的指针
ListNode *Lp = NULL, *Rp = NULL; //对链表左右拆分排序保存的指针
while (P1 != NULL) //查找链表中的最大值和最小值
{
minVal = min(minVal, P1->val);
maxVal = max(maxVal, P1->val);
P1 = P1->next;
}
int z = (minVal + maxVal) >> 1; //最大值和最小值的求平均
if (minVal == maxVal) return head;
P1 = head;
while (P1) //链表遍历是否到结尾
{
P2 = P1->next;
if (P1->val <= z) //链表值大于中间值,节点指向Rp保存
{
P1->next = Lp;
Lp = P1;
}else{ //链表值小于中间值,节点指向Lp保存
P1->next = Rp;
Rp = P1;
}
P1 = P2;
}
Rp = sortList(Rp); //递归排序
Lp = sortList(Lp);
P1 = Lp; //下面就是链接左、右排序后的链表
while (Lp->next) Lp = Lp->next;
Lp->next = Rp;
return P1;
}
};
/* 归并排序法对链表的排序 */
class Solution3 {
public:
int getListLen(ListNode* head) {
int len = 0;
while (head) {
len++;
head = head->next;
}
return len;
}
ListNode* merge_sort(ListNode* head, int n) {
if (n <= 1)return head;
int m = n / 2;
ListNode* Lp= head, * Rp = NULL, *p= head, ret;
//会遍历到左半部分的最后一个节点,左半部分最后一个节点必须指向NULL,才能拆分链表
for (int i = 1; i < m; i++) p = p->next;
Rp = p->next;
p->next = NULL; //注意:左半部分链表的末尾指向NULL,拆分链表,不然就会陷入死循环
Lp = merge_sort(Lp, m); //向内递归排序
Rp = merge_sort(Rp, n - m);
p = &ret, ret.next = NULL; //因为是向后插入链表元素,所以需要一个链表头记录,都是用指针不能记录头部
while (Lp || Rp) //左边和右边的链表一次插入p总链表
{ //注意如果Rp == NULL成立,后面就不会在进入了
if (Rp == NULL || (Lp && (Lp->val <= Rp->val))) //左右链表元素比较大小
{
p->next = Lp;
p = Lp;
Lp = Lp->next;
}else{
p->next = Rp;
p = Rp;
Rp = Rp->next;
}
}
return ret.next;
}
ListNode* sortList(ListNode* head) {
//计算链表的长度
int n = getListLen(head);
return merge_sort(head, n);
}
};
void test2()
{
Solution3 s2;
int arr[5] = { 0,4,3,5,-1 };
ListNode* ptr1 = NULL;
ListNode* ptr2 = NULL;
for (int i = 0; i < 5; i++) //前向插入节点生成链表
{
ListNode* list = (ListNode*)malloc(sizeof(ListNode));
list->val = arr[i];
list->next = ptr1;
ptr1 = list;
}
ptr2 = s2.sortList(ptr1);
while(ptr2) //打印链表并释放内存
{
ListNode* ptr3 = ptr2;
cout << ptr2->val << " ";
ptr2 = ptr2->next;
free(ptr3);
}
}
int main()
{
test2();
return 0;
}
最终运行结果: