排序算法是算法中的基础,今天我来用自己的话说下三种最基本的算法,理解了这三种基本的算法就可以进一步学习怎么优化排序算法了。呵呵,废话不多说,咱们开始。
简单选择排序算法:
简单选择排序的基本思想是:一次选定数组中的一个数,记下当前位置并假设它是从当前位置开始后面数中的最小数min=i,从这个数的下一个数开始扫描直到最后一个数,并记录下最小数的位置min,扫描结束后如果min不等于i,说明假设错误,则交换min与i位置上数。(也即:每次从数列中找出一个最小的数放到最前面来,再从剩下的n-1个数中选择一个最小的,不断做下去。)
通俗的话说:你要在你的班上选择女朋友,(假定你有这个权利的话),你开始肯定会最喜欢的,然后再选择次喜欢的,然后继续在剩下的MM中找你比较喜欢的。这样就可以按你的要求排成一个序了,就这样理解。
简单选择排序算法的关键:1.每一趟在n-i+1中选取最小的记录 2.通过n-i次关键字进行比较 3.总共需要n(n-1)/2次比较 4.选择排序算法的时间复杂度是“死”的,也就是O(n^2)
算法代码:
- #include<stdio.h>
- voidSelectSort(int*a,intlen)//简单选择排序算法*a为数组len为数组长度
- {
- inti,j,k;
- for(i=1;i<len;i++)//比较n-i次i为指向无序区的开始位置
- {
- j=i;
- for(k=i-1;j<len;j++)//k记下目前最小关键字的位置,每一轮进行比较取出最小值
- {
- if(a[j]<a[k])//如果排在前面的数字大于后面的就交换两者的key
- {
- k=j;
- }
- }
- if(k>=i)//一轮结束后,把k认为的最小值和i进行交换
- {
- intm;
- m=a[k];
- a[k]=a[i-1];
- a[i-1]=m;
- }
- }
- }
- intmain(void)
- {
- inta[10];
- while(true)
- {
- for(intn=0;n<10;n++)
- {
- printf("/n第%d数:",(n+1));
- scanf("%d",&a[n]);
- }
- SelectSort(a,10);
- for(inti=0;i<10;i++)//输出排序后的数
- {
- printf("%d",a[i]);
- }
- }
- }
插入排序:
插入排序基本思想是:假设待排序的记录存放在数组R[1..n]中。初始时,R[1]自成1个有序区,无序区为R[2..n]。从i=2起直至i=n为止,依次将R[i]插入当前的有序区R[1..i-1]中,生成含n个记录的有序区。
(也就是:每次从数列中取一个还没有取出过的数,并按照大小关系插入到已经取出的数中使得已经取出的数仍然有序。)
通俗的理解是:比如大家打牌的时候,每次抓到牌后放到适合的位置
算法代码:
- #include<stdio.h>
- voidInsertSort(int*a,intlen)
- {
- for(inti=1;i<len;i++)
- {
- intj=i,x=a[i];//x相当于中间变量,用于把key=i的值保存下来,用于后面交换
- while(j&&a[j-1]>x)//如果j为真且前面一个数大于后面一个数的话
- {
- a[j]=a[j-1],j--;//假如第一次排序的话,这边的a[j]=a[1],也即把前一个值大的给后面一个,并且j再减减,如果为0就退出
- }
- a[j]=x;//假如第一次排序的话,这边的a[j]=a[0],然后把x的值赋给它
- }
- }
- intmain(void)
- {
- inta[10];
- while(true)
- {
- for(intn=0;n<10;n++)
- {
- printf("/n第%d数:",(n+1));
- scanf("%d",&a[n]);
- }
- InsertSort(a,10);
- for(inti=0;i<10;i++)//输出排序后的数
- {
- printf("%d",a[i]);
- }
- }
- }
插入算法图示:
冒泡排序:
冒泡排序的基本思想:将被排序的记录数组R[1..n]垂直排列,每个记录R[i]看作是重量为R[i].key的气泡。根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R:凡扫描到违反本原则的轻气泡,就使其向上"飘浮"。如此反复进行,直到最后任何两个气泡都是轻者在上,重者在下为止。
(也即:分为若干趟进行,每一趟排序从前往后比较每两个相邻的元素的大小(因此一趟排序要比较n-1对位置相邻的数)并在每次发现前面的那个数比紧接它后的数大时交换位置;进行足够多趟直到某一趟跑完后发现这一趟没有进行任何交换操作(最坏情况下要跑n-1趟,这种情况在最小的数位于给定数列的最后面时发生)。事实上,在第一趟冒泡结束后,最后面那个数肯定是最大的了,于是第二次只需要对前面n-1个数排序,这又将把这n-1个数中最小的数放到整个数列的倒数第二个位置。这样下去,冒泡排序第i趟结束后后面i个数都已经到位了,第i+1趟实际上只考虑前n-i个数(需要的比较次数比前面所说的n-1要小)。这相当于用数学归纳法证明了冒泡排序的正确性:实质与选择排序相同。)
通俗的说:在排队时,按个子高的和个子矮的进行比较,两两进行比较
代码实现:
- #include<stdio.h>
- voidBubbletSort(int*a,intlen)//*a传进来的数组len为数组的长度
- {
- intm;
- for(boolbSwap=true;bSwap;len--)
- {
- bSwap=false;//当下面不满足时退出循环
- for(intj=1;j<len;j++)
- {
- if(a[j-1]>a[j])//交换值
- {
- m=a[j];
- a[j]=a[j-1];
- a[j-1]=m;
- bSwap=true;
- }
- }
- }
- }
- intmain(void)
- {
- inta[10];
- while(true)
- {
- for(intn=0;n<10;n++)
- {
- printf("/n第%d数:",(n+1));
- scanf("%d",&a[n]);
- }
- BubbletSort(a,10);
- for(inti=0;i<10;i++)//输出排序后的数
- {
- printf("%d",a[i]);
- }
- }
- }
冒泡演示图:
大家是不是想,选择排序和冒泡排序差不多哈,那他们的区别是哪呢?
冒泡算法,每次比较如果发现较小的元素在后面,就交换两个相邻的元素。而选择排序算法的改进在于:先并不急于调换位置,先从A[1]开始逐个检查,看哪个数最小就记下该数所在的位置P,等一躺扫描完毕,再把A[P]和A[1]对调,这时A[1]到A[10]中最小的数据就换到了最前面的位置。所以,选择排序每扫描一遍数组,只需要一次真正的交换,而冒泡可能需要很多次。比较的次数是一样的。
一般是选择排序的平均时间复杂度比冒泡排序的稍低:
.................................若大家有什么有关问题可以提出,谢谢!。。。。