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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【数据结构基础应用】【查找和排序算法】

發(fā)布時(shí)間:2023/12/1 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【数据结构基础应用】【查找和排序算法】 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

代碼參考《妙趣橫生的算法.C語(yǔ)言實(shí)現(xiàn)》

文章目錄

  • 前言
  • 1、順序查找
  • 2、折半查找
  • 3、直接插入排序
  • 4、選擇排序
  • 5、冒泡排序
  • 6、希爾排序
  • 7、快速排序
  • 8、堆排序
  • 9、排序算法性能比較
  • 10、所有算法的code(C語(yǔ)言)


前言

本章總結(jié)查找和排序算法:順序查找、折半查找、直接插入排序、冒泡排序、簡(jiǎn)單選擇排序、希爾排序、快速排序、堆排序以及排序算法性能比較。


1、順序查找

順序查找就是在文件的關(guān)鍵字結(jié)合key[1,2,…n]中找出與給定的關(guān)鍵字key相等的文件記錄。

步驟描述:

1、從文件的第一個(gè)記錄開始,將每個(gè)記錄的關(guān)鍵字與給定的關(guān)鍵字key進(jìn)行比較

2、如果查找到某個(gè)記錄的關(guān)鍵字等于key,則查找成功,返回該記錄的地址。如果所有記錄的關(guān)鍵字都與key進(jìn)行了比較,但都未匹配,則本次查找失敗,返回失敗標(biāo)記-1

//順序查找:n表示記錄個(gè)數(shù)、key表示要查找記錄的關(guān)鍵字、key[]為存放所有記錄關(guān)鍵字順序表。 int sq_search(keytyped key[],int n,keytype key) {int i;for (i=0;i<n;i++){if (key[i] == key){return i;}}return -1; }

用結(jié)構(gòu)體描述:

