63.如何对单链表进行快排?和数组快排的分析与对比[quicksort of array and linked list]

【本文链接】

http://www.cnblogs.com/hellogiser/p/quick-sort-of-array-and-linked-list.html

【题目】

单链表的特点是:单向。设头结点位head,则最后一个节点的next指向NULL。如果只知道头结点head,请问怎么将该链表排序?

【分析】

对于数组的快排:有2种方式。

(1)指针相向移动:一个指针i指向头,一个指针j指向尾,然后两个指针相向运动并按一定规律交换值,最后找到一个支点p使得支点左边的值小于支点,支点右边的值大于支点。由于单链表只有next指针,没有前驱指针,因此这种方法行不通。

(2)指针同向移动:两个指针i和j,这两个指针均往数组的右方移动,移动的过程中保持i之前的值都小于选定的key,i和j之间的值都大于选定的key,那么当j走到末尾的时候便完成了一次支点的寻找。这个思路非常适合单链表。

对于数组,我们很容易写出下面的代码。

【代码1】

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/5/30
*/


// i from left,j from right
// i------------>p<-----------------j
int Partition(int a[], int left, int right)
{
    
// partition so that a[left..p-1]<=a[p] and a[p+1..right]>a[p]
    int pivot = a[left], i = left , j = right;
    
while (i < j)
    {
        
while (a[i] <= pivot) i++;
        
while (a[j] > pivot) j--;
        
if (i < j)
            myswap(a[i], a[j]);
    }
    myswap(a[left], a[j]);
    
return j;
}

void QuickSort(int a[], int left, int right)
{
    
if(left < right) // less
    {
        
int p = Partition(a, left, right);
        QuickSort(a, left, p - 
1);
        QuickSort(a, p + 
1, right);
    }
}

void  QuickSort(int a[], int n)
{
    QuickSort(a, 
0, n - 1);
}

【代码2】

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/5/30
*/


// i and j both from left
// i,j---------------->
int Partition2(int a[], int left, int right)
{
    
// partition so that a[left..p-1]<=a[p] and a[p+1..right]>a[p]
    // left----i<=pivot, i----j>=pivot
    int pivot = a[left], i = left , j = left + 1;
    
while (j <= right)
    {
        
if (a[j] < pivot)
        {
            i++;
            myswap(a[i], a[j]);
        }
        j++;
    }
    myswap(a[left], a[i]);
    
return i;
}

void QuickSort2(int a[], int left, int right)
{
    
if(left < right) // less
    {
        
int p = Partition2(a, left, right);
        QuickSort2(a, left, p - 
1);
        QuickSort2(a, p + 
1, right);
    }
}

void  QuickSort2(int a[], int n)
{
    QuickSort2(a, 
0, n - 1);
}

对于链表而言,借鉴(2)指针同向移动的思想容易改成如下代码。

【代码】

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/5/30
*/


// i and j both from left
// i,j---------------->
node *Partition2_List(node *left, node *right)
{
    
// partition so that a[left..p-1]<=a[p] and a[p+1..right]>a[p]
    // left----i<=pivot, i----j>=pivot
    node *pivot = left, *i = left , *j = left->next;
    
while (j != right)
    {
        
if (j->value < pivot->value)
        {
            i = i->next;
            myswap(i->value, j->value);
        }
        j = j->next;
    }
    myswap(left->value, i->value);
    
return i;
}

void QuickSort2_List(node *left, node *right)
{
    
if(left != right) // less
    {
        node *p = Partition2_List(left, right);
        QuickSort2_List(left, p);
        QuickSort2_List(p->next, right);
    }
}

void  QuickSort2_List(node *head)
{
    QuickSort2_List(head, 
NULL);
}

【参考】

http://blog.csdn.net/wumuzi520/article/details/8078322

【本文链接】

http://www.cnblogs.com/hellogiser/p/quick-sort-of-array-and-linked-list.html