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

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

做網(wǎng)站需要用到那些軟件中國(guó)優(yōu)秀網(wǎng)頁(yè)設(shè)計(jì)案例

做網(wǎng)站需要用到那些軟件,中國(guó)優(yōu)秀網(wǎng)頁(yè)設(shè)計(jì)案例,網(wǎng)站建設(shè)目標(biāo)責(zé)任,怎么制作海報(bào)圖片目錄 基本排序 一.冒泡排序 二.選擇排序 三.插入排序 進(jìn)階排序(遞歸實(shí)現(xiàn)) 一.快排hoare排序 1.單趟排序 快排步湊 快排的優(yōu)化 (1)三數(shù)取中 (2)小區(qū)間優(yōu)化 二.前后指針?lè)?遞歸實(shí)現(xiàn)) 三.快排的非…

目錄

基本排序

一.冒泡排序

二.選擇排序

三.插入排序

進(jìn)階排序(遞歸實(shí)現(xiàn))

一.快排hoare排序

1.單趟排序

快排步湊

快排的優(yōu)化

(1)三數(shù)取中

(2)小區(qū)間優(yōu)化

二.前后指針?lè)?遞歸實(shí)現(xiàn))

三.快排的非遞歸實(shí)現(xiàn)(前后指針?lè)ǖ姆沁f歸)

快排的挖坑法的實(shí)現(xiàn)

二.堆排序

1.建堆的選擇

2.堆排序的實(shí)現(xiàn)

二希爾排序

三.歸并排序(遞歸實(shí)現(xiàn)與非遞歸的實(shí)現(xiàn))

歸并排序(非遞歸實(shí)現(xiàn))

四.非比較排序(計(jì)數(shù)排序)

計(jì)數(shù)排序的缺陷

五.排序總結(jié)

穩(wěn)定性的概念

六,排序的選擇題練習(xí)與鞏固


歡迎各位大佬的關(guān)顧,能給個(gè)贊就好了QWQ,由于篇幅很大,可以根據(jù)目錄跳轉(zhuǎn)你想看的排序哦!!

基本排序

一.冒泡排序

冒泡排序即,每次相鄰比較排序,每次將最小或最大固定在數(shù)組最后

void BubbleSort(int* arr, int len)
{for (int i = 0; i < len; i++){int flag = 1;for (int j = 0; j < len - i-1; j++){if (arr[j] > arr[j+1]){flag = 0;Swap(&arr[j + 1],&arr[j]);}}if (flag)break;}
}

二.選擇排序

很明顯選擇排序就是去找最小或者最大的下標(biāo)然后賦值給原始位置,代碼實(shí)現(xiàn)如下

void SelectSort(int* arr, int len)
{for (int i = 0; i < len-1; i++){int min = i;for (int j = i + 1; j < len; j++){if (arr[j] < arr[min])min = j;}Swap(&arr[min], &arr[i]);}
}

但是這種選擇排序也太low了讓我們來(lái)實(shí)現(xiàn)一個(gè)Plus版本,一次循環(huán)找到最大與最小