typedef struct {keytype key; //keytype類型的關(guān)鍵字keydatatype data; //記錄其中信息 }RecordType; int sq_search(RecordType r[], int n, keytype key) {int i;for (i = 0;i < n;i++){if (r[i].key == key) //查找成功{return i;}}return -1; } //缺點(diǎn):平均查找長(zhǎng)度過(guò)大,查找效率較低

2、折半查找

只有在關(guān)鍵字的排序是有序的(遞增或遞減)情況下,才能應(yīng)用折半查找的算法描述。

基本思想:

減少查找序列的長(zhǎng)度,分而治之進(jìn)行關(guān)鍵字的查找。

查找過(guò)程:先去定待查找記錄的所在反胃,然后逐漸縮小查找的范圍,直到找到為止(也可能查找失敗)

//基于遞增序列的折半查找 //n表示記錄個(gè)數(shù)、k表示要查找到的關(guān)鍵字、key[]關(guān)鍵字順序表 int bin_search(keytype key[], int n, keytype k) {int low = 0, high = n - 1, mid;while (low <= high){mid = (low+high) / 2;if (key[mid] == k)return mid;if (k > key[mid])low = mid + 1; //在后半序列中查找elsehigh = mid - 1;}return -1; //查找失敗,返回-1 }

用結(jié)構(gòu)體描述:

typedef struct {keytype key; //關(guān)鍵字datatype data; //記錄的信息 }RecordType;int bin_search(RecordType r[], int n, keytype key) {int low = 0, high = n - 1, mid;while (low <= high){mid = (low + high) / 2;if (r[mid].key == key)return mid;if (key > r[mid].key)low = mid + 1; //在后半序列中查找elsehigh = mid - 1;}return -1; //查找失敗,返回-1 }

3、直接插入排序

排序可以理解為:
根據(jù)文件記錄的關(guān)鍵字值得遞增或者遞減關(guān)系將文件記錄的次序進(jìn)行重新排列的過(guò)程。
或者是:將一個(gè)按值無(wú)序的數(shù)據(jù)序列轉(zhuǎn)換成為一個(gè)按值有序的數(shù)據(jù)序列的過(guò)程

直接插入排序(Straight Insertion Sort)是一種最簡(jiǎn)單的排序方法,其基本操作是將一條記錄插入到已排好的有序表中,從而得到一個(gè)新的、記錄數(shù)量增1的有序表。

在日常生活中,經(jīng)常碰到這樣一類排序問(wèn)題:把新的數(shù)據(jù)插入到已經(jīng)排好的數(shù)據(jù)列中。例如:一組從小到大排好順序的數(shù)據(jù)列{1,2,3,4,5,6,7,9,10},通常稱之為有序列,我們用序號(hào)1,2,3,…表示數(shù)據(jù)的位置,欲把一個(gè)新的數(shù)據(jù)8插入到上述序列中。

完成這個(gè)工作的步驟:
①確定數(shù)據(jù)“8”在原有序列中應(yīng)該占有的位置序號(hào)。數(shù)據(jù)“8”所處的位置應(yīng)滿足小于或等于該位置右邊所有的數(shù)據(jù),大于其左邊位置上所有的數(shù)據(jù)。

②將這個(gè)位置空出來(lái),將數(shù)據(jù)“8”插進(jìn)去。
直接插入排序(straight insertion sort)的做法是:
每次從無(wú)序表中取出第一個(gè)元素,把它插入到有序表的合適位置,使有序表仍然有序。
第一趟比較前兩個(gè)數(shù),然后把第二個(gè)數(shù)按大小插入到有序表中; 第二趟把第三個(gè)數(shù)據(jù)與前兩個(gè)數(shù)從后向前掃描,把第三個(gè)數(shù)按大小插入到有序表中;依次進(jìn)行下去,進(jìn)行了(n-1)趟掃描以后就完成了整個(gè)排序過(guò)程。
直接插入排序是由兩層嵌套循環(huán)組成的。外層循環(huán)標(biāo)識(shí)并決定待比較的數(shù)值。內(nèi)層循環(huán)為待比較數(shù)值確定其最終位置。直接插入排序是將待比較的數(shù)值與它的前一個(gè)數(shù)值進(jìn)行比較,所以外層循環(huán)是從第二個(gè)數(shù)值開始的。當(dāng)前一數(shù)值比待比較數(shù)值大的情況下繼續(xù)循環(huán)比較,直到找到比待比較數(shù)值小的并將待比較數(shù)值置入其后一位置,結(jié)束該次循環(huán)。

#include<iostream> using namespace std; void Insertsort(int a[],int k) {int i, j;for (i = 1;i < k;i++)//循環(huán)從第2個(gè)元素開始{if (a[i] < a[i - 1]){int temp = a[i];for (j = i - 1;j >= 0 && a[j] > temp;j--){a[j + 1] = a[j];}a[j + 1] = temp;//此處就是a[j+1]=temp;}} } int main() {int a[] = { 98,76,109,34,67,190,80,12,14,89,1 };int k = sizeof(a) / sizeof(a[0]);Insertsort(a,k);for (int f = 0;f < k;f++){cout << a[f] << " ";}return 0; }

4、選擇排序

基本思想:第i趟排序從序列后n-i+1個(gè)元素中選擇一個(gè)最小的元素,與該n-i+1個(gè)元素的最前面那個(gè)元素進(jìn)行位置交換,也就是與第i個(gè)位置上的元素進(jìn)行交換,直道n=i-1;

直觀講,每一趟的選擇排序就是從序列中未排好順序的元素中選擇一個(gè)最小的元素,將鈣元素與這些未排好的元素中的第一個(gè)元素交換位置。

void Selectsort(int a[], int k) {int i, j,min;int tmp;for (i = 0;i < k;i++){min = i;for (j = i + 1;j < k;i++){if (a[j] <= a[min]){min = j;}}if (min != i) //如果找到比a[min]還要小的值就進(jìn)行交換位置,否則不交換{tmp = a[min];a[min] = a[i];a[i] = tmp;}} }

5、冒泡排序

基本思想描述:

1、將序列中的第一個(gè)元素和第二個(gè)元素進(jìn)行比較,若前者大于后者,則將第一個(gè)元素與第二個(gè)元素進(jìn)行位置交換,否則不交換

2、將第2個(gè)元素與第3個(gè)元素進(jìn)行比較,同樣若前者大于后者,則將第2個(gè)元素與第3個(gè)元素進(jìn)行位置交換,否則不交換。

3、以此類推,直到將第n-1個(gè)元素與第n個(gè)元素進(jìn)行比較為止。此過(guò)程稱為第1趟冒泡排序,進(jìn)過(guò)第21趟冒泡排序后,將長(zhǎng)度為n的序列中最大的元素置于序列的尾部,即第n個(gè)位置上。

4、之后再進(jìn)行第2趟…第n-1趟排序。冒泡排序完成。

改進(jìn)思路:

以序列3 6 4 2 11 10 6為例:

第一趟bubblesort之后:

3 4 2 6 10 6 11

第二趟bubblesort之后:

3 2 4 6 6 10 11

第三趟bubblesort之后:

2 3 4 6 6 10 11

這時(shí)再進(jìn)行冒泡排序就會(huì)發(fā)現(xiàn),序列本身不會(huì)再發(fā)生變化,只有相鄰元素的比較,而沒(méi)有相鄰元素的交換,也就是說(shuō)此時(shí)排序已經(jīng)完成了。

所以可以這樣改進(jìn):

如果某一趟排序過(guò)程中只有元素之間的比較而沒(méi)有元素之間的位置交換,說(shuō)明排序完成。

void ImprovedBubblesort(int a[], int n) {int i, j;int tmp;int flag = 1; //flag=1,說(shuō)明本趟排序中仍有元素交換動(dòng)作for (i = 0;i < n && flag==1;i++) //趟次,一共n-1次{flag = 0;for (j = 0;j < n - 1;j++) //元素交換{if (a[j] > a[i]){flag = 1;tmp = a[j];a[j] = a[i];a[i] = tmp;}}} }

6、希爾排序

基本思路:

1、設(shè)定一個(gè)元素間隔增量gap,將參加排序的序列按照這個(gè)間隔數(shù)gap從第1個(gè)元素開始依次分成若干個(gè)子序列。

2、在子序列中可以采用其他的排序方法,例如冒泡排序。

3、縮小增量gap,重新將整個(gè)序列按照新的間隔數(shù)gap進(jìn)行劃分,再分別對(duì)每個(gè)子序列排序。過(guò)程描述:縮小增量gap–>劃分序列–>將子序列排序

4、直到間隔數(shù)gap=1為止。

希爾排序過(guò)程:

思考:如何確定間隔數(shù)gap?
數(shù)學(xué)上仍然是一個(gè)尚未解決的難題,但是經(jīng)驗(yàn)告訴我們一種比較常用且效果好的方法:
1、首先gap取值為序列長(zhǎng)度的一半
2、后續(xù)排序過(guò)程中,后一趟排序的gap取值為前一趟排序gap的一半取值
算法描述:

void Shellsort(int a[], int n) {int i, j;int tmp;int flag = 1; int gap = n; //第一次gap為nwhile (gap > 1){//確定gapgap = gap / 2;//以gap劃分子序列,每一次迭代都是一組子序列的一趟自排序(冒泡)do {flag = 0;for (i = 0;i < n - gap;i++){j = i + gap;if (a[j] < a[i]){flag = 1;tmp = a[j];a[j] = a[i];a[i] = tmp;}}} while (flag==1);} }

7、快速排序

基本思想:
1、在當(dāng)前的排序序列中任意選取一個(gè)元素,把該元素稱為基準(zhǔn)元素或支點(diǎn),把下雨等于基準(zhǔn)元素的所有元素都移動(dòng)到基準(zhǔn)元素的前面,把大于基準(zhǔn)元素的所有元素都移到基準(zhǔn)元素的后面,這樣使得基準(zhǔn)元素所處的位置 恰好就是排序的最終位置,并且把當(dāng)前參加排序的序列分為前后兩個(gè)序列。
2、上述的過(guò)程稱為一趟快速排序,即快速排序的一次劃分
3、接下來(lái)分別對(duì)這兩個(gè)子序列重復(fù)上述的排序操作(如果子序列長(zhǎng)度大于1的話),直到所有元素都被移動(dòng)到排序后他們應(yīng)處的最終位置上。
效率之所以高:每一次元素的移動(dòng)都是跳躍的,不會(huì)像冒泡排序只能在相鄰元素之間進(jìn)行,元素移動(dòng)的間隔較大,因此總的比較和移動(dòng)次數(shù)減少

具體步驟:

1、假設(shè)序列a,設(shè)置兩個(gè)變量i、j.分別指向首元素和尾元素,設(shè)定i指向的首元素為基準(zhǔn)元素

2、反復(fù)執(zhí)行i++,直到i指向的元素>=基準(zhǔn)元素,或者i指向尾部

3、反復(fù)執(zhí)行j–,直到指向的元素<基準(zhǔn)元素,或者j指向頭部

4、若此時(shí)i<j,將i和j指向的元素進(jìn)行交換。(大的元素在后面)

5、完成第一次交換后,重復(fù)執(zhí)行步驟1、2,直到i>=j位置

6、此時(shí)i>=j,然后將基準(zhǔn)元素與j指向的元素交換位置,至此完成了原序列的第一次劃分

7、接下來(lái)分別對(duì)基準(zhǔn)元素前后的子序列中長(zhǎng)度大于1的子序列重復(fù)執(zhí)行上述操作。

步驟分析:

對(duì)于每個(gè)子序列的操作又是一次劃分,因此這個(gè)算法具有遞歸性質(zhì)。

每次劃分過(guò)程的基準(zhǔn)元素仍可設(shè)定為子序列的第一個(gè)元素

//快速排序 void Quicksort(int a[], int s,int t) {int i, j;if (s < t){//【1】設(shè)置兩個(gè)變量i、j.分別指向首元素和尾元素,設(shè)定i指向的首元素為基準(zhǔn)元素i = s;j = t + 1;while (1){do i++;while(!(a[s]<=a[i] || i==t)); //【2】重復(fù)i++操作,直到i指向的元素>=基準(zhǔn)元素,或者i指向尾部do j--;while (!(a[s]>=a[j] || j==s)); //【3】反復(fù)執(zhí)行j--,直到指向的元素<基準(zhǔn)元素,或者j指向頭部if (i < j) //【5】若此時(shí)i<j,將i和j指向的元素進(jìn)行交換。(大的元素在后面){swap(a[j], a[i]);}else break; //【5】完成第一次交換后,重復(fù)執(zhí)行步驟1、2,直到i>=j位置}//【6】此時(shí)i>=j,然后將基準(zhǔn)元素與j指向的元素交換位置,至此完成了原序列的第一次劃分swap(a[s],a[j]);//【7】接下來(lái)分別對(duì)基準(zhǔn)元素前后的子序列中長(zhǎng)度大于1的子序列重復(fù)執(zhí)行上述操作。Quicksort(a,s,j-1); //前半序列Quicksort(a,j+1,t); //后半序列} }

快速排序只適用于順序表線性結(jié)構(gòu)或者數(shù)組序列的排序,不適合在鏈表上實(shí)現(xiàn)

8、堆排序

heapsort是選擇排序的改進(jìn)。

首先了解一下堆的概念:

堆通常是一個(gè)可以被看做一棵完全二叉樹的數(shù)組對(duì)象。

堆的定義如下:n個(gè)元素的序列{k1,k2,ki,…,kn}當(dāng)且僅當(dāng)滿足下關(guān)系時(shí),稱之為堆。

(ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4…n/2)

堆總是滿足下列性質(zhì):

1、 堆中某個(gè)節(jié)點(diǎn)的值總是不大于或不小于其父節(jié)點(diǎn)的值;

2、 堆總是一棵完全二叉樹。

了解一下完全二叉樹的概念:

https://blog.csdn.net/judgejames/article/details/87868602

將根節(jié)點(diǎn)最大的堆叫做最大堆或大根堆,根節(jié)點(diǎn)最小的堆叫做最小堆或小根堆

舉例:

序列{49,22,40,20,18,36,6,12,17}

基于大頂堆的完全二叉樹表示的堆排序的核心思想可描述如下:

1、將原始序列構(gòu)成一個(gè)堆(建立初始堆)

2、交換堆的第一個(gè)元素和堆的最后一個(gè)元素

3、將交換最大值元素之后的剩余元素所構(gòu)成的序列再轉(zhuǎn)換成一個(gè)堆

4、重復(fù)上述2、3步驟n-1次

經(jīng)過(guò)上述操作,就可以將一個(gè)無(wú)序的序列從小到大進(jìn)行排序。

關(guān)鍵問(wèn)題:

1、如何原始序列構(gòu)成一個(gè)堆

2、如何將交換最大值元素之后的剩余元素所構(gòu)成的序列再轉(zhuǎn)換成一個(gè)堆

第二個(gè)問(wèn)題:

該二叉樹雖然不是一個(gè)堆,但是除了根結(jié)點(diǎn)外,其余任何一棵子樹仍然滿足堆的特性。

自上而下調(diào)整:將序號(hào)為i的結(jié)點(diǎn)與其左右孩子(2i 、2i+1)三個(gè)值中的最大值替換到序號(hào)為i的結(jié)點(diǎn)的位置上。

只要徹底地完成一次自上而下的調(diào)整,該二叉樹就會(huì)變成一個(gè)堆。

最后一步:交換第一個(gè)元素和新堆的最后一個(gè)元素的位置,也就是將最大的元素移至新堆的最后。

第一個(gè)問(wèn)題:

如果原序列對(duì)應(yīng)的完全二叉樹有n個(gè)結(jié)點(diǎn),則:

1、初始化時(shí),令序列號(hào)為i= Floor (n/2),它對(duì)應(yīng)于而擦函數(shù)中第 Floor (n/2)個(gè)結(jié)點(diǎn)(二叉樹中的結(jié)點(diǎn)按照層次編號(hào),從1開始,從左到右,從上到下編號(hào))

2、調(diào)用函數(shù)adjust調(diào)整

3、每執(zhí)行完一次調(diào)整都執(zhí)行一次i=i-1操作

4、重復(fù)步驟2、3,直到i==1時(shí)執(zhí)行步驟5

5、最后再調(diào)用adjust函數(shù)調(diào)整一次。

這樣就完成調(diào)整了。

示例:初始序列為:{23,6,77,2,60,10,58,16,48,20}

code:

//堆排序 //【1】將二叉樹調(diào)整為一個(gè)堆的函數(shù): //函數(shù)作用:將以第i個(gè)元素作為根結(jié)點(diǎn)的子樹調(diào)整為一個(gè)新的堆序列,前提是該子樹中除了根結(jié)點(diǎn)外其余的任何一個(gè)子樹仍然滿足堆的特性,如果該子樹除了根結(jié)點(diǎn)外其他子樹也不完全是 //堆結(jié)構(gòu)的話,則不能僅通過(guò)依次調(diào)用adjust函數(shù)就將其調(diào)整為堆 //輸入:序列a i:序列a中的元素下標(biāo) void BiTreeAdjustToHeap(int a[],int i,int n) {int j;int tmp;tmp = a[i];j = 2 * i; //j為i的左孩子結(jié)點(diǎn)序號(hào)while (j <= n){if (j < n && a[j] < a[j + 1]){j++; //j為i的左右孩子中較大孩子的序號(hào)}if (tmp >= a[j]) //如果父結(jié)點(diǎn)值比孩子值還大就不需要調(diào)整了{break;}a[j / 2] = a[j]; //較大的子節(jié)點(diǎn)與父節(jié)點(diǎn)交換位置j = 2 * j; //繼續(xù)向下調(diào)整}a[j / 2] = tmp; }//【2】原始序列初始化函數(shù) void InitHeap(int a[],int n) {for(int i=n/2;i>=0;i--){BiTreeAdjustToHeap(a,i,n);} } //堆排序函數(shù) void Heapsort(int a[], int n) {int i = 0;//【1】原始序列初始化函數(shù)InitHeap(a,n);//【2】交換第1個(gè)和第n個(gè)元素,再將根結(jié)點(diǎn)向下調(diào)整for (i = n - 1;i >= 0;i--){swap(a[i+1],a[0]);BiTreeAdjustToHeap(a,0,i); //將根結(jié)點(diǎn)向下調(diào)整} }

需要把握的要點(diǎn):

1、堆排序是針對(duì)線性序列的排序,之所以要采用完全二叉樹的形式解釋堆排序的過(guò)程,是出于方便解釋的需要

2、堆排序的第一步是將原序列變成一個(gè)對(duì)序列

3、一系列的交換調(diào)整操作。所謂交換就是將堆中第一個(gè)元素與本次調(diào)整范圍內(nèi)的新堆的最后一個(gè)元素交換位置,使得較大的元素能夠置于序列的最后面,所謂調(diào)整就是將交換后的剩余元素從上至下調(diào)整為為一個(gè)新堆的過(guò)程。

4、通過(guò)2、3操作可以將一個(gè)無(wú)序序列從小到大偶愛(ài)徐

5、如果基于大頂堆進(jìn)行堆排序,則排序后的序列從小到大。若是基于小頂堆,則從大到小。

9、排序算法性能比較

排序算法平均時(shí)間最壞情況空間需求
直接插入排序O(n^2)O(n^2)O(1)
冒泡排序O(n^2)O(n^2)O(1)
簡(jiǎn)單選擇排序O(n^2)O(n^2)O(1)
希爾排序O(nlog2n)O(nlog2n)O(1)
快速排序O(nlog2n)O(n^2)O(nlog2n)
堆排序O(nlog2n)O(nlog2n)O(1)

總結(jié):

1、如果參加排序的序列最開始就是基本有序或者局部有序的,使用這直接插入排序和冒泡排序的效果較好,排序速度較快,最好的情況下(原序列按值有序),時(shí)間復(fù)雜度O(n)

2、快速排序最快,堆排序空間消耗最小

3、序列中元素個(gè)數(shù)越小,采用冒泡排序排序算法、直接插入排序、簡(jiǎn)單選擇排序較合適

當(dāng)序列規(guī)模變大時(shí),采用希爾排序、快速排序和堆排序比較合適

4、從穩(wěn)定性來(lái)講:直接插入、冒泡是穩(wěn)定的排序方法。簡(jiǎn)單選擇排序、希爾排序、快速排序、堆排序是不穩(wěn)定的排序算法

10、所有算法的code(C語(yǔ)言)

#include<iostream> using namespace std; void swap(int& a, int& b) {//方法一: int tmp = 0;tmp = b;b = a;a = tmp;//方法二: //a = a+b; //b = a-b; //a = a -b; //方法三: //a ^= b ^= a ^= b; //方法四: 冒泡和希爾和改進(jìn)冒泡,使用這個(gè)方法不成功 //a = a+b-(b=a); } //參考:https://blog.csdn.net/shangguanyunlan/article/details/51778378 // void Insertsort(int a[],int k) {int i, j;for (i = 1;i < k;i++)//循環(huán)從第2個(gè)元素開始{if (a[i] < a[i - 1]){int temp = a[i];for (j = i - 1;j >= 0 && a[j] > temp;j--){a[j + 1] = a[j];}a[j + 1] = temp;//此處就是a[j+1]=temp;}} } //選擇排序 void Selectsort(int a[], int k) {int i, j,min;int tmp;for (i = 0;i < k;i++){min = i;for (j = i + 1;j < k;i++){if (a[j] <= a[min]){min = j;}}if (min != i) //如果找到比a[min]還要小的值就進(jìn)行交換位置,否則不交換{swap(a[min],a[i]);}} } //冒泡排序 void Bubblesort(int a[], int n) {int i, j;int tmp;for (i=0;i<n;i++) //趟次,一共n-1次{for (j = 0;j < n - 1;j++) //元素交換{if (a[j] > a[i]){swap(a[j], a[i]);}}} } //改進(jìn)的冒泡排序 void ImprovedBubblesort(int a[], int n) {int i, j;int tmp;int flag = 1; //flag=1,說(shuō)明本趟排序中仍有元素交換動(dòng)作for (i = 0;i < n && flag==1;i++) //趟次,一共n-1次{flag = 0;for (j = 0;j < n - 1;j++) //元素交換{if (a[j] > a[i]){flag = 1;swap(a[j], a[i]);}}} } //希爾排序 void Shellsort(int a[], int n) {int i, j;int tmp;int flag = 1; int gap = n; //第一次gap為nwhile (gap > 1){//確定gapgap = gap / 2;//以gap劃分子序列,每一次迭代都是一組子序列的一趟自排序(冒泡)do {flag = 0;for (i = 0;i < n - gap;i++){j = i + gap;if (a[j] < a[i]){flag = 1;swap(a[j], a[i]);}}} while (flag==1);} } //快速排序 void Quicksort(int a[], int s,int t) {int i, j;if (s < t){//【1】設(shè)置兩個(gè)變量i、j.分別指向首元素和尾元素,設(shè)定i指向的首元素為基準(zhǔn)元素i = s;j = t + 1;while (1){do i++;while(!(a[s]<=a[i] || i==t)); //【2】重復(fù)i++操作,直到i指向的元素>=基準(zhǔn)元素,或者i指向尾部do j--;while (!(a[s]>=a[j] || j==s)); //【3】反復(fù)執(zhí)行j--,直到指向的元素<基準(zhǔn)元素,或者j指向頭部if (i < j) //【5】若此時(shí)i<j,將i和j指向的元素進(jìn)行交換。(大的元素在后面){swap(a[j], a[i]);}else break; //【5】完成第一次交換后,重復(fù)執(zhí)行步驟1、2,直到i>=j位置}//【6】此時(shí)i>=j,然后將基準(zhǔn)元素與j指向的元素交換位置,至此完成了原序列的第一次劃分swap(a[s],a[j]);//【7】接下來(lái)分別對(duì)基準(zhǔn)元素前后的子序列中長(zhǎng)度大于1的子序列重復(fù)執(zhí)行上述操作。Quicksort(a,s,j-1); //前半序列Quicksort(a,j+1,t); //后半序列} }//堆排序 //【1】將二叉樹調(diào)整為一個(gè)堆的函數(shù): //函數(shù)作用:將以第i個(gè)元素作為根結(jié)點(diǎn)的子樹調(diào)整為一個(gè)新的堆序列,前提是該子樹中除了根結(jié)點(diǎn)外其余的任何一個(gè)子樹仍然滿足堆的特性,如果該子樹除了根結(jié)點(diǎn)外其他子樹也不完全是 //堆結(jié)構(gòu)的話,則不能僅通過(guò)依次調(diào)用adjust函數(shù)就將其調(diào)整為堆 //輸入:序列a i:序列a中的元素下標(biāo) void BiTreeAdjustToHeap(int a[],int i,int n) {int j;int tmp;tmp = a[i];j = 2 * i; //j為i的左孩子結(jié)點(diǎn)序號(hào)while (j <= n){if (j < n && a[j] < a[j + 1]){j++; //j為i的左右孩子中較大孩子的序號(hào)}if (tmp >= a[j]) //如果父結(jié)點(diǎn)值比孩子值還大就不需要調(diào)整了{break;}a[j / 2] = a[j]; //較大的子節(jié)點(diǎn)與父節(jié)點(diǎn)交換位置j = 2 * j; //繼續(xù)向下調(diào)整}a[j / 2] = tmp; }//【2】原始序列初始化函數(shù) void InitHeap(int a[],int n) {for(int i=n/2;i>=0;i--){BiTreeAdjustToHeap(a,i,n);} } //堆排序函數(shù) void Heapsort(int a[], int n) {int i = 0;//【1】原始序列初始化函數(shù)InitHeap(a,n);//【2】交換第1個(gè)和第n個(gè)元素,再將根結(jié)點(diǎn)向下調(diào)整for (i = n - 1;i >= 0;i--){swap(a[i+1],a[0]);BiTreeAdjustToHeap(a,0,i); //將根結(jié)點(diǎn)向下調(diào)整} } void show_sort_result(int a[],int k) {for (int f = 0;f < k;f++){cout << a[f] << " ";}printf("\n"); } int main() {int a[] = { 98,76,109,34,67,190,80,12,14,89,1 };int k = sizeof(a) / sizeof(a[0]);//printf("直接插入排序\n");//Insertsort(a,k);//show_sort_result(a,k);//printf("選擇排序\n");//Insertsort(a, k);//show_sort_result(a,k);//printf("冒泡排序\n");//Bubblesort(a, k);//show_sort_result(a, k);//printf("改進(jìn)后的冒泡排序\n");//ImprovedBubblesort(a, k);//show_sort_result(a, k);//printf("希爾排序\n");//Shellsort(a, k);//show_sort_result(a, k);//printf("快速排序\n");//Quicksort(a,0,k-1);//show_sort_result(a, k);//printf("堆排序\n");//Heapsort(a,k-1);//show_sort_result(a, k);return 0; }

總結(jié)

以上是生活随笔為你收集整理的【数据结构基础应用】【查找和排序算法】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。