下面的排序只针对无头结点的单链表,当然有头节点稍微改改就可以了
选择排序
选择排序就是每次选一个最小的,放到前面
为了方便操作,创造一个头结点
/**
* Definition of singly-linked-list:
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
//空链表或者只有一个节点
if(head==nullptr||head->next==nullptr)return head;
ListNode* temp=new ListNode(0);
temp->next=head;
for(ListNode* r=temp;r->next->next!=nullptr;r=r->next){
ListNode* p,*q;
//p用来存储最小的节点的前驱
for(p=r,q=r->next;q->next!=nullptr;q=q->next){
if(q->next->val<p->next->val){
p=q;
}
}
q=p->next;//指向最小
p->next=q->next;//断链
//拼接
q->next=r->next;
r->next=q;
}
head=temp->next;
delete temp;
return head;
}
};
插入排序
也创建一个头结点方便操作
插入排序由于链表不能往前迭代,所以只能在有序的部分遍历,找插入位置
所以这个不是真正意义上的插入排序
/**
* Definition of singly-linked-list:
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param head: The first node of linked list.
* @return: The head of linked list.
*/
ListNode * insertionSortList(ListNode * head) {
// write your code here
//空链表或者只有一个节点
if(head==nullptr||head->next==nullptr)return head;
ListNode* temp=new ListNode(1);
temp->next=head;
//temp的链表现在是有序的那部分
ListNode* p=head->next,*q,*r;
head->next=nullptr;
while(p){
q=temp;
//找插入位置
while(q->next&&q->next->val<=p->val){
q=q->next;
}
r=p->next;
p->next=q->next;
q->next=p;
p=r;
}
return temp->next;
}
};
快速排序
由于不能往前迭代,所以只能换种方法
p指向小于哨兵的最后一个,q是用来迭代的,如果q当前的值小于哨兵,就把他和p后面的交换,大概感觉就是下面这张图
/**
* Definition for singly-linked list.
* 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 Solution {
public:
void helper(ListNode* head,ListNode* tail){
if(head==tail||head->next==tail)return;
int val=head->val;
ListNode* p=head;
for(ListNode* q=head->next;q!=tail;q=q->next){
if(q->val<val){
p=p->next;
if(p!=q){
swap(p->val,q->val);
}
}
}
swap(head->val,p->val);
helper(head,p);
helper(p->next,tail);
}
ListNode* sortList(ListNode* head) {
if(head==nullptr||head->next==nullptr)return head;
helper(head,nullptr);
return head;
}
};
归并排序
在链表排序中,归并应该算最快的
用快慢指针找中间,然后左边归并,右边归并,然后合并,都是基本操作
唯一要注意的是如果是空链表或者是只有一个节点,要直接返回,不然会死循环
/**
* Definition for singly-linked list.
* 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 Solution {
public:
ListNode* merge(ListNode* p,ListNode* q){
if(q==nullptr)return p;
else if(p==nullptr)return q;
ListNode* r,*tail=nullptr;
while(p!=nullptr&&q!=nullptr){
if(p->val<=q->val){
if(tail!=nullptr){
tail->next=p;
tail=p;
}
else{
r=tail=p;
}
p=p->next;
}
else{
if(tail!=nullptr){
tail->next=q;
tail=q;
}
else{
r=tail=q;
}
q=q->next;
}
}
if(p==nullptr)p=q;
tail->next=p;
return r;
}
ListNode* sortList(ListNode* head) {
if(head==nullptr||head->next==nullptr)return head;
ListNode* slow=head,*fast=head;
while(fast->next!=nullptr&&fast->next->next!=nullptr){
slow=slow->next;
fast=fast->next->next;
}
fast=slow->next;
slow->next=nullptr;
head=sortList(head);
fast=sortList(fast);
return merge(head,fast);
}
};
总结
效率上,归并应该是最快的
在leetcode上,只有归并能过
https://leetcode.com/problems/sort-list/submissions/
下面这个是lintcode链表插入排序,用插入和选择都能过
https://www.lintcode.com/problem/insertion-sort-list/
下面这个是lintcode链表排序,快排和归并能过,目测选择和插入过不了
https://www.lintcode.com/problem/sort-list/description
下面这个是牛客网,虽然说是选择排序,但是只有归并能过
C++完整版
#include<iostream>
#include<random>
#include<vector>
#include<algorithm>
using namespace std;
/**
* 链表节点
*/
template<typename T>
class Node{
public:
T data;
Node<T>* next;
Node():next(nullptr){}
explicit Node(const T& data):data(data),next(nullptr){}
};
/**
* 无头结点单链表
*/
template<typename T>
class LinkedList{
private:
Node<T>* head;//链表
/**
* 两个链表归并
* @param p 链表1
* @param q 链表2
* @return 归并后的链表
*/
static Node<T>* merge(Node<T>* p,Node<T>* q){
if(nullptr == p){
return q;
}
else if(nullptr == q){
return p;
}
Node<T>* r;//合并后的链表
Node<T>* tail= nullptr;//合并后的链表的最后一个节点
while(p!=nullptr&&q!=nullptr){
if(p->data<=q->data){
if (tail != nullptr) {
tail->next = p;
tail = p;
}
else {
r = tail = p;
}
p=p->next;
}
else{
if (tail != nullptr) {
tail->next = q;
tail = q;
}
else {
r = tail = q;
}
q=q->next;
}
}
if(p==nullptr){
p=q;
}
tail->next=p;
return r;
}
/**
* 归并排序
* @param head 链表
* @return 排序后的链表
*/
static Node<T>* mergeSort(Node<T>* head){
//空链表或者只有一个元素
if(head==nullptr||head->next==nullptr){
return head;
}
//快慢指针,找中间节点
Node<T>* fast=head,*slow=head;
while(fast->next!=nullptr&&fast->next->next!=nullptr){
slow=slow->next;
fast=fast->next->next;
}
//右半边
Node<T>* right=slow->next;
//断链
slow->next=nullptr;
head=mergeSort(head);
right=mergeSort(right);
//归并
return merge(head,right);
}
/**
* 快排辅助函数
* @param head 链表
* @param tail 链表最后一个节点的下一个
*/
static void quickSortHelper(Node<T>* head,Node<T>* tail){
//空链表或者只有一个元素
if(head==tail||head->next==tail){
return;
}
Node<T>* p=head;//小于哨兵的节点的最后一个
int val=head->data;//哨兵
for(Node<T>* q=head->next;q!=tail;q=q->next){
if(q->data<val){
p=p->next;
if(p!=q){
swap(p->data,q->data);
}
}
}
swap(head->data,p->data);
quickSortHelper(head,p);
quickSortHelper(p->next,tail);
}
/**
* 快排
* @param head 链表
* @return 排序后的链表
*/
static Node<T>* quickSort(Node<T>* head){
//空链表或者只有一个元素
if(head==nullptr||head->next==nullptr)return head;
quickSortHelper(head,nullptr);
return head;
}
public:
LinkedList():head(nullptr){}
/**
* 销毁链表
*/
void destroy(){
while(head!=nullptr){
Node<T>* p=head->next;
delete head;
head=p;
}
head=nullptr;
}
~LinkedList(){
destroy();
}
void init(const vector<T>& init_data){
destroy();
Node<T>* tail= nullptr;
for(const T& c:init_data){
if(tail!=nullptr){
tail->next=new Node<T>(c);
tail=tail->next;
}
else{
head=tail=new Node<T>(c);
}
}
}
explicit LinkedList(const vector<T>& init_data){
head= nullptr;
init(init_data);
}
/**
* 判断链表是否有序
* @return true是|false否
*/
bool isSorted()const{
if(head==nullptr||head->next==nullptr)return true;
T pre=head->data;
for(Node<T>* p=head->next;p!=nullptr;p=p->next){
if(p->data<pre)return false;
pre=p->data;
}
return true;
}
/**
* 选择排序
*/
void selectSort(){
if(head==nullptr||head->next==nullptr){
return;
}
auto temp=new Node<T>();
temp->next=head;
for(Node<T>* r=temp;r->next->next!=nullptr;r=r->next){
Node<T>* p,*q;
for(p=r,q=r->next;q->next!=nullptr;q=q->next){
if(q->next->data<p->next->data){
p=q;
}
}
q=p->next;
p->next=q->next;
q->next=r->next;
r->next=q;
}
head=temp->next;
delete temp;
}
/**
* 插入排序
*/
void insertSort(){
if(head==nullptr||head->next==nullptr){
return;
}
auto* temp=new Node<T>();//创建一个头结点
temp->next=head;
Node<T>* p=head->next;
head->next=nullptr;
while(p!=nullptr){
Node<T>* q=temp;
T val=p->data;
while(q->next!=nullptr&&q->next->data<=val){
q=q->next;
}
Node<T>* r=p->next;
p->next=q->next;
q->next=p;
p=r;
}
head=temp->next;
delete temp;
}
/**
* 归并排序
*/
void mergeSort(){
head=mergeSort(head);
}
/**
* 快速排序
*/
void quickSort(){
head=quickSort(head);
}
/**
* 将链表转成vector
* @return 转换后的vector
*/
vector<T> getElements()const{
vector<T> result;
for(Node<T>* p=head;p!=nullptr;p=p->next){
result.push_back(p->data);
}
return result;
}
friend ostream& operator<<(ostream& out,const LinkedList<T>& linkedList) {
if(linkedList.head==nullptr){
return out;
}
bool flag=false;
for(Node<T>* p=linkedList.head;p!=nullptr;p=p->next){
if(flag){
out<<' ';
}
else{
flag=true;
}
out<<p->data;
}
return out;
}
};
bool isSame(vector<int>& a,vector<int>& b){
if(a.size()!=b.size())return false;
for(int i=0,size=a.size();i<size;++i){
if(a[i]!=b[i])return false;
}
return true;
}
int main(){
const int N=1000;
random_device rd;
vector<int> v;
for(int i=0;i<N;++i){
v.push_back(rd());
}
vector<int> temp=v;
sort(v.begin(),v.end());
vector<int> p;
LinkedList<int> linkedList;
bool flag=false;
linkedList.init(temp);
linkedList.selectSort();
p=linkedList.getElements();
if(!isSame(v,p)){
cout<<"selectSort wrong"<<endl;
flag=true;
}
linkedList.init(temp);
linkedList.insertSort();
p=linkedList.getElements();
if(!isSame(v,p)){
cout<<"insertSort wrong"<<endl;
flag=true;
}
linkedList.init(temp);
linkedList.mergeSort();
p=linkedList.getElements();
if(!isSame(v,p)){
cout<<"mergeSort wrong"<<endl;
flag=true;
}
linkedList.init(temp);
linkedList.quickSort();
p=linkedList.getElements();
if(!isSame(v,p)){
cout<<"quickSort wrong"<<endl;
flag=true;
}
if(flag){
for(int& c:temp){
cout<<c<<' ';
}
cout<<endl;
}
else{
cout<<"SUCCESS"<<endl;
}
return 0;
}