int SelectSortPlus(int* arr, int len)
{int begin = 0;int end = len - 1;for (int i = begin; i <=end-1; i++){int min = begin;int max = begin;for (int j = i+1; j <= end; j++){if (arr[j] < arr[min])min = j;if (arr[j] > arr[max])max = j;}Swap(&arr[begin], &arr[min]);if (begin == max)//注意這里當(dāng)begin與max的下標(biāo)一樣的時(shí)候,會(huì)被先換導(dǎo)致bugmax = min;Swap(&arr[end], &arr[max]);begin++;end--;}
}

三.插入排序

看動(dòng)圖可以很容易的理解插入排序就是將已排好的序的后一個(gè)與前面的進(jìn)行比較,比它大或小的往后移動(dòng)

void InsertSort(int* a, int len)
{for (int i = 0; i < len - 1; i++){int end = i;int temp = a[end + 1];while (end >= 0){if (temp < a[end]){a[end + 1] = a[end];end--;}else{break;}a[end + 1] = temp;}}
}

進(jìn)階排序(遞歸實(shí)現(xiàn))

一.快排hoare排序

快排有著多種實(shí)現(xiàn)方式我們下面這個(gè)是hoare(創(chuàng)始人)的排序方式

快速排序是一種高效的排序現(xiàn)在來(lái)讓我們來(lái)實(shí)現(xiàn)一下

1.單趟排序

想要寫出一個(gè)排序首先我們要去理解這個(gè)排序的單趟 單趟如圖所示

如圖我們可以發(fā)現(xiàn)它的步驟如下

快排步湊

(1)選出基準(zhǔn)值key 為 left

(2)右邊r先走找到比key小的停止

(3)右邊r找到的情況下,左邊L再開始找比key大的值

(3)左邊L找到的情況下停止,將這兩個(gè)值進(jìn)行交換

循環(huán)上面的操作

直到他們相遇,將相遇的位置的值與key值交換

這就是快排的單趟排序,接下來(lái)讓我們來(lái)實(shí)現(xiàn)一下

void QuickSort2(int* arr, int left, int right)
{int key = left;int begin = left;int end = right;while (begin < end){//先從右邊開始找小 //注意結(jié)束條件 begin一定<endwhile (begin < end && arr[end] >= arr[key]){--end;}//再?gòu)淖筮呎掖體hile (begin < end && arr[begin] <= arr[key]){++begin;}//兩邊都找到了之后進(jìn)行交換Swap(&arr[begin], &arr[end]);}//最后相遇再與key交換Swap(&arr[begin], &arr[key]);}
}

想必這里大家會(huì)有一些疑問(wèn),為什么

1.為什么要右邊先走,左邊先走可以嗎

2.為什么最后交換key的位置就固定了

3.要怎么樣才能實(shí)現(xiàn)排序的效果

循環(huán)的實(shí)現(xiàn),既然單趟可以固定住key值在整個(gè)數(shù)里面的想要排序的位置,那我們可不可以將這個(gè)數(shù)組進(jìn)行分割[left~key-1]key[key+1~right]

運(yùn)用遞歸來(lái)實(shí)現(xiàn)呢

答案是肯定的

只需要每次遞歸進(jìn)行分割,固定n的值的位置,如下圖所示

如圖所示很明顯當(dāng)我們進(jìn)行遞歸的時(shí)候每次的位置都將被固定,從而實(shí)現(xiàn)了排序

代碼如下

void QuickSort2(int* arr, int left, int right)
{//返回條件if (left >= right)return;int key = left;int begin = left;int end = right;while (begin < end){//先從右邊開始找小 //注意結(jié)束條件 begin一定<endwhile (begin < end && arr[end] >= arr[key]){--end;}//再?gòu)淖筮呎掖體hile (begin < end && arr[begin] <= arr[key]){++begin;}//兩邊都找到了之后進(jìn)行交換Swap(&arr[begin], &arr[end]);}//最后相遇再與key交換Swap(&arr[begin], &arr[key]);//遞歸排序分割成兩份//[left~key-1] key [key+1~right]最后相遇的指針也是一樣的QuickSort2(arr, left, end - 1);QuickSort2(arr, end + 1, right);
}

到這里我們也就完成了閹割版的快排,但是距離真正的快排還是有些距離

現(xiàn)在的這個(gè)排序有著致命的缺陷如果說(shuō)在數(shù)組已經(jīng)是有些的情況下,快排的將會(huì)退化,就像是二叉樹退化為單叉樹一樣,如果我們這時(shí)還去遞歸那就會(huì)有爆棧(棧溢出)的風(fēng)險(xiǎn),原因很簡(jiǎn)單

如下圖所示

如果是有序的情況下,那么遞歸的深度將會(huì)變成n如果數(shù)據(jù)量太大將會(huì)爆棧

所以接下來(lái)要去實(shí)現(xiàn)一下三數(shù)取中,小區(qū)間優(yōu)化來(lái)對(duì)遞歸快排進(jìn)行優(yōu)化

快排的優(yōu)化

(1)三數(shù)取中

選擇key值進(jìn)行,key值的選擇就是為了避免這種有序情況的出現(xiàn),因?yàn)檫xkey固定key的位值,我們只需要找到中間的那個(gè)數(shù)進(jìn)行固定區(qū)間遞歸的高度將會(huì)變?yōu)?img referrerpolicy="no-referrer" alt="\log n" class="mathcode" src="https://latex.csdn.net/eq?%5Clog%20n" />解決了爆棧的風(fēng)險(xiǎn)

int GetMid2(int* arr, int left, int right)
{//三個(gè)數(shù)進(jìn)行比較 分類討論int mid = (left + right) / 2;if (arr[left] < arr[mid]){if (arr[mid] < arr[right]){return mid;}//arr[mid]>arr[right]else if (arr[right] < arr[left]){return left;}else{return right;}}else//arr[left]> arr[mid]{if (arr[mid] > arr[right]){return mid;}//arr[righ]>arr[mid]else if (arr[right]>arr[left]){return left;}else{return right;}}
}
(2)小區(qū)間優(yōu)化

