感觉链表的快速排序也挺好写的,甚至比数组更容易理解,但不知道为什么看到很多人都说快排不适合单链表结构的数据。
思想:
- 取第一个元素为哨兵,遍历链表,将小于、等于、大于的元素分成3个子链表;
- 递归整理“小于”链表;
- 递归整理“大于”链表;
- 将3个链表连接起来。
代码实现如下:
//链表快速排序,返回最后一个元素的地址
myNode* quickSortForList(myNode* &head)
{
if(head==nullptr||head->next==nullptr) return head;
//分成小于,等于,大于哨兵的3个链表
auto pivot=head;//取第一个元素为哨兵
auto pt=head;//遍历指针
myNode* ls_head=new myNode;//小于哨兵的链表头,该链表第一个元素无效
myNode* eq_head=head;//等于哨兵的链表头,该链表第一个元素有效
myNode* bg_head=new myNode;//大于哨兵的链表头,该链表第一个元素无效
myNode* ls_pt=ls_head, *eq_pt=eq_head, *bg_pt=bg_head;
while(pt=pt->next)
{
if(pt->val < pivot->val)
{//小于哨兵,加到第一个链表后面
ls_pt->next=pt;
ls_pt=ls_pt->next;
}
else if(pt->val == pivot->val)
{
eq_pt->next=pt;
eq_pt=eq_pt->next;
}
else
{
bg_pt->next=pt;
bg_pt=bg_pt->next;
}
}
ls_pt->next=nullptr;//链表最后一个元素指向空指针
eq_pt->next=nullptr;
bg_pt->next=nullptr;
ls_pt=quickSortForList(ls_head->next);//整理小于哨兵的链表,返回整理后的链表的最后一个元素的地址
bg_pt=quickSortForList(bg_head->next);//
if(ls_pt) //如果小于哨兵的链表不为空,则将3个链表首尾链接在一起
{
ls_pt->next=eq_head;
eq_pt->next=bg_head->next;//由于第一个元素无效,bg_head->next才是头
head=ls_head->next;//整理后链表的头指针
}
else
{//如果小于哨兵的链表为空,合并其他2个链表
eq_pt->next=bg_head->next;
head=eq_head;
}
delete ls_head;
delete bg_head;
//如果大于哨兵的链表不为空返回该链表的最后一个元素的位置
//否则返回等于哨兵的链表的最后一个元素的位置
if(bg_pt) return bg_pt;
else return eq_pt;
}
myNode定义:
class myNode
{
public :
int val;
myNode* next;
};