中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

深圳網(wǎng)站設(shè)計(jì)價(jià)格表優(yōu)化大師下載舊版本安裝

深圳網(wǎng)站設(shè)計(jì)價(jià)格表,優(yōu)化大師下載舊版本安裝,做qq的網(wǎng)站,南京營(yíng)銷型網(wǎng)站建設(shè)公司> 作者簡(jiǎn)介:?舊言~,目前大一,現(xiàn)在學(xué)習(xí)Java,c,c,Python等 > 座右銘:松樹千年終是朽,槿花一日自為榮。 > 目標(biāo):掌握每種排序的方法,理解每種排序利弊…

> 作者簡(jiǎn)介:?舊言~,目前大一,現(xiàn)在學(xué)習(xí)Java,c,c++,Python等
> 座右銘:松樹千年終是朽,槿花一日自為榮。

> 目標(biāo):掌握每種排序的方法,理解每種排序利弊和復(fù)雜度。

> 毒雞湯:船停在碼頭是最安全的,但那不是造船的目的;人呆在家里是最舒服的,但那不是人生的意義。最美好的生活方式,莫過于和一群志同道合的人奔跑在理想的路上!
> 望小伙伴們點(diǎn)贊👍收藏?加關(guān)注喲💕💕?

🌟前言?

? ? ? ? 談起排序這個(gè)事情,大家都是耳熟能詳?shù)氖铝?#xff0c;從我們認(rèn)識(shí)的斗地主,每一復(fù)牌都是按照從小到大的順序排序的,如圖:


? ? ? ?排序的目的是為了讓我們很好的管理,使無序的事情變成有序,當(dāng)然排序的方法有很多,如由大到小,由大到小.....。而面對(duì)大量數(shù)據(jù)就需要排序。在數(shù)據(jù)結(jié)構(gòu)中我們發(fā)明了多種排序,如我們最早認(rèn)識(shí)的冒泡排序,本篇博客讓大家對(duì)多種排序有一個(gè)很好的認(rèn)知,閑話少談。

?主體??

咱們就掌握八種就行啦


🌙冒泡排序

這里博主在C語言刷題訓(xùn)練專欄中講到過冒泡排序,咱們?cè)倩仡櫥仡?img referrerpolicy="no-referrer" alt="" height="28" src="https://img-blog.csdnimg.cn/37a1f48659d84b0197d13a1abcc579b9.png" width="28" />


這里我們以接口的形式寫代碼,那咱們上代碼咯