什么是小區(qū)間優(yōu)化?在我們進(jìn)行快排的時(shí)候,如果每次的區(qū)間都能二分的化,這個(gè)遞歸的過(guò)程是可以看出一顆二叉樹,而在滿二叉樹的葉子節(jié)點(diǎn)個(gè)數(shù)為整棵樹的一半,對(duì)于快排來(lái)說(shuō)它的最后一層和倒數(shù)第二層,是不用去排和只排一個(gè)數(shù)的,但是卻還要開辟棧幀,所以我們這里使用小區(qū)間優(yōu)化帶代碼如下直接使用當(dāng)區(qū)間小于10時(shí)進(jìn)行插入排序

//小區(qū)間優(yōu)化 提升效率節(jié)省空間
if ((right - left + 1) < 10)//減少遞歸次數(shù)
{//加上偏移量leftInsertSort(arr+left, right - left + 1);
}
else
{//進(jìn)行遞歸
}

注意事項(xiàng)

二.前后指針?lè)?遞歸實(shí)現(xiàn))

由于hoare版本的有些復(fù)雜要去考慮什么右邊先走之類的,所以又有人想出了更加簡(jiǎn)單跟容易理解的辦法,前后指針?lè)?#xff0c;過(guò)程如圖所示

可以發(fā)現(xiàn)與hoare版本大體一致都是去選擇key與key比較,不同點(diǎn)在于,只有是cur去找比key小的值,當(dāng)找到比key小的值的時(shí)候++prev然后與cur位置的值進(jìn)行交換,最后當(dāng)cur走到最后,prev的值再與key位置的值進(jìn)行交換,比起hoare版本簡(jiǎn)單了許多,接下來(lái)我們來(lái)嘗試實(shí)現(xiàn)一下

void QuickSortByPointer(int* arr, int left, int right)
{if (left >= right)return;//三數(shù)取中int mid = GitMid(arr,left,right);Swap(&arr[mid], &arr[left]);int key = left;int prev = left;int cur = prev+1;//三數(shù)取中if ((right - left + 1) < 10){InsertSort(arr+left, right - left + 1);//加上left}else{while (cur <= right){if (arr[key] > arr[cur]&&++prev != cur)//為什么要寫成這樣?Swap(&arr[prev], &arr[cur]);cur++;}Swap(&arr[prev], &arr[key]);//區(qū)間變?yōu)閇0,prev-1]prev[prev+1,right]QuickSortByPointer(arr, left, prev - 1);//值給錯(cuò)了應(yīng)該是leftQuickSortByPointer(arr, prev + 1, right);}
}

你以為到這里快排就結(jié)束了嘛其實(shí)還是馬達(dá)馬達(dá)得是(遠(yuǎn)遠(yuǎn)沒有結(jié)束),雖然我們加上三數(shù)取中,與小區(qū)間的優(yōu)化但是如果數(shù)據(jù)量過(guò)大還是會(huì)有爆棧的風(fēng)險(xiǎn)(棧的空間比較小),所以我們可以使用數(shù)據(jù)結(jié)構(gòu)的棧來(lái)模擬實(shí)現(xiàn)程序中的壓棧與出棧,(由于是在堆中建立,內(nèi)存巨大,8G的內(nèi)存不可能溢出把!)

三.快排的非遞歸實(shí)現(xiàn)(前后指針?lè)ǖ姆沁f歸)

可以看見我們先是將每次的單次排序進(jìn)行封裝的

我們可以想象一下在程序中棧幀的建立與銷毀的過(guò)程,然后我們也可以自己使用數(shù)據(jù)結(jié)構(gòu)的棧來(lái)實(shí)現(xiàn)

快排其實(shí)是可以看作二叉樹的前序遍歷的,但是棧又是后進(jìn)先出,想要先得到左邊界的值就需要先進(jìn)右邊,想要得到右邊界的值就需要先進(jìn)左邊

