簡體   English   中英

快速排序中使用的兩個分區版本的區別

[英]Difference of the two versions of partition used in quicksort

第一個很簡單,只需從兩側步行直到找到還原。

/*C++ version, [first, last), last needs --first to fetch the last element*/
/*returns the middle of partitioning result*/
int* partition( int *first, int *last, int pivot ) {
    while (true) {
        while (*first < pivot) ++first;
        --last;//Don't edit this, it's true.
        while (pivot < *last) --last;
        if (!(first < last)) return first;
        swap(*first, *last);
        ++first;
    }
}

第二個(顯示在“ 算法簡介 ”中)是:

int* partition( int a[], int n, int pivot ) {
    bound = 0;
    for ( i = 1; i != n; ++i )
        if ( a[i] < pivot )
            swap( &a[i], &a[++bound]);
    swap(a, a + bound);
    return a + bound;
}

第二個不變式是“ 綁定前的所有元素均小於樞軸 ”。

問:兩個版本的優缺點是什么?

我首先給出一個,第二個需要對iterator(pointer)進行++操作,因此它可以應用於某些ForwardIterator例如鏈表的迭代器。 其他提示?

就這兩種算法的基本思想而言,兩者都是正確的。 他們將進行相同數量的比較,但是第二個將比第一個進行更多的交換。

您可以通過逐步遍歷算法(使用5作為樞軸對數組1 9 2 8 3 7 4 6 5進行分區)來看到這一點。 當第一個算法交換兩個數字時,它再也不會觸及任何一個。 第二種算法首先交換9和2,然后交換9和3,依此類推,進行多次交換以將9移動到其最終位置。

也有其他差異。 如果我沒有犯任何錯誤,這是第一種算法對數組進行分區的方式:

1 9 2 8 3 7 4 6 5
f                 l
1 9 2 8 3 7 4 6 5  # swap 9,5
  f             l
1 5 2 8 3 7 4 6 9  # swap 8,4
      f     l
1 5 2 4 3 7 8 6 9  # return f = 5
        l f

這是第二種算法對數組進行分區的方式:

1 9 2 8 3 7 4 6 5  # 1<5, swap 1,1
bi      
1 9 2 8 3 7 4 6 5  # 9>5, no swap
  bi
1 9 2 8 3 7 4 6 5  # 2<5, swap 9,2
  b i
1 2 9 8 3 7 4 6 5  # 8>5, no swap
    b i
1 2 9 8 3 7 4 6 5  # 3<5, swap 9,3
    b   i
1 2 3 8 9 7 4 6 5  # 7>5, no swap
      b   i
1 2 3 8 9 7 4 6 5  # 4<5, swap 8,4
      b     i
1 2 3 4 9 7 8 6 5  # 6>5, no swap
        b     i
1 2 3 4 9 7 8 6 5  # 5=5, exit loop, swap 9,5
        b       i
1 2 3 4 5 7 8 6 9  # return b = 4
        b       i

請注意,與其他算法中的2個相比,它是如何進行5次交換的。 還將數組中的最后一項移動到中間數組。 在這種情況下,最后一項恰好是樞軸,因此它是移到中間的樞軸,但這不是一般情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM