五种排序算法整理 一(堆排序,快速排序、插入排序、选择排序、冒泡排序)

一、堆排序

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 }
posted @ 2020-01-10 17:41  kongbursi  阅读(1833)  评论(0编辑  收藏  举报