void QuickSortNoR(int* arr, int begin, int end)
{Stack st;CreatStack(&st);StackPush(&st, end);StackPush(&st, begin);while (StackGetSize(&st)!=0){int left = StackPop(&st);//我的Pop是即出又返回棧頂元素的因?yàn)楹筮M(jìn)先出想要先得到left進(jìn)右int right = StackPop(&st);//小區(qū)間優(yōu)化if ((right - left + 1) / 2 < 10)InsertSort(arr + left, right - left + 1);else{//開始模擬遞歸int key = PartPointer(arr, left, right);//這個(gè)函數(shù)是每一次的單趟排序if (key + 1 < right)//進(jìn)行遞歸由于后進(jìn)先出 先進(jìn)右區(qū)間{StackPush(&st, right);//后進(jìn)先出由于我們的右區(qū)間是后出 所以先進(jìn)StackPush(&st, key + 1);}if (left < key - 1)//注意錯(cuò)誤之處區(qū)間不要寫錯(cuò)了{(lán)StackPush(&st, key - 1);StackPush(&st, left);}}}
}
int PartPointer(int* arr, int left, int right)
{//三數(shù)取中int mid = GitMid(arr, left, right);Swap(&arr[mid], &arr[left]);int key = left;int prev = left;int cur = prev + 1;while (cur <= right){if (arr[key] > arr[cur])Swap(&arr[++prev], &arr[cur]);cur++;}Swap(&arr[prev], &arr[key]);return prev;//返回key的位置 prev就是key中間值 然后進(jìn)行區(qū)間的分割同上
}

快排的挖坑法的實(shí)現(xiàn)

(由于篇幅有限這里不在過(guò)多講解)

int PartSort2(int* a, int begin, int end)
{//begin是坑int key = a[begin];while (begin < end){while (begin < end && a[end] >= key)--end;// end給begin這個(gè)坑,end就變成了新的坑。a[begin] = a[end];while (begin < end && a[begin] <= key)++begin;// end給begin這個(gè)坑,begin就變成了新的坑。a[end] = a[begin];}a[begin] = key;return begin;
}

二.堆排序

學(xué)習(xí)完了快排,接下來(lái)學(xué)習(xí)堆,首先我們要知道堆的概念,

堆在邏輯結(jié)構(gòu)上是一個(gè)完全二叉樹,在物理結(jié)構(gòu)上是一個(gè)數(shù)組,

想要找到兒子節(jié)點(diǎn)就是(parent-1)/2

想要找到父親節(jié)點(diǎn)就是child*2+1

如果想要深入理解堆可以看我的這一篇博客堆的實(shí)現(xiàn)與堆排序(純C語(yǔ)言版)-CSDN博客

1.建堆的選擇


當(dāng)我們想要進(jìn)行排序的時(shí)候首先要模擬堆的插入過(guò)程進(jìn)行建堆,這里有個(gè)問(wèn)題如果想要降序排列那么應(yīng)該建小堆還是大堆呢,在我剛開學(xué)學(xué)習(xí)的時(shí)候想的是肯定是建大堆啊因?yàn)檫@樣根節(jié)點(diǎn)就是最大的然后再出堆,其實(shí)這樣想就錯(cuò)了,這樣只是出堆降序,不是數(shù)組本身進(jìn)行了降序排列,所以降序是其實(shí)是建小堆,升序其實(shí)是建大堆.那又是怎么實(shí)現(xiàn)的呢

2.堆排序的實(shí)現(xiàn)

在進(jìn)行建堆之后(小堆降序來(lái)舉例),我們就只需要模擬出堆,這時(shí)每次最小的數(shù)就被放在了最后的位置,最后完成排序后,整個(gè)數(shù)據(jù)就有序,如圖當(dāng)我們想要升序排列的時(shí)候建大堆

下面是完整的代碼

void HeapSort(int* a, int max)//max為最大個(gè)數(shù)
{//建隊(duì)for (int i = 0; i <max; i++){AdjustUp(a, i);//模擬插入建小堆}//排序int end = max - 1;//找到最后一個(gè)元素的下標(biāo)進(jìn)行交換while (end>0){Swap(&a[0], &a[end]);AdjustDown(a, 0, end);--end;//最后的有序不在排序}
}

其實(shí)第一步建堆算法還沒有做到極致,還可以倒著向下調(diào)整,這樣的時(shí)間復(fù)雜度更低

//建堆法2
for (int i = (max - 1 - 1) / 2; i >= 0; i--)//找到第一個(gè)非葉子結(jié)點(diǎn) 倒著進(jìn)行想下調(diào)整
{AdjustDown(a, i, max-1);
}

二希爾排序

希爾排序是一個(gè)時(shí)間復(fù)雜度大約為O(N^{1.3})的排序算法,

它其實(shí)就是運(yùn)用的插入排序

它的排序可以分為2步

1.預(yù)排序分為gap組進(jìn)行

2.當(dāng)gap=1時(shí)即為選擇排序