//冒泡排序測(cè)試
void BubbleSort(int* a, int n)
{for (int i = 0; i < n - 1; i++){int exchange = 0;for (int j = 1; j < n - i; j++){if (a[i - 1] > a[i]){//這里是一個(gè)交換函數(shù)Swap(&a[i - 1], &a[i]);exchange = 1;}}//這里進(jìn)行一趟有序時(shí),直接跳出循環(huán)if (exchange == 0){break;}}
}

注意事項(xiàng):
💦1.我們知道當(dāng)給的數(shù)據(jù)有序時(shí),就不再需要進(jìn)行循環(huán)了,直接跳出循環(huán)(exchange作用)。
💦2. 第二個(gè)循環(huán)中??j < n - i? 不能搞錯(cuò)。

時(shí)間復(fù)雜度:O(N2)

空間復(fù)雜度:O(1)

穩(wěn)定性:穩(wěn)定

復(fù)雜性:簡(jiǎn)單

🌙直接插入排序

直接插入排序是一種簡(jiǎn)單的插入排序法,其基本思想是: 把待排序的記錄按其關(guān)鍵碼值的大小逐個(gè)插入到一個(gè)已經(jīng)排好序的有序序列中,直到所有的記錄插入完為止,得到一個(gè)新的有序序列 ,就好像我們斗地主拿牌插入相似。

咱們看看一個(gè)動(dòng)態(tài)的插入動(dòng)作。

?這里我們以接口的形式寫代碼,那咱們上代碼咯


//插入排序
void InsertSort(int* a, int n)
{for (int i = 0; i < n - 1; i++){int end = i;int tmp = a[end + 1];//一個(gè)元素進(jìn)行插入while (end >= 0){if (tmp < a[end]){a[end + 1] = a[end];}else{break;}--end;}//最后把插入的元素賦值回去a[end + 1] = tmp;}
}

注意事項(xiàng):
💦1.我們先進(jìn)行第end個(gè)元素移動(dòng),再進(jìn)行n個(gè)元素進(jìn)行移動(dòng)。
💦2. 最后需要a[end + 1] = tmp賦值

時(shí)間復(fù)雜度:O(N2)

空間復(fù)雜度:O(1)

穩(wěn)定性:穩(wěn)定

復(fù)雜性:簡(jiǎn)單

🌙希爾排序

? ? ? ?希爾排序法又稱縮小增量法。希爾排序法的基本思想是:先選定一個(gè)整數(shù),把待排序文件中所有記錄分成個(gè)組,所有距離為的記錄分在同一組內(nèi),并對(duì)每一組內(nèi)的記錄進(jìn)行排序。然后,取,重復(fù)上述分組和排序的工作。當(dāng)?shù)竭_(dá)=1時(shí),所有記錄在統(tǒng)一組內(nèi)排好序。咱們看看下面的圖解:



在看看一個(gè)動(dòng)態(tài)的圖解:


??這里我們以接口的形式寫代碼,那咱們上代碼咯

//希爾排序測(cè)試
void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){//間隔gap的元素進(jìn)行排序gap = gap / 3 + 1;//本質(zhì)上是插入排序for (int i = 0; i < n - gap; ++i){int end = i;int tmp = a[end + gap];//一個(gè)元素進(jìn)行插入while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end = end - gap;}else{break;}}//最后把插入的元素賦值回去a[end + gap] = tmp;}}
}

注意事項(xiàng):
💦1.首先先嵌套一個(gè)插入排序,再把分組的元素進(jìn)行交換。
💦2.?gap = gap / 3 + 1這個(gè)不要忘記。

時(shí)間復(fù)雜度:O(N1·23)

空間復(fù)雜度:O(1)

穩(wěn)定性:不穩(wěn)定

復(fù)雜性:復(fù)雜

🌙選擇排序

? ? ? ?基本思想:每一次從待排序的數(shù)據(jù)元素中選出最小(或最大)的一個(gè)元素,存放在序列的起始位置,直到全部待排序的數(shù)據(jù)元素排完 。咱們看看圖解:


?

這里我們看一個(gè)動(dòng)態(tài)的圖解:

?

上代碼:

//選擇排序測(cè)試
void SelectSort(int* a, int n)
{//初始化第一個(gè)元素 和 最后一個(gè)元素int begin = 0;int end = n - 1;while (begin < end){//選出最大值和最小值int mini = begin, maxi = begin;for (int i = begin + 1; i <= end; i++){if (a[i] > a[maxi]){maxi = i;}if (a[i] < a[mini]){mini = i;}}//最小值和最初的元素交換Swap(&a[begin], &a[mini]);//如果max被換走就需要重新賦值if (maxi == begin){maxi = mini;}//最大值和最末的元素交換Swap(&a[end], &a[maxi]);++begin;--end;}
}

注意事項(xiàng):
💦1.這里先找到最小值和最大值,然后交換到最前面和最后面,一次進(jìn)行。
💦2. 如果最大值被交換后,需要從新賦值。

時(shí)間復(fù)雜度:O(N2)

空間復(fù)雜度:O(1)

穩(wěn)定性:不穩(wěn)定

復(fù)雜性:簡(jiǎn)單

🌙堆排序

? ? ? ?堆排序(Heapsort)是指利用堆積樹(堆)這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計(jì)的一種排序算法,它是選擇排序的一種。它是通過堆來進(jìn)行選擇數(shù)據(jù)。需要注意的是排升序要建大堆,排降序建小堆。咱們看看圖解:



再看看動(dòng)態(tài)的圖解:



上代碼:

//堆排序測(cè)試
//實(shí)現(xiàn)向下調(diào)整建大堆
void AdjustDown(int* a, int n, int parent)
{//孩子和父親的關(guān)系 int child = parent * 2 + 1;while (child < n){//找出小的那個(gè)孩子if (child + 1 < n && a[child + 1] < a[child]){++child;}//實(shí)現(xiàn)向下調(diào)整元素if (a[child] < a[parent]){//元素交換Swap(&a[child], &a[parent]);// 繼續(xù)往下調(diào)整parent = child;child = parent * 2 + 1;}else{break;}}
}//堆排序測(cè)試
void HeapSort(int* a, int n)
{//向下調(diào)整建堆for (int i = (n - 1 - 1) / 2; i >= 0; i--){//實(shí)現(xiàn)向下調(diào)整建大堆AdjustDown(a, n, i);}int end = n - 1;while (end > 0){//元素交換Swap(&a[0], &a[end]);//實(shí)現(xiàn)向下調(diào)整建大堆AdjustDown(a, end, 0);--end;}
}

注意事項(xiàng):
💦1.首先我們需要建大堆(以在二叉樹講解咯),交換,再建大堆
💦2. 每交換一個(gè)元素都需要再建一次大堆。

時(shí)間復(fù)雜度:O(NlogN)

空間復(fù)雜度:O(1)

穩(wěn)定性:不穩(wěn)定

復(fù)雜性:復(fù)雜

🌙快排

? ? ? ? 在快排這個(gè)板塊中我將講述四個(gè)方法,希小伙伴都能掌握。

? ? ? ? 快速排序是Hoare于1962年提出的一種二叉樹結(jié)構(gòu)的交換排序方法,其基本思想為:任取待排序元素序列中的某元素作為基準(zhǔn)值,按照該排序碼將待排序集合分割成兩子序列,左子序列中所有元素均小于基準(zhǔn)值,右子序列中所有元素均大于基準(zhǔn)值,然后最左右子序列重復(fù)該過程,直到所有元素都排列在相應(yīng)位置上為止。

💫Hoare方法

? ? ? ?在動(dòng)態(tài)圖中,key稱為基準(zhǔn)值,默認(rèn)把基準(zhǔn)值定義在數(shù)組的首元素上,其次為了加快遍歷的速度,需要用到兩個(gè)變量分別去對(duì)應(yīng)數(shù)組的首尾部分,L處在數(shù)列的首部,它需要從左往右尋找比Keyi位置的值大的,遇到后就停下來,沒遇到就一直走;R處在數(shù)列的尾部,它需要從右往左去尋找比keyi位置的值小的,也是遇到后就停下來,沒遇到就一直走。

? ? ? ? 當(dāng)L與R都遇到停下來后開始互換位置,然后繼續(xù)遍歷,直到L==R時(shí),雙方都不會(huì)再走了,因?yàn)樗鼈冏叩搅送粋€(gè)位置,這個(gè)位置被稱為它倆的相遇點(diǎn),之后便需要將keyi位置的值與相遇點(diǎn)的值互換位置,這樣keyi位置的值就放到了中間,成為了數(shù)組的中心——基準(zhǔn)值,它意味著將數(shù)組分為兩個(gè)子序列,左序列全是小于Keyi的值,右序列全是大于Keyi的值,這樣便可以利用遞歸,一層一層再對(duì)左右兩個(gè)子序列進(jìn)行相同的步驟——將一個(gè)大的無序序列轉(zhuǎn)化為多個(gè)小的序列,從而進(jìn)行排序,最終排列為完全有序的序列。
?



上代碼:

//三數(shù)取中 (找出中間值)
int GetMidi(int* a, int left, int right)
{//中間值int mid = (left + right) / 2;//三個(gè)數(shù)比較找出中間值if (a[left] < a[mid]){if (a[mid] < a[right]){return mid;}else if (a[left] > a[right]){return left;}else{return right;}}else{if (a[mid] > a[right]){return mid;}else if (a[left] < a[right]){return left;}else{return right;}}
}// 右邊找小,左邊找大,交換,把左邊的值跟a[keyi]交換
int PartSort1(int* a, int left, int right)
{//找中間值(相對(duì))int midi = GetMidi(a, left, right);//把最左邊(相對(duì))跟中間值(相對(duì))換Swap(&a[left], &a[midi]);//定位最左邊(相對(duì))int keyi = left;while (left < right){//找小while (left < right && a[right] >= a[keyi]){--right;}//找大while (left < right && a[left] <= a[keyi]){++left;}//左右交換Swap(&a[left], &a[right]);}//此時(shí)左邊走到中間了,開始交換Swap(&a[keyi], &a[left]);//返回return left;
};

注意事項(xiàng):
💦1.首先先找到中間值。
💦2.再和最左邊元素互換

💦3.左邊找比(中間值)大的數(shù),右邊找(中間值)小的數(shù),然后左右值交換。

💦4.此時(shí)左邊走到中間了,開始交換

💦5.上述進(jìn)行循環(huán),知道排序完成

💫挖坑法

大家就看一下下面圖解:



//三數(shù)取中 (找出中間值)
int GetMidi(int* a, int left, int right)
{//中間值int mid = (left + right) / 2;//三個(gè)數(shù)比較找出中間值if (a[left] < a[mid]){if (a[mid] < a[right]){return mid;}else if (a[left] > a[right]){return left;}else{return right;}}else{if (a[mid] > a[right]){return mid;}else if (a[left] < a[right]){return left;}else{return right;}}
}//挖坑法
int PartSort2(int* a, int left, int right)
{//找中間值(相對(duì))int midi = GetMidi(a, left, right);//把最左邊(相對(duì))跟中間值(相對(duì))換Swap(&a[left], &a[midi]);//定位最左邊(相對(duì))int key = a[left];//保存key值以后,左邊形成第一個(gè)坑int hole = left;while (left < right){//右邊先走,找小,填到左邊的坑,右邊形成新的坑位while (left < right && a[right] >= key){--right;}a[hole] = a[right];hole = right;//左邊再走,找大,填到右邊的坑,左邊形成新的坑位while (left < right && a[left] <= key){++left;}a[hole] = a[left];hole = left;}a[hole] = key;return hole;
}

💫前后指針

? ? ? ?通過創(chuàng)建兩個(gè)指針,prev指針指向數(shù)組序列首元素位置,cur指向prev的下一個(gè)位置,cur通過遍歷去尋找比key基準(zhǔn)值小的,若找到了,還得看prev的下一個(gè)位置是否為cur所處的位置,若prev的下一個(gè)位置確實(shí)為cur所處位置,則將cur指向的值與prev指向的值進(jìn)行互換,若prev的下一個(gè)位置不是cur所處位置,則cur繼續(xù)往后遍歷,直到cur遍歷結(jié)束,最后要將key基準(zhǔn)值與prev指向的值進(jìn)行互換,最終確認(rèn)基準(zhǔn)值處于數(shù)組序列的中間位置。




//三數(shù)取中 (找出中間值)
int GetMidi(int* a, int left, int right)
{//中間值int mid = (left + right) / 2;//三個(gè)數(shù)比較找出中間值if (a[left] < a[mid]){if (a[mid] < a[right]){return mid;}else if (a[left] > a[right]){return left;}else{return right;}}else{if (a[mid] > a[right]){return mid;}else if (a[left] < a[right]){return left;}else{return right;}}
}//前后指針
int PartSort3(int* a, int left, int right)
{//找中間值(相對(duì))int midi = GetMidi(a, left, right);//把最左邊(相對(duì))跟中間值(相對(duì))換Swap(&a[left], &a[midi]);//定義指針開頭int prev = left;//定義指針開頭后一個(gè)int cur = prev + 1;int keyi = left;while (cur <= right){if (a[cur] < a[keyi] && ++prev != cur){Swap(&a[prev], &a[cur]);}++cur;}//交換Swap(&a[prev], &a[keyi]);return prev;
}

💫快排非遞歸

1.初始化我們的棧。

2.入棧把我們的開始的left==0 ?right==n-1;

3.進(jìn)入我們的循環(huán)體循環(huán)體進(jìn)入的條件是判斷棧中是否還有數(shù)值如果有數(shù)值的化什么其中的數(shù)值對(duì)應(yīng)的范圍還是沒有序的就需要出棧(這個(gè)時(shí)候就需要進(jìn)行出棧(注意棧的數(shù)值的左右范圍的對(duì)應(yīng)))進(jìn)行我們的挖坑排序(對(duì)于挖坑我們應(yīng)該把key返回出來通過key的數(shù)值進(jìn)行我們?cè)僖淮蔚娜霔2僮魍瑫r(shí)我們的范圍)。

