日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

c语言实现快速排序对文件中字符,C语言中快速排序和插入排序优化的实现

發布時間:2023/12/19 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c语言实现快速排序对文件中字符,C语言中快速排序和插入排序优化的实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

快速排序快速排序思想

1962年,由C.A.R.Hoare創造出來。該算法核心思想就一句話:“排序數組時,將數組分成兩個小部分,然后對它們遞歸排序”。然而采取什么樣的策略將數組分成兩個部分是關鍵,想想看,如果隨便將數組A分成A1和A2兩個小部分,即便分別將A1和A2排好序,那么A1和A2重新組合成A時仍然是無序的。所以,我們可以在數組中找一個值,稱為key值,我們在把數組A分解為A1和A2前先對A做一些處理,讓小于key值的元素都移到其左邊,所有大于key值的元素都移到其右邊。這樣遞歸排序A1和A2,數組A就排好了。

舉例

我們要排序的數組如下:

55 41 59 26 53 58 97 93

我們選取第一個元素作為key值,即55.(一般都是選取第一個元素)。假如我們有一種辦法可以將數組做一步預處理,讓小于key值的元素都位于其左邊,大于key值的元素都位于其右邊,預處理完數組如下:

41 26 53 55 59 58 97 93

這樣數組就被key值劃分成了兩段,A[0...2]小于key,A[4...7]大于key,可見key值本身已排好序,接下來對A[0...2]和A[4...7]分別進行遞歸排序,那么整個數組就排好序了。預處理做的工作再次澄清下:找一個key值,把key位放到某位置A[p],使小于key值的元素都位于A[p]左邊,大于key值的元素都位于A[p]的右邊。到此,我們的快排模型就成型了。

/*l, u 代表待排序部分的下界和上界*/

void qsort(l, u)

{

/*遞歸結束條件是待排序部分的元素個數小于2*/

if(l >= u)

{

return;

}

/*此處進行預處理,預處理后key值位于位置p*/

qsort(l, p-1);

qsort(p+1, u);

}

接下來看如何做預處理。我們選取A[0]做為key值, p作為key值的位置。我們從A[1]開始遍歷后面的數組,用變量i指示目前的位置,每次找到小于key的值都與A[++p]交換。開始時p=0.

55?41?59?26?53?58?97?93 i = 1,A[i]位置為41, 即A[i] < key, swap(++p , i),即p = 1:

55?41?59?26?53?58?97?93 i = 2,A[i]位置為59,A[i] > key,不做任何改變。

i = 3,A[i]位置為26,A[i] < key,swap(++p, i), 即p = 2:

55?41?26?59?53?58?97?93 i = 4,A[i]位置為53,A[i] < key,swap(++p, i),p = 3:

55?41?26?53?59?58?97?93 i = 5,A[i]位置為58,A[i] > key,不做任何改變。

i = 6,A[i]位置為97,A[i] > key,不做任何改變.

i = 7,A[i]位置為93,A[i] > key,不做任何改變.結束循環。此時p為key的最終位置。還需一步把key值填入p位置。

最后swap(l, p)即把Key值放到最終位置上了。至于為什么要交換l,p的位置,可以另拿一組數據試一下:55,41,59,26,99,58,97,93。

完整的程序1

/*l, u 代表待排序部分的下界和上界*/

void qsort(int l, int u)

{

/*遞歸結束條件是待排序部分的元素個數小于2*/

if(l >= u)

{

return;

}

int p = l;

for(int i = l+1; i <= u; i++)

{

if(A[i] < A[l])

{

swap(++p, i);

}

}

swap(l, p);

qsort(l, p-1);

qsort(p+1, u);

}

這就是第一代快速排序算法,正常情況下其復雜度為nlogn,但在考慮一種極端情況:n個相同元素組成的數組。在n-1次劃分中每次劃分都需要O(n)的時間,所以總的時間為O(n^2)。使用雙向劃分就可以避免這個問題。

雙向劃分快速排序

/*l, u 代表待排序部分的下界和上界*/

void qsort(int l, int u)

{

/*遞歸結束條件是待排序部分的元素個數小于2*/

if(l >= u)

{

return;

}

key = A[l]

for(int i = l, j = u+1; i <= j;)

{

do i++ while(i <= u && A[i] < key));

do j-- while(A[j] > key);

if(i > j)

{

break;

}

swap(i, j);

}

swap(l, j);

qsort(l, j-1);

qsort(j+1, u);

}

插入排序優化插入排序的精髓就是首先將第一個元素視為有序子數組x[0...0],然后插入x[1]...x[n-1].思想很簡單,代碼也很簡單,簡單的代碼有沒有優化的空間呢?編程珠璣中提供了幾個優化后的方案,效率提高了70%之多。

簡單的實現(sort1)

void insertSort(int *array, size_t size)

{

for(size_t i = 1; i < size; i++)

{

for(int j = i; j > 0 && array[j - 1] > array[j]; j--)

{

swap(array[j - 1], array[j]);

}

}

}

優化思路

內循環的swap函數可能不如內聯函數快些,所以第一步優化將該swap函數展開,據作者說,展開后效率提高了60%。

優化代碼(sort2)

void insertSort(int *array, size_t size)

{

for(size_t i = 1; i < size; i++)

{

for(int j = i; j > 0 && array[j - 1] > array[j]; j--)

{

int t = array[j];

array[j] = array[j - 1];

array[j - 1] = t;

}

}

}

優化思路

由于內循環中總是給變量t賦同樣的值(x[i]的初始值),所以內循環關于t的兩條賦值語句移出循環,據說這么做的效率又提高了15%。

優化代碼(sort3)

void insertSort(int *array, size_t size)

{

for(size_t i = 1; i < size; i++)

{

int j = i;

int t = array[j];

for(; j > 0 && array[j - 1] > array[j]; j--)

{

array[j] = array[j - 1];

}

array[j] = t;

}

}

《編程珠璣》書中給出了三種排序的運行時間:

插入排序的效率總是O(n2),效率差在比較的次數以及交換的頻率,如果交換的頻率減少的話就可以大大提高插入排序的效率,這也是為什么元素基本有序時插入排序效率高的原因。

個人觀點

代碼調優以及性能優化都可能帶來一系列的副作用,比如程序的正確性,可讀性,可維護性等。是否需要調優要看問題性質,調優既是華而不實的“花活”,也是一把利刃,區別就在于使用的場合。

總結

以上是生活随笔為你收集整理的c语言实现快速排序对文件中字符,C语言中快速排序和插入排序优化的实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。