希爾排序的實(shí)質(zhì)就是如果在排一個(gè)升序的數(shù)組,如果大的在很前面,每次就是一步一步的移動(dòng),而當(dāng)有了gap之后,移動(dòng)的步長(zhǎng)將會(huì)變大,大的數(shù)將會(huì)以更快的速度移到后面

我們將插入排序來(lái)進(jìn)行一下比較

void InsertSort(int* a, int len)
{for (int i = 0; i < len - 1; i++){int end = i;int temp = a[end + 1];while (end >= 0){if (temp < a[end]){a[end + 1] = a[end];end--;}else{break;}a[end + 1] = temp;}}
}

可以看見在進(jìn)行插入排序的時(shí)候,此時(shí)的步長(zhǎng)gap為1,每次只會(huì)往后面進(jìn)行一步,所以我們這里只需去改變想要排序的步長(zhǎng)即可

下面是代碼的實(shí)現(xiàn)

void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){// +1保證最后一個(gè)gap一定是1// gap > 1時(shí)是預(yù)排序// gap == 1時(shí)是插入排序gap = gap / 3 + 1;for (size_t i = 0; i < n - gap; ++i){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;}}
}

我們可以發(fā)現(xiàn),我們上面是一組一組來(lái)排序

也可以多組并走都是一樣的

三.歸并排序(遞歸實(shí)現(xiàn)與非遞歸的實(shí)現(xiàn))

歸并排序的思想就是分治法(分而治之),如圖所示

首先我們要?jiǎng)?chuàng)建一個(gè)臨時(shí)的數(shù)組

運(yùn)用了二叉樹的后序遍歷的思維,先將數(shù)組拆分,拆分后的數(shù)組又來(lái)進(jìn)行合并,在進(jìn)行合并的兩個(gè)數(shù)組分別有序,只需要比較一次將小的放入到臨時(shí)的數(shù)組當(dāng)中,放完成后再拷貝回去完成排序

重點(diǎn)就是在進(jìn)行合并的時(shí)候兩個(gè)數(shù)組是有序的!

讓我們來(lái)實(shí)現(xiàn)一下

l

999000lkklkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklkkkkkkkkkkkkkkkkkkkkkkkk? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 222

代碼如下

void MergeSort(int* arr, int len)
{int* temp = (int*)malloc(sizeof(int) * len);_MergeSort(arr,temp,0,len-1);free(temp);temp = NULL;
}
void _MergeSort(int* arr, int* temp, int left, int right)
{//返回條件if (left >= right)return;//進(jìn)行遞歸//分成[left mid][mid+1,right]不能寫成[left mid-1][mid,right]分區(qū)間的時(shí)候?qū)?huì)出現(xiàn)問(wèn)題//單趟排序 將左右區(qū)間看作有序數(shù)組 進(jìn)行比較放入temp數(shù)組中int mid = (left + right) / 2;//[left mid][mid+1,right]int begin1 = left;int begin2 = mid + 1;int end1 = mid;int end2 = right;_MergeSort(arr, temp, begin1, end1);//左區(qū)間_MergeSort(arr, temp, begin2, end2);//右區(qū)間int i = 0;while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] < arr[begin2]){temp[i++] = arr[begin1++];}else//直接else{temp[i++] = arr[begin2++];}}//循環(huán)結(jié)束后還有元素全部放后面while (begin1 <= end1){temp[i++] = arr[begin1++];}//循環(huán)結(jié)束后還有元素全部放后面while (begin2 <= end2){temp[i++] = arr[begin2++];}//進(jìn)行拷貝回去memcpy(arr+left, temp, i*sizeof(int));
}

歸并排序(非遞歸實(shí)現(xiàn))

想要實(shí)現(xiàn)歸并的非遞歸,我們是否還需要像快排一樣去模擬棧呢,當(dāng)我們?nèi)∧M棧的時(shí)候由于歸并的遞歸是一個(gè)后序遍歷,而棧無(wú)法去記錄值,所以使用棧就要用兩個(gè),較為麻煩,使用我們直接用下面這種思想

由上面遞歸實(shí)現(xiàn)的歸并排序很容易想,其中的gap為每個(gè)小組的個(gè)數(shù)

但是好像還有一個(gè)問(wèn)題,數(shù)組越界的問(wèn)題

當(dāng)我們使用了上面的數(shù)據(jù)進(jìn)行分組的時(shí)候,所以我們要進(jìn)行區(qū)間的判斷

加入

if (begin2 > len - 1)//begin2已經(jīng)越界,說(shuō)明只有一組了沒必要再排
{break;
}
if (end2 > len - 1)//end2越界了進(jìn)行修正即可
{end2 = len - 1;
}