3.1[left ? key-1] 和[key+1 ? right] ? 這樣的范圍滿足條件才能繼續(xù)push ?之后pop進(jìn)行我們的排序;

4如果說我們的循環(huán)體結(jié)束了的話我們的數(shù)組就一定有序!



前面已經(jīng)講述了棧,這里就不再實(shí)現(xiàn)棧了

//快排非遞歸(采用棧的形式)(先進(jìn)后出)
void QuickSortNonR(int* a, int begin, int end)
{//定義ST st;//初始化STInit(&st);//添加元素STPush(&st, end);STPush(&st, begin);while (!STEmpty(&st)){//剝離元素  讓left取先入但是后出的元素(區(qū)間的左邊)int left = STTop(&st);STPop(&st);//讓right取棧頂元素(是我們后入的區(qū)間的右邊)int right = STTop(&st);STPop(&st);// 右邊找小,左邊找大,交換,把左邊的值跟a[keyi]交換int keyi = PartSort1(a, left, right);//分割成段 // [lefy,keyi-1] keyi [keyi+1, right]if (keyi + 1 < right){//添加元素STPush(&st, right);STPush(&st, keyi + 1);}if (left < keyi - 1){//添加元素STPush(&st, keyi - 1);STPush(&st, left);}}//銷毀STDestroy(&st);
}

