插入排序,選擇,冒泡,快速排序演算法及優化

2021-07-10 10:13:32 字數 3805 閱讀 6676

一開始只想貼**,但是後來發現還是有人看的。所以覺得還是有必要花點時間去寫寫。

先定義乙個用於交換兩個數的函式吧。

#if 0

inline void swap(int& a, int& b)

#else

//inline void swap(int& a, int& b)

}#endif

用於獲得一段**執行時間的巨集,限於windows系統,其他系統可以用相應的獲取時間的函式代替gettickcount()。

/*

*獲取一段**(func)執行的時間

*/#define gettm(func, t) \

dowhile(0)

簡單的冒泡的過程像是在水裡有個氣泡,他一直往上冒一樣。

我就不多說了。直接看**:

/*

簡單氣泡排序

*/void buble(int a, int n)

} }}

直接來說優化。我們記錄下最後一次發生交換的地方,之後的都是有序的

/*

* 改進,記錄最後一次交換的位置,則這個位置之後的是有序的,無交換則全有序

*/void buble1(int a, int n)

} i = pos;//之後的有序,不用再遍歷

}}

第二種優化,我們可以同時首尾都進行冒泡,一次找到乙個最大的,乙個最小的。可能我寫的**有問題。經過我多次試驗,效率反而下降。。或者資料很不湊巧。

/*

首尾同時進行氣泡排序。

*/void buble2(int a, int n)

} high--;

//找到最小的

for ( i = high; i > low; i--)

}low++;

}}

選擇排序的思想,一次選出乙個最大的數,或者找到最小的數。

**

/*

選擇排序

*/void choosesort(int a, int n)

} }}

優化的話,一次其實也可以找到乙個最大值,乙個最小值,我實際測試的時候,發現還是有很大提公升的。

/*

選擇排序,每次找到最大和最小

*/void choosesort1(int a, int n)

if (max < a[j])

}swap(a[i], a[minpos]);

swap(a[j], a[maxpos]);

}}

陣列前面的是有序的。後面的數,插入到前面有序部分相應的位置。

/*

*插入排序

*/void insertsort(int a, int n)

a[++j] = temp;

}}

優化的話。。沒想到啥。。。

快速排序:

快速排序的思想是一次確定乙個數的位置,使得他左邊比他小,右邊比他大。

/*

快速排序

*/void quiksort(int a, int n)

while (i < j)

a[j] = a[i];

} a[i] = temp;

quiksort(a, i );

quiksort(a + i + 1, n - i -1 );

}

對快排的優化,可以從下面的幾點出發,

1、與關鍵碼(樞軸)相同的數,可以移動到中間,下次不再參與遞迴。

2、樞軸的選擇很重要。如果每次都選擇第乙個,則有可能出現一種情況,那就是已經是乙個有序的陣列的話,快排退化到冒泡。。。所以選取樞軸,盡量讓這個樞軸就是靠近資料中間位置的數,這個可以選擇陣列兩端和中間的三個數做比較,選取第二大的(中間數)作為樞軸,但是如果陣列很大,這估計也不能得到比較好的效果,所以還有一種方法,選取前三個數,取中數,中間三個數,去中數,最後的三個數,取中數,然後在這三個中數中再選取中數,以最後選取出來的這個中數作為樞軸。其實覺得還可以把陣列分成三部分,0-1/4,1/4-3/4,3/4-1,主要是可以用位移運算才這麼分。然後分別取三個區間的中位數比較,最後再取三個中位數的中位數作為樞軸。

例如 13,33,3,4,43,55,44,23,66,88,99

第一種選取13,55, 99,比較獲得樞軸為55。

第一種選取13,33, 3,選取13。中間三個43,55,44選取44。 後面三個66,88,99,選取88,然後13,44,88再比較,最終選取44作為樞軸。

第三種選取13,43,44,  66,99,最後比較取 44 這個中間數作為樞軸。

3、當一次比較之後分出的子區間的個數很小。接近於8個左右,可以採用插入排序對這個子區間進行排序。

4、遞迴改為迴圈,明顯第乙個遞迴很好改,但是第二個遞迴就不那麼好改了。

基於以上說明。貼出**

//獲得三個數中第二大的數的位置

int getmidnumpos(int arr,int a, int b,int c)

void quiksort1(int a, int n)

int i, j, temp;

if (n <= 7)

a[++j] = temp;

}return;

}else if ( n <= 40 )

else

int h, t;

h =    i = 0;

t = j = n - 1;

while (true)

i++;

}while (i<=j && temp <= a[j])

j--;

}    

if (i>j)

swap(a[i], a[j]);

i++;

j--;

}//把移動到兩邊與樞軸相同的數移動到中間。下次不再遞迴

for (int k = 0; k < h; k++)

for (int k = n-1; k >t ; k--)

quiksort1(a, i);

quiksort1(a + j + 1 , n - j - 1 );

}

做了一些改變之後的快排:

void quiksort2(int arr, int len)

a[++j] = temp;

}return;

} else if (n <= 40)

else

h = i = 0;

t = j = n - 1;

while (true)

i++;

}while (i <= j && temp <= a[j])

j--;

}if (i > j)

swap(a[i], a[j]);

i++;

j--;

} ti = i;

//移動次數可以調整

steps = (h < (ti - h)) ? h : (ti - h);

for ( k = 0; k < steps; k++)

len = i - h + 1;

tj = j;

steps = (n - 1 - t) < (t - j) ? (n - 1 - t) : (t - j);

for ( k = 0; k

以上說明,**如有問題,請斧正,感激不盡。

謝謝。

氣泡排序 選擇排序 插入排序 快速排序

include 氣泡排序,思想 從最末位開始 往前一位一位比較,比前一位小的話,就交換位置 兩個for,第乙個for迴圈用於記錄已排序的位置,第二個for迴圈用於已排序位置到結束位置之間的氣泡排序 void popsort int p int n 選擇排序,由前往後選擇最小的數。一輪比較完後,將最小...

氣泡排序 選擇排序 插入排序 快速排序

氣泡排序 元素兩兩比較,大的往後放,經過一輪比較後,那麼最大的元素就會出現在最後面。public static void main string args for int j 0 j arr i 1 system.out.println arrays.tostring arr 每次拿乙個元素,跟他後...

氣泡排序 選擇排序 快速排序 插入排序

排序只對一維資料有意義.兩層迴圈,第一層是遍歷每乙個元素.第二層迴圈,讓兩兩之間進行比較交換.時間複雜度 o n 2 空間複雜度 o 1 穩定性 穩定的 def buble sort arr for i in range len arr 1 for j in range len arr i 1 if...