http://fengchangjian.com/?p=1330
快排最核心的思想就是划分,确定一个枢轴元素(pivot),每一趟划分的目的就是把待排序列分为两部分,前一部分比枢轴小(序列A),后一部分比枢轴大(序列B)。经过一趟划分之后序列变为:{A} pivot {B}。以下是具体步骤:
1、确定每一次划分的枢轴元素为当前待排序列的头节点。
2、设置Slow和Fast两个游标,Slow指向序列A中的最后一个元素,初始化为枢轴本身(待排序列头节点)。让Fast遍历一遍待排序列,当所指元素比枢轴小时,将Slow往前游一格,交换Slow和Fast所指元素的值,这样仍能保证Slow指向的元素是序列A中的最后一个元素。
3、交换Slow所指元素和枢轴元素的值。
4、对序列A和B重复步骤1~4。
下面是单链表快速排序算法的Java实现:
1、单链表节点的定义。
/**
* @param ListHead 待排序列的头节点
* @param ListEnd 待排序列的尾节点
*/
public static void qsort(Element ListHead, Element ListEnd) {
if (ListHead == null || ListEnd == null)
return;
if (ListHead == ListEnd) {
return;
}
//Slow游标,指向序列A的最末尾元素。
Element Slow = ListHead;
//Fast游标,用于遍历整个待排序列。
Element Fast = ListHead.next;
//TempEnd游标,总是指向Slow游标的前驱节点,递归调用时需要。
Element TempEnd = ListHead;
int temp;
while (Fast != ListEnd) {
//当前节点的值比枢轴小,进行交换。
if (Fast.data < ListHead.data) {
//TempEnd游标总是指向Slow的前驱。
TempEnd = Slow;
Slow = Slow.next;
//交换Slow和Fast游标所指的元素的值
temp = Slow.data;
Slow.data = Fast.data;
Fast.data = temp;
}
Fast = Fast.next;
}
//交换Slow游标所指的元素和枢轴元素的值,使序列成为{A} povit {B}形式
temp = ListHead.data;
ListHead.data = Slow.data;
Slow.data = temp;
//递归调用
qsort(ListHead, TempEnd);
qsort(Slow.next, ListEnd);
}
上面的代码有点问题:
struct Node
{
int key;
Node* next;
Node(int nKey, Node* pNext)
: key(nKey)
, next(pNext)
{}
};
Node* GetPartion(Node* pBegin, Node* pEnd)
{
int key = pBegin->key;
Node* p = pBegin;
Node* q = p->next;
while(q != pEnd)
{
if(q->key < key)
{
p = p->next;
swap(p->key,q->key);
}
q = q->next;
}
swap(p->key,pBegin->key);
return p;
}
void QuickSort(Node* pBeign, Node* pEnd)
{
if(pBeign != pEnd)
{
Node* partion = GetPartion(pBeign,pEnd);
QuickSort(pBeign,partion);
QuickSort(partion->next,pEnd);
}
}
QuickSort(head, NULL);