🌙歸并排序

這里講述兩種方法,一種是遞歸型另一種則是非遞歸

💫歸并排序遞歸型

? ? ? ? 歸并排序(MERGE-SORT)是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法(Divide andConquer)的一個(gè)非常典型的應(yīng)用。將已有序的子序列合并,得到完全有序的序列;即先使每個(gè)子序列有序,再使子序列段間有序。若將兩個(gè)有序表合并成一個(gè)有序表,稱為二路歸并。 歸并排序核心步驟:



void _MergeSort(int* a, int* tmp, int begin, int end)
{//尾小于頭時(shí)if (end <= begin)return;//開始分割int mid = (end + begin) / 2;// [begin, mid][mid+1, end]_MergeSort(a, tmp, begin, mid);_MergeSort(a, tmp, mid + 1, end);//歸并到tmp數(shù)據(jù)組,再拷貝回去//a->[begin, mid][mid+1, end]->tmpint begin1 = begin, end1 = mid;int begin2 = mid + 1, end2 = end;int index = begin;//開始拷貝while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[index++] = a[begin1++];}else{tmp[index++] = a[begin2++];}}//當(dāng)?shù)谝欢卧貨]有完全拷貝完就把剩下的拷貝進(jìn)去while (begin1 <= end1){tmp[index++] = a[begin1++];}//當(dāng)?shù)诙卧貨]有完全拷貝完就把剩下的拷貝進(jìn)去while (begin2 <= end2){tmp[index++] = a[begin2++];}//拷貝回原數(shù)組memcpy(a + begin, tmp + begin, (end - begin + 1) * sizeof(int));
}//歸并排序(分路并歸)
void MergeSort(int* a, int n)
{//開辟空間int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");return;}//調(diào)用_MergeSort(a, tmp, 0, n - 1);//釋放內(nèi)存free(tmp);
}

💫歸并排序非遞歸型

? ? ? ?第一次當(dāng) gap 為 1 的時(shí)候,我們將距離為 1 的兩個(gè)數(shù)組(其實(shí)就是兩個(gè)元素為 1 的數(shù))進(jìn)行歸并,得到了擁有兩個(gè)元素的一個(gè)有序數(shù)組,然后通過循環(huán)將后面的元素全部用同樣的方式歸并。然后就得到了如上圖所示藍(lán)色表示的元素排布。同時(shí)我們?cè)趯⑦@一步驟之后的數(shù)組拷貝回到原數(shù)組。在進(jìn)行接下來的操作(這里的意思和上遞歸的是一樣的)。接著每次將 gap 的值增加 2 倍,直到 gap 的值不小于 n 結(jié)束歸并。這個(gè)過程我們將其稱為小區(qū)間優(yōu)化。