完整的代碼如下

void MergeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");return;}// gap每組歸并數(shù)據(jù)的數(shù)據(jù)個(gè)數(shù)int gap = 1;while (gap < n){for (int i = 0; i < n; i += 2 * gap){// [begin1, end1][begin2, end2]int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;//printf("[%d,%d][%d,%d] ", begin1, end1, begin2, end2);// 第二組都越界不存在,這一組就不需要?dú)w并if (begin2 >= n)break;// 第二的組begin2沒越界,end2越界了,需要修正一下,繼續(xù)歸并if (end2 >= n)end2 = n - 1;int j = i;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] <= a[begin2])//注意等號(hào)這樣才會(huì)穩(wěn)定{tmp[j++] = a[begin1++];}else{tmp[j++] = a[begin2++];}	}while (begin1 <= end1){tmp[j++] = a[begin1++];}while (begin2 <= end2){tmp[j++] = a[begin2++];}memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));}//memcpy(a , tmp , sizeof(int) *n );//printf("\n");gap *= 2;}free(tmp);tmp = NULL;
}

四.非比較排序(計(jì)數(shù)排序)

接下來(lái)讓我們來(lái)學(xué)習(xí)最后一個(gè)排序,這個(gè)排序的特點(diǎn)是非比較的排序,通過(guò)建立一個(gè)數(shù)組來(lái)存放數(shù)組中每個(gè)數(shù)出現(xiàn)的次數(shù),來(lái)實(shí)現(xiàn)排序

首先來(lái)思考我們想要開辟的數(shù)組的大小,那是否就是原數(shù)組的長(zhǎng)度大小呢,因?yàn)橐鎯?chǔ)每個(gè)元素出現(xiàn)的次數(shù),那么我們開辟數(shù)組必須是連續(xù)的,在開辟數(shù)組長(zhǎng)度大小的時(shí)候有個(gè)細(xì)節(jié),如果每次都從0開始建立計(jì)數(shù)數(shù)組,那如果遇到一個(gè)最小值為99,最大值為110的數(shù)組,那我們還是需要從0開始建立數(shù)組,前面明明一個(gè)數(shù)都沒有出現(xiàn)但是我們卻還是去開辟的數(shù)組,浪費(fèi)了很多的空間,所以我們只需要去找到最大與最小的那個(gè)值,計(jì)算出rang=最大值-最小值+1(注意要加一),所以計(jì)數(shù)數(shù)數(shù)組的大小為rang,那我們?cè)谶M(jìn)行計(jì)數(shù)的時(shí)候就只需要進(jìn)行-min就可以了

然后是進(jìn)行排序,當(dāng)計(jì)數(shù)數(shù)組里不為0說(shuō)明當(dāng)前位置有映射值進(jìn)行自減1.加上min賦值給原數(shù)組實(shí)現(xiàn)排序效果

代碼如下

