我们知道了普通的快速排序利用的划分函数是从两边向中间划分,但是对于单链表,这种划分函数可就显得不这么适用了。原因在于单链表每个节点只存在存放后一个结点的指针域,找到后一个节点容易,但是想要找到前一个结点的话,可就显得力不从心了。
所以,我们可以借用普通划分函数的思想,来写一个都从前向后划分的划分函数。
首先我们的i和j肯定都指向前面,我们仍然以第一个值为划分标准 。
ListNode* LinkParition(ListNode* left, ListNode* right)
{
ListNode* ip = left;
ListNode* jp = left->next;
int tmp = left->data;
while (jp != right)
{
if (jp->data <= tmp)
{
ip = ip->next;
std::swap(ip->data, jp->data);
}
jp = jp->next;
}
std::swap(left->data, ip->data);
return ip;
}
如果j指向的值大于标准值,就j向后走,当j指向的值小于等于划分标准值,这时i向后走一个,交换i和j指向的值,然后j继续向后走…直到j指向了right结点。此时完成一次划分。
剩下代码和普通快排 一样,递归执行。
void QuickPass(ListNode* left, ListNode* right)
{
if (left != right)
{
ListNode* p = LinkParition(left, right);
QuickPass(left, p);
QuickPass(p->next, right);
}
}
void ListQuickSort(ListNode* head)
{
QuickPass(head, nullptr);
}
给一个完整单链表示例:
typedef int ElemType;
typedef struct ListNode
{
ElemType data;
ListNode* next;
}ListNode, * LinkList;
ListNode* Init_List(const vector<int>& ar)
{
ListNode* head = (ListNode*)malloc(sizeof(ListNode));
head->data = ar[0];
head->next = nullptr;
ListNode* p = head;
for (int i = 1; i < ar.size(); ++i)
{
ListNode* s = (ListNode*)malloc(sizeof(ListNode));
if (s == nullptr) return nullptr;
s->data = ar[i];
s->next = nullptr;
p->next = s;
p = s;
}
return head;
}
void Print_List(ListNode* p)
{
while (p != nullptr)
{
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
ListNode* LinkParition(ListNode* left, ListNode* right)
{
ListNode* ip = left;
ListNode* jp = left->next;
int tmp = left->data;
while (jp != right)
{
if (jp->data <= tmp)
{
ip = ip->next;
std::swap(ip->data, jp->data);
}
jp = jp->next;
}
std::swap(left->data, ip->data);
return ip;
}
void QuickPass(ListNode* left, ListNode* right)
{
if (left != right)
{
ListNode* p = LinkParition(left, right);
QuickPass(left, p);
QuickPass(p->next, right);
}
}
void ListQuickSort(ListNode* head)
{
QuickPass(head, nullptr);
}
int main()
{
vector<int>ar = { 56,34,23,78,90,12,45,67,89,100 };
LinkList head= Init_List(ar);
Print_List(head);
ListQuickSort(head);
Print_List(head);
return 0;
}