陣列元素奇偶排序程式中的死迴圈引起的思考

2021-07-12 03:30:05 字數 2405 閱讀 7147

有一陣列:

a[8] =

對該陣列進行排序使得奇數全部在偶數的前面,並且不可以引進分配新的陣列空間。

看到這樣的題目,也許會覺得很簡單,因為題目的目的很明確,只要將奇數全部移到偶數的前面即可,而奇數與奇數之間、偶數與偶數之間都不要求順序。最開始我想到了如下**:

void sort_one(int * a,int

len)}}

由於該段**中a[i]只要是奇數就將a[i]移動到陣列首位置,而a[0]至a[i-1]依次向後移動到a[2]至a[i]的位置,該方法決定了判斷只需從a[1]開始。若是不滿足if語句,i就加1,判斷下乙個即可,外層for迴圈執行完成時,奇偶排序也就完成了。

上面的程式是我自己見到這樣的問題時的第一想法,當時寫完之後沒有出錯也就沒有再管,而乙個月後,又看到別人寫了下面這段類似於sort_one(int * a,int len),卻無任何輸出的程式:

void sort_error(int * a, int

len)}}

該程式思路與sort_one(int * a,int len)思路剛好相反,sort_one(int * a,int len)是將奇數放到最前面,sort_error(int * a,int len)則是將偶數移到到陣列最後面,判斷並處理完成之後,也是奇數在前偶數在後。從思路上看起來似乎可行,但是卻沒有任何輸出,這段程式引發了我的思考。用圖來說明:

當i=0時,a[0]=56是偶數,移到最後面;68向前移到a[0],依舊是偶數,移到後面;20向前移到a[0],仍然是偶數,再移到最後面;15向前移到a[0],不是偶數,則i++;17、101、131、119均是奇數,i繼續自加。

當i加到如上圖所示:a[i]=56,是偶數,則56移到陣列最後;68、20前移,a[i]=68,是偶數,則68移到陣列最後;20、56前移,a[i]=20,是偶數,則20移到陣列最後;56、68再前移,a[i]=56……,由於沒有奇數,i便不能自加,i < len一直成立,迴圈無法退出便進入了死迴圈。只要陣列中有乙個偶數,便會形成死迴圈,此段程式也就沒有任何作用。

對於sort_error(int * a,int len),其主要問題在於它自身的退出迴圈條件與程式的執行方式相互衝突:i在遇到偶數時不能自加,而把偶數都移到最後導致i始終不能加到len,程式陷入死迴圈可謂是「自作孽,不可活」。那麼我們的解決方法就是使迴圈結束條件與執行方式不衝突。

而唯一的辦法就是當偶數向後移動一次,退出迴圈的條件就不能再是i < len了,而是在i < len-1,若是移動了兩次,那麼陣列最後應有兩個偶數,而退出條件也應該成為i < len-2 ……,所以我們不妨設定乙個標誌point = len-1,每當偶數向後移動乙個,point就自減一次,而退出迴圈的條件改為i < point即可。**如下:

void sort_two(int * a, int

len)}}

即使陣列全是偶數i不自加,但每移動一次point自減一次,最終i < point也能不成立,不會陷入死迴圈。

以上兩種演算法,都是我們最直接最容易想到的,但是一般情況下最直接的方法都不是最高效的演算法。因為我們為了解決問題而解決問題都會想到思維量小的方法,而思維量越小發現問題的本質不會深入,得出的結果自然不會高效。

void sort_two()和void sort_one()由於每次移動乙個滿足判斷條件的數,都要成批地依次移動起點到目的點之間的所有資料元素,把不必要的步驟執行了許多遍。那麼如果我們讓i從前往後找偶數,讓j從後向前找奇數,並把從前面找到的第乙個偶數與從後面找到的第乙個奇數互換位置,而不動其它不相關的數,之後繼續執行以上操作,把從前面找到的第二個偶數與從後面找到的第二個奇數互換位置……當i與j的相對位置變成i後j前時,奇數就全部移到偶數的前面了。**如下:

void sort_three(int * a, int len)

用sort_three()只需要將不同的a[i]與a[j]互換三次即可,即使奇數全在偶數後面,最多也僅僅是需要互換len/2次。而sort_one()和sort_two()僅僅是移動元素就需要移動二三十次,當陣列過長時其缺點就顯得尤為突出。

在以上所有程式都是兩層迴圈,時間複雜度都是o(n^2),我們將sort_three()稍作修改就可以降低其時間複雜度,**如下:

void sort_four(int *a, int

len)}}

少了一層迴圈巢狀,時間複雜度雖然降低了,但是並沒有比sort_three()高效,因為其演算法相同,**執行步驟也是一樣的。

用氣泡排序法對陣列中的元素排序

注 此處以公升序排枚舉例 共10個元素 2 4,3,5,8,6,1,7,9,0 要將其公升序排列 1.將第乙個元素與其後的每個元素進行比較 2與4比較 2 4 將這兩個值交換 4,2,3,5,8,6,7,9,0 交換後2位於第二個元素位置處,2與3比較 2 3 交換 4,3,2,5,8,6,7,9,...

去除排序好的陣列中重複的元素

題目描述 去除陣列中重複的元素 例如 1,2,2,3,3,4,5,6,6 1,4,5 實現思想 簡單來說就是。如果當前元素是第乙個元素,只要比較它與後乙個元素是否相等,如果不相等,直接新增到新的陣列中。如果當前元素不是第乙個元素,就比較它相鄰的左右兩邊的元素是否相等,如果不相等就新增。詳細就是 先找...

陣列排序同時返回元素在原陣列中的位置

對陣列中的元素進行排序是非常基礎的問題,從現有的眾多排序演算法中任選一種即可實現。但是如果要求排序後同時返回新的 有序 陣列中每個元素在舊的 未排序 陣列中之原始位置,問題可能就變得有些棘手了。例如假設有乙個陣列如下 2,30,1,5,12,8,6 排序 從小到大 後可得新的陣列如下 1,2,5,6...