void CountSort2(int* arr, int len)
{//找到原數(shù)組的最大與最小值int min = arr[0];int max = arr[len - 1];for (int i = 0; i < len; i++){if (arr[i] < min){min = arr[i];}if (arr[i] > max){max = arr[i];}}int rang = max - min + 1;//開辟計(jì)數(shù)數(shù)組 注意這里要初始化開辟的計(jì)數(shù)數(shù)組 這樣奇計(jì)數(shù)數(shù)組才全是0int* count = (int*)calloc(rang,sizeof(int) * rang);//進(jìn)行計(jì)數(shù)for (int i = 0; i < len; i++){count[arr[i] - min]++;}//進(jìn)行排序int j = 0;for (int i = 0; i < rang; i++){while (count[i]--)//當(dāng)count[i]的元素不為0的時(shí)候說(shuō)明當(dāng)前映射有值{arr[j++] = i + min;}}}

計(jì)數(shù)排序的缺陷

既然計(jì)數(shù)排序是一種映射的方法,所以是只能對(duì)整數(shù)進(jìn)行排列的

五.排序總結(jié)

學(xué)習(xí)完了上面的排序現(xiàn)在我們來(lái)進(jìn)行一下總結(jié),

排序? ? ? ? ?平局時(shí)間復(fù)雜度? ? 最壞時(shí)間復(fù)雜度 最好時(shí)間復(fù)雜度 穩(wěn)定性

冒泡排序? ? ? ? ? ? ? ? O(N^{2})? ????????????????O(N^{2})? ? ? ?O(N^{})? ? ? ?? ? ? ? ?穩(wěn)定?

選擇排序????????????????O(N^{2})?????????????????O(N^{2})????????O(N^{2})?? ? ? ? ? ? ? 不穩(wěn)定

插入排序? ? ? ? ? ? ? ? O(N^{2})?????????????????O(N^{2})????????O(N^{})? ? ? ? ? ? ? ??穩(wěn)定

希爾排序? ? ? ? ? ? ? ? O(N^{1.3})? ? ? ? ? ? ??O(N^{2})????????O(N^{1.3})? ? ? ? ? ? ?不穩(wěn)定

堆排序? ? ? ? ? ? ? ? ? ? O(N*\log N)??O(N*\log N)O(N*\log N) 不穩(wěn)定

快速排序????????????????O(N*\log N)? ?O(N^{2})?????????O(N*\log N)? ? ? ?不穩(wěn)定

歸并排序?????????????????O(N*\log N)? ??O(N*\log N)???O(N*\log N) 穩(wěn)定

?

穩(wěn)定性的概念

上表的穩(wěn)定性是什么意思?其實(shí)就是相同數(shù)據(jù)的前后位置是否發(fā)生改變,如下面紅色5與藍(lán)色5當(dāng)排序完成后紅色5還在藍(lán)色5前面就是穩(wěn)定的

六,排序的選擇題練習(xí)與鞏固

學(xué)完上面的知識(shí),不來(lái)兩道題檢測(cè)一下是不知道自己真正掌握了沒有的下面讓我們來(lái)做幾道題加深一下印象。

1.用某種排序方法對(duì)關(guān)鍵字序列 25 84 21 47 15 27 68 35 20 進(jìn)行排序,序列的變化情況采樣如下:

20 15 21 25 47 27 68 35 84

15 20 21 25 35 27 47 68 84

15 20 21 25 27 35 47 68 84

請(qǐng)問(wèn)采用的是以下哪種排序算法( )

A.選擇排序

B.希爾排序

C.歸并排序

D.快速排序

答案:D

解析:

此題中的排序是快排二分排序的思想,第一趟的基準(zhǔn)值是25,第二趟的基準(zhǔn)值分別是20,47,第三趟的基準(zhǔn)值分別是15,21,35,68

?

2.下面的排序算法中,初始數(shù)據(jù)集的排列順序?qū)λ惴ǖ男阅軣o(wú)影響的有( )

① 快速排序

② 希爾排序

③ 插入排序

④ 堆排序

⑤ 歸并排序

⑥ 選擇排序

A.①④⑤

B.④⑤⑥

C.②③⑥

D.②③⑤⑥

答案:B

解析:

快排: 初始順序影響較大,有序是,性能最差

插入: 接近有序,性能最好

希爾:希爾是對(duì)插入排序的優(yōu)化,這種優(yōu)化是在無(wú)序的序列中才有明顯的效果,如果序列接近有序,反而是插入最優(yōu)。

堆排,歸并,選擇對(duì)初始順序不敏感

3.下列排序方法中,每一趟排序結(jié)束時(shí)都至少能夠確定一個(gè)元素最終位置的方法是( )

① 選擇排序

② 歸并排序

③ 快速排序

④ 堆排序

A.①④

B.①②④

C.①③④

D.①②③④

?

答案:C

解析:

選擇排序每次選一個(gè)最值,放在最終的位置

快速排序每次基準(zhǔn)值的位置也可以確定

堆排序每次堆頂元素的位置也可以確定

所以這三種方法都可以每次至少確定一個(gè)元素的位置

而歸并排序每次都需要對(duì)n個(gè)元素重新確定位置,所以不能保證每次都能確定一個(gè)元素位置,有可能每次排序所有元素的位置都為發(fā)生變化。

?

4.現(xiàn)有數(shù)字序列 5 11 7 2 3 17,目前要通過(guò)堆排序進(jìn)行降序排序,那么由該序列建立的初始堆應(yīng)為( )

A.2 3 7 11 5 17

B.17 11 7 2 3 5

C.17 11 7 5 3 2

D.2 3 5 7 11 17

答案:A

解析:

要降序排列,所以要建小堆,每次把堆頂元素放在當(dāng)前堆的最后一個(gè)位置

建堆要進(jìn)行向下調(diào)整算法(從最后一個(gè)非葉子節(jié)點(diǎn)開始進(jìn)行向下調(diào)整算法,直到根元素)

5

11 7

2 3 17

5

2 7

11 3 17

2

3 7

11 5 17

