五種排序算法整理 一(堆排序,快速排序、插入排序、選擇排序、冒泡排序)


一、堆排序

1、部分概念

 

滿二叉樹:深度為k,且含有(2^k)-1個結點的二叉樹

完全二叉樹:深度為k的,又n個結點的,當且僅當其每一個節點都與深度為k的滿二叉樹種編號從1至n的節點一一對應時,稱為完全二叉樹

 

堆的結構可以分為大根堆小根堆,是一個完全二叉樹

每個結點的值都大於其左孩子和右孩子結點的值,稱之為大根堆;每個結點的值都小於其左孩子和右孩子結點的值,稱之為小根堆

(這個它們右兒子值與左兒子誰的值大誰的值小沒有要求

1.父結點索引:(i-1)/2(這里計算機中的除以2,省略掉小數)

2.左孩子索引:2*i+1

3.右孩子索引:2*i+2

 

 

 2、堆排序過程

升序----使用大頂堆

降序----使用小頂堆

思想(這里我們用大頂堆):

假設要對一個有n個元素的數組進行排序。這樣的話我們先把這個數組里面的前n個數據拿出來構建一個大頂堆。這個時候我們肯定能保證堆頂那個元素是最大的。然后我們把那個最大的元素放在數組的倒數第一個位置。然后在對數組里面前n-1個元素再構建一次大頂堆,這個時候再把堆頂元素拿出來放到數組倒數第二個位置。依次進行n-1次就完了。。。

 

怎么把一個二叉樹弄成大頂堆?看下面

 

 

由上面這個圖我么可以知道它的數組中元素順序是這樣:【9,1,6,4,5】 

我們發現1號位置的權值並不大於它的兒子的權值,所以我們給它左右兒子中那個權值大的兒子交換

 

 這個時候我們知道最大權值是9,那就讓最大權值放在數組倒數第一個位置,讓倒數第一個位置的權值和它交換一下

 

 這個時候原數組就變成了:【1,5,6,4,9】,然后就接着對這個二叉樹改造,使它變成大頂堆(這個時候第4和位置就不再參與)

 

 發現這樣就是一個大頂堆了

 

 數組:【4,5,1,6,9】

 

 又變成了大頂堆

 

 數組:【1,4,5,6,9】

 

 又變成了大頂堆

 

 數組:【1,4,5,6,9】

 

循環了5-1=4次,所以該結束了

 

最后結果就是【1,4,5,6,9】

 

剩余四種排序算法見下一篇博客:

五種排序算法整理 二(堆排序,快速排序、插入排序、選擇排序、冒泡排序)

 

全部代碼(這個是五種算法的代碼):

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #define maxn 1005
  5 int v[maxn],n,size=0;
  6 void Bubble_sort()  //冒泡排序
  7 {
  8     int i,j,temp;
  9     printf("原始序列:\n");
 10     for( i=0; i<n; ++i)
 11     {
 12         printf("%d ",v[i]);
 13     }
 14     printf("\n");
 15     printf("中間序列:\n");
 16     for(i=0; i<n; ++i)
 17     {
 18         for(j=i+1; j<n; ++j)
 19         {
 20             if(v[i]>v[j])  //因為是從小到大排序,所以這個條件滿足就是交換他們的值
 21             {
 22                 temp=v[i];
 23                 v[i]=v[j];
 24                 v[j]=temp;
 25             }
 26         }
 27 
 28         for( j=0; j<n; ++j)
 29         {
 30             printf("%d ",v[j]);
 31         }
 32         printf("\n");
 33     }
 34     printf("最終序列:\n");
 35     for( i=0; i<n; ++i)
 36     {
 37         printf("%d ",v[i]);
 38     }
 39     printf("\n");
 40 }
 41 void insert_sort() //簡單插入排序
 42 {
 43     int i,j,k,temp;
 44     printf("原始序列:\n");
 45     for( i=0; i<n; ++i)
 46     {
 47         printf("%d ",v[i]);
 48     }
 49     printf("\n");
 50     printf("中間序列:\n");
 51     for(i=1; i<n; ++i)
 52     {
 53         temp=v[i];
 54         for(j=i-1; j>=0; --j)
 55         {
 56             if(v[j]>temp)
 57             {
 58                 v[j+1]=v[j];
 59             }
 60             else break;
 61         }
 62         v[j+1]=temp;
 63 
 64         for( j=0; j<n; ++j)
 65         {
 66             printf("%d ",v[j]);
 67         }
 68         printf("\n");
 69     }
 70     printf("最終序列:\n");
 71     for( i=0; i<n; ++i)
 72     {
 73         printf("%d ",v[i]);
 74     }
 75     printf("\n");
 76 }
 77 void select_sort()  //簡單選擇排序
 78 {
 79     int i,j,k,temp,ans;
 80     printf("原始序列:\n");
 81     for( i=0; i<n; ++i)
 82     {
 83         printf("%d ",v[i]);
 84     }
 85     printf("\n");
 86     printf("中間序列:\n");
 87 
 88     for(i=0; i<n-1; ++i)
 89     {
 90         temp=i;
 91         for(j=i+1; j<n; ++j)
 92         {
 93             if(v[j]<v[temp]) temp=j;
 94         }
 95         if(temp!=i)  //如果相等的話那它就不用換位置
 96         {
 97             ans=v[temp];
 98             v[temp]=v[i];
 99             v[i]=ans;
100         }
101         for( j=0; j<n; ++j)
102         {
103             printf("%d ",v[j]);
104         }
105         printf("\n");
106     }
107 
108     printf("最終序列:\n");
109     for( i=0; i<n; ++i)
110     {
111         printf("%d ",v[i]);
112     }
113     printf("\n");
114 }
115 void quickSort(int begin,int end)  //快速排序
116 {
117     int k;
118     //如果區間不只一個數
119     if(begin < end)
120     {
121         int temp = v[begin]; //將區間的第一個數作為基准數
122         int i = begin; //從左到右進行查找時的“指針”,指示當前左位置
123         int j = end; //從右到左進行查找時的“指針”,指示當前右位置
124         //不重復遍歷
125         while(i < j)
126         {
127             //當右邊的數大於基准數時,略過,繼續向左查找
128             //不滿足條件時跳出循環,此時的j對應的元素是小於基准元素的
129             while(i<j && v[j] > temp)
130                 j--;
131             //將右邊小於等於基准元素的數填入右邊相應位置
132             v[i] = v[j];
133             //當左邊的數小於等於基准數時,略過,繼續向右查找
134             //(重復的基准元素集合到左區間)
135             //不滿足條件時跳出循環,此時的i對應的元素是大於等於基准元素的
136             while(i<j && v[i] <= temp)
137                 i++;
138             //將左邊大於基准元素的數填入左邊相應位置
139             v[j] = v[i];
140             for( k=0; k<n; ++k)
141             {
142                 printf("%d ",v[k]);
143             }
144             printf("\n");
145         }
146 
147         //將基准元素填入相應位置
148         v[i] = temp;
149         //此時的i即為基准元素的位置
150         //對基准元素的左邊子區間進行相似的快速排序
151         quickSort(begin,i-1);
152         //對基准元素的右邊子區間進行相似的快速排序
153         quickSort(i+1,end);
154     }
155     //如果區間只有一個數,則返回
156     else
157         return;
158 }
159 void solve_quickSort()
160 {
161     int i,j;
162     printf("原始序列:\n");
163     for( i=0; i<n; ++i)
164     {
165         printf("%d ",v[i]);
166     }
167     printf("\n");
168     printf("中間序列:\n");
169 
170     quickSort(0,n-1);
171 
172     printf("最終序列:\n");
173     for( i=0; i<n; ++i)
174     {
175         printf("%d ",v[i]);
176     }
177     printf("\n");
178 }
179 void swap(int *x,int *y)
180 {
181     int temp=*x;
182     *x=*y;
183     *y=temp;
184 }
185 int headSort(int* arr,int length)  //堆排序
186 {
187     int idx,k;
188     if(length<=0)
189         return -1;
190     //數組中順序存放的數據就對應完全二叉樹堆中的對應結點的值,現在調整為大根堆
191     for( idx=length/2-1; idx>=0; --idx) //從最后一個非葉子結點開始調整為最大堆
192     {
193         adjust(arr,idx,length-1);  //最后一個非葉子結點和它的孩子比較調整
194     }
195     //排序,根結點后最后一個結點交換,調整
196     for( idx=length-1; idx>0; --idx)
197     {
198         swap(&arr[0],&arr[idx]);  //每次選出一個最大的數放到末尾,也就是數組末尾
199         for( k=0; k<n; ++k)
200         {
201             printf("%d ",v[k]);
202         }
203         printf("\n");
204         adjust(arr,0,idx-1);  //調整根結點到idx-1個結點為大根堆
205     }
206     return 0;
207 }
208 void adjust(int* arr,int idx1,int idx2)
209 {
210     int tmp,idx;
211     if(idx1>=idx2||idx1<0||idx2<0)
212         return ;
213     tmp = arr[idx1];  //暫時存放要調整的數據
214     for( idx=idx1*2+1; idx<=idx2; idx=idx*2+1) //從要調整的數據的左孩子開始比較
215     {
216         //選出左右孩子中的最大結點
217         if(idx+1<=idx2 && arr[idx]<arr[idx+1])
218             ++idx;
219         if(arr[idx]>tmp)  //不滿足大根堆,調整
220         {
221             arr[idx1] = arr[idx];  //交換,可能破壞子樹滿足大根堆的性質
222             idx1 = idx;  //本來這里要交換的,但時tmp暫時存放了初始arr[idx1]的值,這里每次比較都是和tmp比較,好比交換了,所以可以不用先交換
223             //繼續向下調整,直到樹滿足大根堆性質
224         }
225         else
226             break;
227     }
228     arr[idx1] = tmp;
229 }
230 void solve_heapSort()
231 {
232     int i,j;
233     printf("原始序列:\n");
234     for( i=0; i<n; ++i)
235     {
236         printf("%d ",v[i]);
237     }
238     printf("\n");
239     printf("中間序列:\n");
240 
241     headSort(v,n);
242 
243     printf("最終序列:\n");
244     for( i=0; i<n; ++i)
245     {
246         printf("%d ",v[i]);
247     }
248     printf("\n");
249 }
250 int main()
251 {
252     int i,x;
253     printf("輸入序列長度:");
254     scanf("%d",&n);
255     for( i=0; i<n; ++i)
256     {
257         scanf("%d",&v[i]);
258     }
259     system("cls");
260     printf ( "                                                                 \n");
261     printf ( "                                                                 \n");
262     printf ( "                                                                 \n");
263     printf ("--------------------------------------                           \n");
264     printf ("--------------------------------------\n");
265     printf ("--------丨[0]冒泡排序            丨---\n");
266     printf ("--------丨[1]簡單插入排序        丨---\n");
267     printf ("--------丨[2]簡單選擇排序        丨---\n");
268     printf ("--------丨[3]快速排序            丨---\n");
269     printf ("--------丨[4]堆排序              丨---\n");
270     printf ("--------丨[5]結束                丨---\n");
271     printf ("----------輸入相應數字----------------\n");
272     printf ( "                                                                 \n");
273     printf ( "                                                                 \n");
274     scanf("%d",&x);
275     if(x==0)
276     {
277         system("cls");
278         Bubble_sort();
279     }
280     else if(x==1)
281     {
282         system("cls");
283         insert_sort();
284     }
285     else if(x==2)
286     {
287         system("cls");
288         select_sort();
289     }
290     else if(x==3)
291     {
292         system("cls");
293         solve_quickSort();
294     }
295     else if(x==4)
296     {
297         system("cls");
298         solve_heapSort();
299     }
300     else if(x==5)
301     {
302         system("cls");
303         printf("程序運行結束\n");
304     }
305     else printf("輸入錯誤\n");
306 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM