1. 程式人生 > >交換算法引起的快速排序錯誤

交換算法引起的快速排序錯誤

可靠 col 通過 中間變量 可靠性 什麽 color 減法 出現

前兩天手寫快速排序,最後得到的結果是錯誤的而且還錯的非常奇怪。輸入的待排序數組是:

int a[10] = {2,6,4,8,0,1,5,9,3,7};

最後得到的結果是:

0 0 2 0 0 0 6 0 8 0

上網看了看別人的代碼,發現我寫的快速排序的算法邏輯是沒有錯誤的,難道是交換元素時用的算法不對?

我用的交換算法是異或交換,就是不用中間變量那種:

void swap( int *a, int *b )
{
    *a = *a + *b;
    *b = *a - *b;
    *a = *a - *b;
}

然後將其換成使用中間變量的交換算法:

void
swap( int *a, int *b ) { int temp; temp = *a; *a = *b; *b = temp; }

然後結果就對了,但是一直想不明白為什麽。最後通過在紙上演算一遍才恍然大悟。

例如我這個輸入:

2 6 4 8 0 1 5 9 3 7

中間的比較交換過程略去不表,然後它會到達這麽一個狀態:

0 /1 / 2 / 8 4 6 5 9 3 7
^
^

解釋一下,第一輪排序將2放到屬於它的位置,然後分成左邊的序列0 1和右邊的序列8 4 6 5 9 3 7。第二輪對左邊的0 1進行排序,將0放置到屬於它的位置(沒動)。第三輪對1進行排序,問題就出在這裏,由於只有一個元素,但按照算法也要進行一次交換,如果使用不借助中間變量的交換算法(加減法、異或法),傳遞給void swap( int *a, int *b )的a, b指向的是同一地址,也就是說實際上是這樣的:

void swap( int *a, int *a )
{
    *a = *a + *a;
    *a = *a - *a; //*a==0,永世不得翻身
    *a = *a - *a;
}

其實在第二輪時,0與0交換就出現了這個問題,但是由於它是0沒有表現出來。

以前總覺得不用中間變量的交換算法稍微有那麽點帥,看來還是得想好了再用。可靠性最重要啊。

交換算法引起的快速排序錯誤