所以初始堆序列為: 2 3 7 11 5 17

5.下列選項(xiàng)中,不可能是快速排序第2趟排序后的結(jié)果的是( )

A.2 3 5 4 6 7 9

B.2 7 5 6 4 3 9

C.3 2 5 4 7 6 9

D.4 2 3 5 7 6 9

?

答案:C

解析:

這里說(shuō)的是快排的第二趟,即在第一趟快排的結(jié)果的基礎(chǔ)上進(jìn)行的,如果已經(jīng)經(jīng)過(guò)了一趟排序,則會(huì)通過(guò)第一趟選擇的基準(zhǔn)值劃分兩個(gè)子區(qū)間,每個(gè)子區(qū)間也會(huì)以區(qū)間內(nèi)選擇的基準(zhǔn)值劃分成兩部分。

A: 第一趟的基準(zhǔn)值可以為2, 第二趟的基準(zhǔn)值可以為3

B: 第一趟的基準(zhǔn)值可以為2, 第二趟的基準(zhǔn)值可以為9

C: 第一趟的基準(zhǔn)值只能是9,但是第二趟的基準(zhǔn)值就找不出來(lái),沒有符合要求的值作為基準(zhǔn)值,所以不可能是一個(gè)中間結(jié)果。

D: 第一趟的基準(zhǔn)值可以為9, 第二趟的基準(zhǔn)值可以為5

由于個(gè)人精力有限,如有錯(cuò)誤歡迎指出!!!

小bit!!!

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

相關(guān)文章:

  • 網(wǎng)頁(yè)制作培訓(xùn)學(xué)費(fèi)seo人員工作內(nèi)容
  • 免費(fèi)查企業(yè)最好的網(wǎng)站杭州seo博客
  • 陜西印象盒子seo整站優(yōu)化吧
  • php做網(wǎng)站開源項(xiàng)目東莞網(wǎng)站設(shè)計(jì)
  • 高中學(xué)校網(wǎng)站模板如何制作一個(gè)網(wǎng)站
  • 網(wǎng)站抄襲別人的做可以嗎網(wǎng)站入口百度
  • 常熟建設(shè)銀行 招聘網(wǎng)站seddog站長(zhǎng)之家
  • 公司網(wǎng)站維護(hù)內(nèi)容重慶seo公司
  • wordpress插件直播長(zhǎng)沙seo工作室
  • 專門做面條菜譜的網(wǎng)站輿情監(jiān)測(cè)軟件免費(fèi)版
  • 網(wǎng)站建設(shè)的費(fèi)用是多少錢購(gòu)物網(wǎng)站如何推廣
  • 做燈箱的網(wǎng)站百度收錄網(wǎng)站提交入口
  • 網(wǎng)站規(guī)劃與建設(shè)大作業(yè)b站網(wǎng)站推廣mmm
  • 做棋牌網(wǎng)站合法熱狗seo顧問(wèn)
  • 黃頁(yè)網(wǎng)站是什么指數(shù)
  • 網(wǎng)站建設(shè) app百度怎么優(yōu)化排名
  • 網(wǎng)站背景跟著鼠標(biāo)動(dòng)的圖怎么做sem優(yōu)化
  • 東湖南昌網(wǎng)站建設(shè)公司杭州網(wǎng)站優(yōu)化效果
  • 網(wǎng)站的形成網(wǎng)站整站優(yōu)化推廣方案
  • 做海報(bào)文案的參考網(wǎng)站什么是網(wǎng)絡(luò)整合營(yíng)銷
  • wordpress站點(diǎn)描述濮陽(yáng)市網(wǎng)站建設(shè)
  • 幫做3d模型的網(wǎng)站南寧seo怎么做優(yōu)化團(tuán)隊(duì)
  • python庫(kù)之web網(wǎng)站開發(fā)PPT今天剛剛發(fā)生的重大新聞
  • 綿陽(yáng)市建設(shè)局網(wǎng)站全網(wǎng)推廣怎么做
  • 中國(guó)工程局人才招聘網(wǎng)臨沂seo推廣外包
  • 開公司可以在哪些網(wǎng)站做推廣鄭州網(wǎng)站建設(shè)公司
  • 網(wǎng)站建設(shè)圖片素材信息流推廣
  • 有沒有做任務(wù)能兌換現(xiàn)金的網(wǎng)站百度提交網(wǎng)址入口
  • 不讓在建設(shè)門戶網(wǎng)站aso優(yōu)化工具
  • 一個(gè)可以做行程的網(wǎng)站最新新聞熱點(diǎn)事件