//歸并排序(非遞歸)
void MergeSortNonR(int* a, int n)
{//開辟空間int* tmp = (int*)malloc(sizeof(int) * n);//判斷if (tmp == NULL){perror("malloc fail");return;}int gap = 1;while (gap < n){for (int i = 0; i < n; i += 2 * gap){int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;// [begin1,end1] [begin2,end2] 歸并// 如果第二組不存在,這一組不用歸并了if (begin2 >= n){break;}// 如果第二組的右邊界越界,修正一下if (end2 >= n){end2 = n - 1;}//printf("[%d,%d][%d,%d] ", begin1, end1, begin2, end2);int index = i;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[index++] = a[begin1++];}else{tmp[index++] = a[begin2++];}}while (begin1 <= end1){tmp[index++] = a[begin1++];}while (begin2 <= end2){tmp[index++] = a[begin2++];}// 拷貝回原數(shù)組memcpy(a + i, tmp + i, (end2 - i + 1) * sizeof(int));}printf("\n");gap *= 2;}free(tmp);
}

🌙計(jì)數(shù)排序

計(jì)數(shù)排序的樸素方法步驟:

? ? ? ? 1、從無序數(shù)組中取出最大值max,新建一個(gè)長(zhǎng)度為max+1的數(shù)組。

? ? ? ? 2、遍歷無序數(shù)組,取其中元素作為新建數(shù)組的索引,存在一個(gè)則新數(shù)組該索引所在的值自增。

? ? ? ? 3、遍歷新數(shù)組,當(dāng)存在不為0的元素,取該元素的索引放入最終數(shù)組,并且該元素自減,直到為0,返回最終數(shù)組。
?



上代碼:

//計(jì)數(shù)排序測(cè)試
void CountSort(int* a, int n)
{//找最大值和最小值int min = a[0], max = a[0];for (size_t i = 0; i < n; i++){if (a[i] < min)min = a[i];if (a[i] > max)max = a[i];}//找出區(qū)間int range = max - min + 1;//開辟(區(qū)間)int* count = (int*)malloc(sizeof(int) * range);printf("range:%d\n", range);//判斷if (count == NULL){perror("malloc fail");return;}//計(jì)入數(shù)字的個(gè)數(shù)memset(count, 0, sizeof(int) * range);// 統(tǒng)計(jì)數(shù)據(jù)出現(xiàn)次數(shù)for (int i = 0; i < n; i++){count[a[i] - min]++;}//排序int j = 0;for (int i = 0; i < range; i++){while (count[i]--){a[j++] = i + min;}}
}

??總結(jié)

咱看看每種排序的復(fù)雜度和穩(wěn)定性。


?🌠Sort.h代碼


#include<stdio.h>//打印數(shù)據(jù)
void PrintArray(int* a, int n);//冒泡排序測(cè)試
void BubbleSort(int* a, int n);
//插入排序測(cè)試
void InsertSort(int* a, int n);
//希爾排序測(cè)試
void ShellSort(int* a, int n);
//選擇排序測(cè)試
void SelectSort(int* a, int n);
//堆排序測(cè)試
void HeapSort(int* a, int n);//快排測(cè)試
void QuickSort1(int* a, int begin, int end);
void QuickSort2(int* a, int begin, int end);
//快排非遞歸測(cè)試
void QuickSortNonR(int* a, int begin, int end);//歸并排序測(cè)試
void MergeSort(int* a, int n);
//歸并排序(非遞歸)測(cè)試
void MergeSortNonR(int* a, int n);
//計(jì)數(shù)排序測(cè)試
void CountSort(int* a, int n);

🌠Test.c代碼

