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


    一、堆排序

    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("原始序列:
    ");
     10     for( i=0; i<n; ++i)
     11     {
     12         printf("%d ",v[i]);
     13     }
     14     printf("
    ");
     15     printf("中间序列:
    ");
     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("
    ");
     33     }
     34     printf("最终序列:
    ");
     35     for( i=0; i<n; ++i)
     36     {
     37         printf("%d ",v[i]);
     38     }
     39     printf("
    ");
     40 }
     41 void insert_sort() //简单插入排序
     42 {
     43     int i,j,k,temp;
     44     printf("原始序列:
    ");
     45     for( i=0; i<n; ++i)
     46     {
     47         printf("%d ",v[i]);
     48     }
     49     printf("
    ");
     50     printf("中间序列:
    ");
     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("
    ");
     69     }
     70     printf("最终序列:
    ");
     71     for( i=0; i<n; ++i)
     72     {
     73         printf("%d ",v[i]);
     74     }
     75     printf("
    ");
     76 }
     77 void select_sort()  //简单选择排序
     78 {
     79     int i,j,k,temp,ans;
     80     printf("原始序列:
    ");
     81     for( i=0; i<n; ++i)
     82     {
     83         printf("%d ",v[i]);
     84     }
     85     printf("
    ");
     86     printf("中间序列:
    ");
     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("
    ");
    106     }
    107 
    108     printf("最终序列:
    ");
    109     for( i=0; i<n; ++i)
    110     {
    111         printf("%d ",v[i]);
    112     }
    113     printf("
    ");
    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("
    ");
    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("原始序列:
    ");
    163     for( i=0; i<n; ++i)
    164     {
    165         printf("%d ",v[i]);
    166     }
    167     printf("
    ");
    168     printf("中间序列:
    ");
    169 
    170     quickSort(0,n-1);
    171 
    172     printf("最终序列:
    ");
    173     for( i=0; i<n; ++i)
    174     {
    175         printf("%d ",v[i]);
    176     }
    177     printf("
    ");
    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("
    ");
    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("原始序列:
    ");
    234     for( i=0; i<n; ++i)
    235     {
    236         printf("%d ",v[i]);
    237     }
    238     printf("
    ");
    239     printf("中间序列:
    ");
    240 
    241     headSort(v,n);
    242 
    243     printf("最终序列:
    ");
    244     for( i=0; i<n; ++i)
    245     {
    246         printf("%d ",v[i]);
    247     }
    248     printf("
    ");
    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 ( "                                                                 
    ");
    261     printf ( "                                                                 
    ");
    262     printf ( "                                                                 
    ");
    263     printf ("--------------------------------------                           
    ");
    264     printf ("--------------------------------------
    ");
    265     printf ("--------丨[0]冒泡排序            丨---
    ");
    266     printf ("--------丨[1]简单插入排序        丨---
    ");
    267     printf ("--------丨[2]简单选择排序        丨---
    ");
    268     printf ("--------丨[3]快速排序            丨---
    ");
    269     printf ("--------丨[4]堆排序              丨---
    ");
    270     printf ("--------丨[5]结束                丨---
    ");
    271     printf ("----------输入相应数字----------------
    ");
    272     printf ( "                                                                 
    ");
    273     printf ( "                                                                 
    ");
    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("程序运行结束
    ");
    304     }
    305     else printf("输入错误
    ");
    306 }
  • 相关阅读:
    痞子衡嵌入式:恩智浦MCU集成开发环境与开发工具教程
    痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU硬件那些事(2.4)- 串行NOR Flash下载算法(Keil MDK工具篇)
    《痞子衡嵌入式半月刊》 第 17 期
    痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU硬件那些事(2.3)- 串行NOR Flash下载算法(J-Link工具篇)
    《痞子衡嵌入式半月刊》 第 16 期
    痞子衡嵌入式:关于做技术的工作态度方面的几点建议
    痞子衡嵌入式:MCUXpresso IDE下添加C++源文件进SDK工程编译的方法
    痞子衡嵌入式:职场上有效地向师傅请教问题的几点建议
    痞子衡职场经验与见闻感悟分享
    痞子衡嵌入式:IAR在线调试时设不同复位类型可能会导致i.MXRT下调试现象不一致(J-Link/DAPLink)
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/12177372.html
Copyright © 2020-2023  润新知