基于比较的排序---选择插入冒泡

Posted mvcq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于比较的排序---选择插入冒泡相关的知识,希望对你有一定的参考价值。

初学排序时,也比较模糊,多是照猫画虎,不能透彻理解。今天对几种简单的排序的做一小结。日后继续学习、总结更多地、性能更优的排序!

一、选择排序

先把代码贴上

 

 1 #include<stdio.h>
 2 int main()
 3 {
 4     int a[9] = {5,7,4,6,1,9,3,2,8};
 5     int len = sizeof(a)/sizeof(int);
 6     int i,j,min,temp,m;
 7     for(i = 0; i < len; i++) 
 8     {
 9         min = i;
10         for(j = i+1; j < len; j++)
11         {
12             if(a[min] > a[j])
13             {
14                 min = j;
15             }
16         }
17 
18         if(min != i)
19         {
20             temp = a[min];
21             a[min] = a[i];
22             a[i] = temp;
23         }
24     }
25 
26     for(m = 0; m <len; m++)
27     {
28         printf("%d ",a[m]);
29     }
30 
31     return 0;
32 
33 }

 

此处以升序为例

如下图所示,对该数组进行升序排序

技术分享图片

 

选择排序的原理其实很简单,就是用一个变量min始终保存当前未排序序列的最小元素下标。当外层的第一次循环结束后,比较一下参加该次循环的下标是否和当前的min一致,如果一致,则不管,如果不一致交换两个下标对应元素的位置。

下面针对这段话结合上图做一分析:

第一趟:在比较之前,先定义min用来保存当前最小元素的下标。

a[min]分别和a[i+1](a[j])比较,第一次a[0](5)和a[1](7)比较,a[0]小,继续,j++,接着a[0]和a[2]比较,a[0]大,则把当前j值的赋给min,即min = 2; 因为min保存的是当前最小元素下标,现在发现有人比他小了,就要更新自身的值了。那么现在就是用a[2]和a[3]比较了,a[2]小,继续j++。a[2]和a[4]比,a[4]小。更新min的值为4,j++。继续用a[4]和a[5]比,a[4]小,j++。一直比较a[8],发现都是a[4]小,则第一趟比较结束。得出最小元素的下标为4。

然后用外层第一次进入循环的i值和min比较,如果不相等,说明这个i对应的元素不是最小元素,那么就和min下标对应的元素互换位置,将最小元素置于数组首位了。

第二趟:此时的i等于2了,min也重新被初始为2,继续让a[min]和a[i+1]比较,步骤和第一趟的完全相同,这趟下来,又可以找到最小元素的角标。

接下来就是重复这个步骤了。

具体过程如下图:

技术分享图片

 

二、直接插入排序

 

 先贴代码

 1 #include<stdio.h>
 2 int main()
 3 {
 4     int a[5] = {5,7,4,6,3};
 5     int len = sizeof(a)/sizeof(int);
 6     int i,j,temp,m;
 7     for(i = 1; i < len; i++)
 8     {
 9         if(a[i] < a[i-1])
10         {
11             temp = a[i];
12         
13             for(j = i-1; j >= 0 && a[j] > temp; j--)
14             {
15                 a[j+1] = a[j];
16             }
17             a[j+1] = temp;
18         }
19     }
20     for(m = 0; m < len; m++)
21     {
22         printf("%d ",a[m]);
23     }
24     return 0;
25 }

话都在图里了:

技术分享图片

三、冒泡排序

贴代码:

 1 #include<stdio.h>
 2 int main()
 3 {
 4     int a[5] = {5,6,3,7,4};
 5     int i,j,k,temp;
 6     int len = sizeof(a)/sizeof(int);
 7 
 8     for(i = 0; i < len - 1; i++)
 9     {
10         bool flag = true;
11         for(j = 0; j < len - i - 1; j++)
12         {
13             if(a[j] > a[j+1]) 
14             {
15                 temp = a[j];
16                 a[j] = a[j+1];
17                 a[j+1] = temp;
18                 flag = false;
19             }
20 
21         }
22         if(flag)
23         {
24             break;
25         }
26     }
27 
28     for(k = 0; k < len; k++)
29     {
30         printf("%d ",a[k]);
31     }
32     return 0;
33 }

上图:

技术分享图片

如图所示,针对数组元素为5,6,3,7,4进行了冒泡排序,每次比较相邻的两个元素,若前者大于后者,则互换,反之,不换,继续往后推进。但可以发现,在进行完三次冒泡之后,已经产生了最终结果:3,4,5,6,7。但程序并不会因此停止,它仍会继续执行两轮,进行最后两次的冒泡,但这是没有意义的。所以在代码中增加了标志flag的设定,如果没有比较了,就不再执行操作,就可以认为,当前序已按照要求序列排列完毕!

总结:

    简单选择排序:

    基本思想为每一趟从待排序的数据元素中选择最小(或最大)的一个元素作为数组首元素,直到所有元素排完为止,简单选择排序是不稳定排序。时间复杂度为O(n2)

    直接插入排序:

    基本思想为每一步将一个待排序的记录,插入到前面已经排好序的有序序列中,直到插完所有元素为止。时间复杂度为O(n2)。

    冒泡排序:

    基本思想为对相邻的元素进行两两比较,顺序相反则进行交换,这样,每一趟会将最小或最大的元素“浮”到顶端,最终达到完全有序。时间复杂度依然为O(n2

 


以上是关于基于比较的排序---选择插入冒泡的主要内容,如果未能解决你的问题,请参考以下文章

三大基础排序算法(冒泡排序,选择排序,插入排序)

排序(上):冒泡排序插入排序和选择排序

java常见排序算法--选择排序冒泡排序插入排序分析与比较

排序--冒泡,插入,选择

图形化排序算法比较:快速排序插入排序选择排序冒泡排序

JavaScript算法(冒泡排序选择排序与插入排序)