#define _CRT_SECURE_NO_WARNINGS 1#include<time.h>
#include<stdlib.h>
#include"Sort.h"
#include"Stack.h"//希爾排序測(cè)試
void TestShellSort()
{int a[] = { 9,1,2,5,7,4,8,6,3,5,1,2,3,5,1,8,3 };ShellSort(a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}//冒泡排序測(cè)試
void TestBubbleSort()
{int a[] = { 9,1,2,5,7,4,8,6,3,5,1,2,3,5,1,8,3 };BubbleSort(a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}//堆排序測(cè)試
void TestHeapSort()
{int a[] = { 9,1,2,5,7,4,8,6,3,5,1,2,3,5,1,8,3 };HeapSort(a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}//選擇排序測(cè)試
void TestSelectSort()
{int a[] = { 9,1,2,5,7,4,8,6,3,5,1,2,3,5,1,8,3 };SelectSort(a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}//測(cè)試代碼
void TestOP()
{srand(time(0));const int N = 100000;int* a1 = (int*)malloc(sizeof(int) * N);int* a2 = (int*)malloc(sizeof(int) * N);int* a3 = (int*)malloc(sizeof(int) * N);int* a4 = (int*)malloc(sizeof(int) * N);int* a5 = (int*)malloc(sizeof(int) * N);int* a6 = (int*)malloc(sizeof(int) * N);int* a7 = (int*)malloc(sizeof(int) * N);for (int i = N - 1; i >= 0; --i){a1[i] = rand();a2[i] = a1[i];a3[i] = a1[i];a4[i] = a1[i];a5[i] = a1[i];a6[i] = a1[i];a7[i] = a1[i];}int begin1 = clock();//插入排序InsertSort(a1, N);int end1 = clock();int begin2 = clock();//希爾排序測(cè)試ShellSort(a2, N);int end2 = clock();int begin7 = clock();//冒泡排序測(cè)試BubbleSort(a7, N);int end7 = clock();int begin3 = clock();//選擇排序測(cè)試SelectSort(a3, N);int end3 = clock();int begin4 = clock();//堆排序測(cè)試HeapSort(a4, N);int end4 = clock();int begin5 = clock();//快排測(cè)試//QuickSort(a5, 0, N - 1);int end5 = clock();int begin6 = clock();//MergeSort(a6, N);//計(jì)數(shù)排序測(cè)試//CountSort(a6, N);int end6 = clock();printf("InsertSort:%d\n", end1 - begin1);printf("ShellSort:%d\n", end2 - begin2);printf("BubbleSort:%d\n", end7 - begin7);printf("SelectSort:%d\n", end3 - begin3);printf("HeapSort:%d\n", end4 - begin4);printf("QuickSort:%d\n", end5 - begin5);printf("MergeSort:%d\n", end6 - begin6);printf("CountSort:%d\n", end6 - begin6);free(a1);free(a2);free(a3);free(a4);free(a5);free(a6);free(a7);
}int main()
{TestOP();//TestBubbleSort();//TestHeapSort();//TestSelectSort();//TestQuickSort();//TestMergeSort();//TestCountSort();//printf("%d\n", Func(100000));return 0;
}

?🌠Sort.c代碼

#define _CRT_SECURE_NO_WARNINGS 1#include"Sort.h"
#include"Stack.h"//交換函數(shù)
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}//打印數(shù)據(jù)
void PrintArray(int* a, int n)
{//循環(huán)for (int i = 0; i < n; i++){printf("%d ", a[i]);}printf("\n");
}//冒泡排序測(cè)試
void BubbleSort(int* a, int n)
{for (int i = 0; i < n - 1; i++){int exchange = 0;for (int j = 1; j < n - i; j++){if (a[i - 1] > a[i]){//這里是一個(gè)交換函數(shù)Swap(&a[i - 1], &a[i]);exchange = 1;}}//這里進(jìn)行一趟有序時(shí),直接跳出循環(huán)if (exchange == 0){break;}}
}//插入排序
void InsertSort(int* a, int n)
{for (int i = 0; i < n - 1; i++){int end = i;int tmp = a[end + 1];//一個(gè)元素進(jìn)行插入while (end >= 0){if (tmp < a[end]){a[end + 1] = a[end];}else{break;}--end;}//最后把插入的元素賦值回去a[end + 1] = tmp;}
}//希爾排序測(cè)試
void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){//間隔gap的元素進(jìn)行排序gap = gap / 3 + 1;//本質(zhì)上是插入排序for (int i = 0; i < n - gap; ++i){int end = i;int tmp = a[end + gap];//一個(gè)元素進(jìn)行插入while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end = end - gap;}else{break;}}//最后把插入的元素賦值回去a[end + gap] = tmp;}}
}//void ShellSort(int* a, int n)
//{/*int gap = 3;for (int j = 0; j < gap; j++){for (int i = j; i < n - gap; i += gap){int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}	*///選擇排序測(cè)試
void SelectSort(int* a, int n)
{//初始化第一個(gè)元素 和 最后一個(gè)元素int begin = 0;int end = n - 1;while (begin < end){//選出最大值和最小值int mini = begin, maxi = begin;for (int i = begin + 1; i <= end; i++){if (a[i] > a[maxi]){maxi = i;}if (a[i] < a[mini]){mini = i;}}//最小值和最初的元素交換Swap(&a[begin], &a[mini]);//如果max被換走就需要重新賦值if (maxi == begin){maxi = mini;}//最大值和最末的元素交換Swap(&a[end], &a[maxi]);++begin;--end;}
}//堆排序測(cè)試
//實(shí)現(xiàn)向下調(diào)整建大堆
void AdjustDown(int* a, int n, int parent)
{//孩子和父親的關(guān)系 int child = parent * 2 + 1;while (child < n){//找出小的那個(gè)孩子if (child + 1 < n && a[child + 1] < a[child]){++child;}//實(shí)現(xiàn)向下調(diào)整元素if (a[child] < a[parent]){//元素交換Swap(&a[child], &a[parent]);// 繼續(xù)往下調(diào)整parent = child;child = parent * 2 + 1;}else{break;}}
}//堆排序測(cè)試
void HeapSort(int* a, int n)
{//向下調(diào)整建堆for (int i = (n - 1 - 1) / 2; i >= 0; i--){//實(shí)現(xiàn)向下調(diào)整建大堆AdjustDown(a, n, i);}int end = n - 1;while (end > 0){//元素交換Swap(&a[0], &a[end]);//實(shí)現(xiàn)向下調(diào)整建大堆AdjustDown(a, end, 0);--end;}
}//三數(shù)取中 (找出中間值)
int GetMidi(int* a, int left, int right)
{//中間值int mid = (left + right) / 2;//三個(gè)數(shù)比較找出中間值if (a[left] < a[mid]){if (a[mid] < a[right]){return mid;}else if (a[left] > a[right]){return left;}else{return right;}}else{if (a[mid] > a[right]){return mid;}else if (a[left] < a[right]){return left;}else{return right;}}
}// 右邊找小,左邊找大,交換,把左邊的值跟a[keyi]交換
int PartSort1(int* a, int left, int right)
{//找中間值(相對(duì))int midi = GetMidi(a, left, right);//把最左邊(相對(duì))跟中間值(相對(duì))換Swap(&a[left], &a[midi]);//定位最左邊(相對(duì))int keyi = left;while (left < right){//找小while (left < right && a[right] >= a[keyi]){--right;}//找大while (left < right && a[left] <= a[keyi]){++left;}//左右交換Swap(&a[left], &a[right]);}//此時(shí)左邊走到中間了,開始交換Swap(&a[keyi], &a[left]);//返回return left;
};//挖坑法
int PartSort2(int* a, int left, int right)
{//找中間值(相對(duì))int midi = GetMidi(a, left, right);//把最左邊(相對(duì))跟中間值(相對(duì))換Swap(&a[left], &a[midi]);//定位最左邊(相對(duì))int key = a[left];//保存key值以后,左邊形成第一個(gè)坑int hole = left;while (left < right){//右邊先走,找小,填到左邊的坑,右邊形成新的坑位while (left < right && a[right] >= key){--right;}a[hole] = a[right];hole = right;//左邊再走,找大,填到右邊的坑,左邊形成新的坑位while (left < right && a[left] <= key){++left;}a[hole] = a[left];hole = left;}a[hole] = key;return hole;
}//前后指針
int PartSort3(int* a, int left, int right)
{//找中間值(相對(duì))int midi = GetMidi(a, left, right);//把最左邊(相對(duì))跟中間值(相對(duì))換Swap(&a[left], &a[midi]);//定義指針開頭int prev = left;//定義指針開頭后一個(gè)int cur = prev + 1;int keyi = left;while (cur <= right){if (a[cur] < a[keyi] && ++prev != cur){Swap(&a[prev], &a[cur]);}++cur;}//交換Swap(&a[prev], &a[keyi]);return prev;
}//快排測(cè)試一
void QuickSort1(int* a, int begin, int end)
{if (begin >= end)return;//小區(qū)間優(yōu)化,小區(qū)間不再遞歸分割排序,降低遞歸次數(shù)//當(dāng)元素小于10時(shí),采用插入排序if ((end - begin + 1) > 10){//找值int keyi = PartSort3(a, begin, end);// [begin, keyi-1] keyi [keyi+1, end]QuickSort1(a, begin, keyi - 1);QuickSort1(a, keyi + 1, end);}else{//插入排序InsertSort(a + begin, end - begin + 1);}
}//快排測(cè)試二
void QuickSort2(int* a, int begin, int end)
{if (begin >= end)return;//調(diào)用int keyi = PartSort3(a, begin, end);//[begin, keyi-1] keyi [keyi+1, end]QuickSort2(a, begin, keyi - 1);QuickSort2(a, keyi + 1, end);
}//快排非遞歸(采用棧的形式)(先進(jìn)后出)
void QuickSortNonR(int* a, int begin, int end)
{//定義ST st;//初始化STInit(&st);//添加元素STPush(&st, end);STPush(&st, begin);while (!STEmpty(&st)){//剝離元素  讓left取先入但是后出的元素(區(qū)間的左邊)int left = STTop(&st);STPop(&st);//讓right取棧頂元素(是我們后入的區(qū)間的右邊)int right = STTop(&st);STPop(&st);// 右邊找小,左邊找大,交換,把左邊的值跟a[keyi]交換int keyi = PartSort1(a, left, right);//分割成段 // [lefy,keyi-1] keyi [keyi+1, right]if (keyi + 1 < right){//添加元素STPush(&st, right);STPush(&st, keyi + 1);}if (left < keyi - 1){//添加元素STPush(&st, keyi - 1);STPush(&st, left);}}//銷毀STDestroy(&st);
}void _MergeSort(int* a, int* tmp, int begin, int end)
{//尾小于頭時(shí)if (end <= begin)return;//開始分割int mid = (end + begin) / 2;// [begin, mid][mid+1, end]_MergeSort(a, tmp, begin, mid);_MergeSort(a, tmp, mid + 1, end);//歸并到tmp數(shù)據(jù)組,再拷貝回去//a->[begin, mid][mid+1, end]->tmpint begin1 = begin, end1 = mid;int begin2 = mid + 1, end2 = end;int index = begin;//開始拷貝while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[index++] = a[begin1++];}else{tmp[index++] = a[begin2++];}}//當(dāng)?shù)谝欢卧貨]有完全拷貝完就把剩下的拷貝進(jìn)去while (begin1 <= end1){tmp[index++] = a[begin1++];}//當(dāng)?shù)诙卧貨]有完全拷貝完就把剩下的拷貝進(jìn)去while (begin2 <= end2){tmp[index++] = a[begin2++];}//拷貝回原數(shù)組memcpy(a + begin, tmp + begin, (end - begin + 1) * sizeof(int));
}//歸并排序(分路并歸)
void MergeSort(int* a, int n)
{//開辟空間int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");return;}//調(diào)用_MergeSort(a, tmp, 0, n - 1);//釋放內(nèi)存free(tmp);
}//歸并排序(非遞歸)
void MergeSortNonR(int* a, int n)
{//開辟空間int* tmp = (int*)malloc(sizeof(int) * n);//判斷if (tmp == NULL){perror("malloc fail");return;}int gap = 1;while (gap < n){for (int i = 0; i < n; i += 2 * gap){int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;// [begin1,end1] [begin2,end2] 歸并// 如果第二組不存在,這一組不用歸并了if (begin2 >= n){break;}// 如果第二組的右邊界越界,修正一下if (end2 >= n){end2 = n - 1;}//printf("[%d,%d][%d,%d] ", begin1, end1, begin2, end2);int index = i;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[index++] = a[begin1++];}else{tmp[index++] = a[begin2++];}}while (begin1 <= end1){tmp[index++] = a[begin1++];}while (begin2 <= end2){tmp[index++] = a[begin2++];}// 拷貝回原數(shù)組memcpy(a + i, tmp + i, (end2 - i + 1) * sizeof(int));}printf("\n");gap *= 2;}free(tmp);
}//計(jì)數(shù)排序測(cè)試
void CountSort(int* a, int n)
{//找最大值和最小值int min = a[0], max = a[0];for (size_t i = 0; i < n; i++){if (a[i] < min)min = a[i];if (a[i] > max)max = a[i];}//找出區(qū)間int range = max - min + 1;//開辟(區(qū)間)int* count = (int*)malloc(sizeof(int) * range);printf("range:%d\n", range);//判斷if (count == NULL){perror("malloc fail");return;}//計(jì)入數(shù)字的個(gè)數(shù)memset(count, 0, sizeof(int) * range);// 統(tǒng)計(jì)數(shù)據(jù)出現(xiàn)次數(shù)for (int i = 0; i < n; i++){count[a[i] - min]++;}//排序int j = 0;for (int i = 0; i < range; i++){while (count[i]--){a[j++] = i + min;}}
}

🌟結(jié)束語

? ? ? ?今天內(nèi)容就到這里啦,時(shí)間過得很快,大家沉下心來好好學(xué)習(xí),會(huì)有一定的收獲的,大家多多堅(jiān)持,嘻嘻,成功路上注定孤獨(dú),因?yàn)閳?jiān)持的人不多。那請(qǐng)大家舉起自己的小說手給博主一鍵三連,有你們的支持是我最大的動(dòng)力💞💞💞,回見。

http://www.risenshineclean.com/news/63931.html

相關(guān)文章:

  • 山東德州如何網(wǎng)站建設(shè)教程qq群排名優(yōu)化
  • 廣州做和改版網(wǎng)站的公司網(wǎng)上賣貨的平臺(tái)有哪些
  • 好用的wordpress代碼編輯器河南seo外包
  • phpcms 做購物網(wǎng)站谷歌seo優(yōu)化公司
  • html京東頁面制作深圳seo優(yōu)化排名優(yōu)化
  • 貴陽 網(wǎng)站建設(shè)推廣百度百科
  • 廊坊哪些公司做網(wǎng)站百度商家版下載
  • 一線城市網(wǎng)站建設(shè)費(fèi)用高長(zhǎng)春網(wǎng)站seo公司
  • 怎么快速開發(fā)一個(gè)網(wǎng)站典型的網(wǎng)絡(luò)營(yíng)銷案例
  • 教做衣服的網(wǎng)站有哪些網(wǎng)頁搜索
  • 越城網(wǎng)站建設(shè)公司陜西網(wǎng)站建設(shè)網(wǎng)絡(luò)公司
  • 煙臺(tái)專業(yè)做網(wǎng)站公司有哪些微博推廣技巧
  • 純文本網(wǎng)站連接北京建站公司
  • 禁用wordpress插件更新網(wǎng)站關(guān)鍵詞優(yōu)化公司
  • 自個(gè)做網(wǎng)站教程濰坊快速網(wǎng)站排名
  • 上海專業(yè)網(wǎng)站推廣公司長(zhǎng)春網(wǎng)站優(yōu)化咨詢
  • 滄州網(wǎng)站建設(shè)制作設(shè)計(jì)優(yōu)化百度瀏覽器電腦版
  • 網(wǎng)站設(shè)計(jì)建設(shè)公司廣州seo優(yōu)化排名公司
  • 在線做漢字頭像的網(wǎng)站合肥瑤海區(qū)
  • 風(fēng)水網(wǎng)站開發(fā)登錄注冊(cè)入口
  • 網(wǎng)站換空間 百度快照倒退一年多 怎么回事百度搜索指數(shù)排行榜
  • 做網(wǎng)站資源知乎seo關(guān)鍵詞挖掘工具
  • 網(wǎng)站開發(fā)主管待遇優(yōu)化大師安卓版
  • 建正建設(shè)官方網(wǎng)站友情鏈接有什么用
  • 湖南做網(wǎng)站問磐石網(wǎng)絡(luò)專業(yè)鞏義網(wǎng)絡(luò)推廣外包
  • 宿州做企業(yè)網(wǎng)站學(xué)生制作個(gè)人網(wǎng)站
  • 重慶網(wǎng)絡(luò)公司網(wǎng)站建設(shè)查詢網(wǎng) 域名查詢
  • 成都建筑設(shè)計(jì)公司排名前十雞西seo
  • 做視頻網(wǎng)站的條件抖音seo推廣
  • 網(wǎng)站建設(shè) 軟件開發(fā)站長(zhǎng)之家統(tǒng)計(jì)