a[j+1]=a[j];
j--;
}
a[j+1]=temp;/*插入*/
}
}
二.
直接选择排序 基本思想:
每次从无序数组中选出一个最小的出来,放到已排好序的数组的最后。
public static void SELECTSORT(int[] R)
{
for (int i = 0; i < R.Length-1; i++)
{
int index = i;
for (int j = i + 1; j < R.Length; j++)
{
if (R[j] < R[index])
{
index = j;
}
} //交换R[i]和R[index]
if (index !
= i)
{
int t = R[i]; R[i] = R[index]; R[index] = t;
}
}
}
插入排序
基本思想:
首先将数组的第一个数sortArray[0]看成是有序的,然后从第二个元素开始和它前面的元素进行比较,如果比前面的某一个数大,就交换。
由于前面的元素是有序的,所以就使有序元素的个数逐渐增大,直到等于n。
public void Sort(int[] sortArray) {
int j = 0;
int key = 0; // key为哨兵
for (int i = 1; i < sortArray.Length; i++) //[0..i-1]已经排好的有序列 {
if (sortArray[i] < sortArray[i - 1]) {
key = sortArray[i]; j = i - 1;
while (j >= 0 && key < sortArray[j]) //当sortArray[i] ≥sortArray[j] 时终止 {
sortArray[j + 1] = sortArray[j]; j--; }
sortArray[j + 1] = key; //插入到j的后面 } } }
冒泡排序
基本思想:
两两比较待排序的数,发现反序时交换,直到没有反序为止。
public static void BubbleSort(int[] R) {
for (int i = 0; i < R.Length - 1; i++) {
bool noswap = true;
for (int j = 0; j < R.Length - 1-i; j++) {
if (R[j] > R[j + 1]) {
int temp = R[j]; R[j] = R[j + 1]; R[j + 1] = temp; noswap = false; } }
if (noswap) {
break; } } }
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
正版。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
直接选择排序(StraightSelectionSort)
1、直接选择排序的基本思想
n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果:
①初始状态:
无序区为R[1..n],有序区为空。
②第1趟排序
在无序区R[1..n]中选出关键字最小的记录R[k],将它与无序区的第1个记录R[1]交换,使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
……
③第i趟排序
第i趟排序开始时,当前有序区和无序区分别为R[1..i-1]和R[i..n](1≤i≤n-1)。
该趟排序从当前无序区中选出关键字最小的记录R[k],将它与无序区的第1个记录R[i]交换,使R[1..i]和R[i+1..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
这样,n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果。
2、直接选择排序的过程
对初始关键字为49、38、65、97、76、13、27和49的文件进行直接选择排序的过程【参见动画演示】
3、算法描述
直接选择排序的具体算法如下:
voidSelectSort(SeqListR)
{
inti,j,k;
for(i=1;ik=i;
for(j=i+1;j<=n;j++)//在当前无序区R[i..n]中选key最小的记录R[k]
if(R[j].keyk=j;//k记下目前找到的最小关键字所在的位置
if(k!
=i){//交换R[i]和R[k]
R[0]=R[i];R[i]=R[k];R[k]=R[0];//R[0]作暂存单元
}//endif
}//endfor
}//SeleetSort
/*
冒泡排序基本思想
将n个记录看作按纵向排列,每趟排序时自下至上对每对相邻记录进行比较,若次序不符合要求(逆序)就交换。
每趟排序结束时都能使排序范围内关键字最小的记录象一个气泡一样升到表上端的对应位置,整个排序过程共进行n-1趟,依次将关键字最小、次小、第三小…的各个记录“冒到”表的第一个、第二个、第三个…位置上。
初态第1趟第2趟第3趟第4趟第5趟第6趟第7趟
3812121212121212
2038202020202020
4620382525252525
3846253838383838
7438463838383838
9174384646464646
1291747474747474
2525919191919191*///打印数组voidPrintArray(intarray[],intn)
{inti;for(i=0;iprintf("%d",array[i]);
printf("\n");
}//冒泡排序voidBubbleSort(intarray[],intn)
{inti=0;intj=0;inttemp=0;intflag=0;for(i=0;i{
flag=0;/*本趟排序开始前,交换标志应为假*/for(j=n-1;j>i;j--)/*内循环控制一趟排序的进行*/
{if(array[j]{
temp=array[j];
array[j]=array[j-1];
array[j-1]=temp;
flag=1;/*发生了交换,故将交换标志置为真*/
}
}if(flag==0)/*本趟排序未发生交换,提前终止算法*/break;/*
printf("第%d趟排序结果:
\n",i+1);
PrintArray(array,n);*/
}
}
voidTestBubbleSort()
{intarray[8]={38,20,46,38,74,91,12,25};
BubbleSort(array,8);
PrintArray(array,8);
}
题外话:
在深入学习更多排序算法后和在实际使用情况中,冒泡排序的使用还是极少的。
它适合数据规模很小的时候,而且它的效率也比较低,但是作为入门的排序算法,还是值得学习的
先尝试用最简单的想法去实现排序,以此来比较学习冒泡排序
问题:
设有一数组,其大小为10个元素(intstr[10])数组内的数据是无序。
现在要求我们通过编程将这个无序的数组变成一个从小到大排序的数组(从下标为0开始)
思路:
按照题目的要求,毫无疑问,正确的结果应该就像这样:
12345678910要做到这样,最简单和最直接想到的方法就是进行对比交换。
∙首先,把10个数里最小的个数放到下标为0的位置上(str[0])
∙通过将下标为0的数(str[0])与剩下其余9个数进行对比交换(将较少者放置在下标为0的位置上),就可以得到这10个数最小的那个
∙10个数最小的那位确定后,接下来就要找剩下9个数最小的那个。
∙因为已经确定出一个最小的数,所以就不要动str[0],直接从str[1]开始,与剩下的8个数对比交换,找出9个数中最小的那位放到下标为1(str[1])的位置上
∙继续按照这个思路就可以将这十个数变成有序的(从小到大)的数组
代码:
[cpp]viewplaincopyprint?
1#include
2
3voidswap(int*a,int*b);//交换两个数
4
5intmain()
6{
7intstr[10];
8inti,j;
9//初始化数组为10987654321
10for(i=0;i<10;i++)
11{
12str[i]=10-i;
13}
14//排序,从a[0]开始排,从小到大
15for(i=0;i<10;i++)
16{
17for(j=i+1;j<10;j++)
18{
19if(str[i]>str[j])
20{
21swap(&str[i],&str[j]);
22}
23}
24}
25//将十个数输出
26for(i=0;i<10;i++)
27printf("%d\n",str[i]);
28return0;
29}
30voidswap(int*a,int*b)
31{
32intc;
33c=*a;
34*a=*b;
35*b=c;
36}
这个方法是比较容易想到的实现方法。
但存在不足:
就是本来位于前面的较小数被交换到后面
演示:
开始:
94568327101(下标从左到右分别是0~9)按照上面的程序进行对比交换
第一次:
49568327101
第二次:
49568327101
。
。
。
:
(没有交换)
第五次:
39568427101
第六次:
29568347101
。
。
。
:
(没有交换)
第十次:
19568347102
可以看出,原来较小的数是在前面的,经过一轮的交换后放到后面了
那么怎样解决这个不足呢?
可以使用冒泡排序
什么是冒泡排序呢?
你可以这样理解:
(从小到大排序)存在10个不同大小的气泡,由底至上地把较少的气泡逐步地向上升,这样经过遍历一次后,最小的气泡就会被上升到顶(下标为0),然后再从底至上地这样升,循环直至十个气泡大小有序。
在冒泡排序中,最重要的思想是两两比较,将两者较少的升上去
冒泡排序最坏情况的时间复杂度是O(n²)
代码:
[cpp]viewplaincopyprint?
37#include
38voidswap(int*a,int*b);
39intmain()
40{
41intarray[10]={15,225,34,42,52,6,7856,865,954,10};
42inti,j;
43for(i=0;i<10;i++)
44{
45//每一次由底至上地上升
46for(j=9;j>i;j--)
47{
48if(array[j]49{
50swap(&array[j],&array[j-1]);
51}
52}
53}
54for(i=0;i<10;i++)
55{
56printf("%d\n",array[i]);
57}
58return0;
59}
60voidswap(int*a,int*b)
61{
62inttemp;
63temp=*a;
64*a=*b;
65*b=temp;
66}
一.算法描述
插入排序:
插入即表示将一个新的数据插入到一个有序数组中,并继续保持有序。
例如有一个长度为N的无序数组,进行N-1次的插入即能完成排序;第一次,数组第1个数认为是有序的数组,将数组第二个元素插入仅有1个有序的数组中;第二次,数组前两个元素组成有序的数组,将数组第三个元素插入由两个元素构成的有序数组中......第N-1次,数组前N-1个元素组成有序的数组,将数组的第N个元素插入由N-1个元素构成的有序数组中,则完成了整个插入排序。
以下面5个无序的数据为例:
6527596458(文中仅细化了第四次插入过程)
第1次插入:
2765596458
第2次插入:
2759656458
第3次插入:
2759646558
第4次插入:
2758596465
二.算法分析
平均时间复杂度:
O(n2)
空间复杂度:
O
(1)(用于记录需要插入的数据)
稳定性:
稳定
三.算法实现
从前向后查找的插入排序:
[cpp]viewplaincopy
∙/********************************************************
∙*函数名称:
InsertSort
∙*参数说明:
pDataArray无序数组;
∙*iDataNum为无序数据个数
∙*说明:
插入排序
∙*********************************************************/
∙voidInsertSort(int*pDataArray,intiDataNum)
∙{
∙for(inti=1;i∙{
∙intj=0;
∙while(j
∙j++;
∙
∙if(j
∙{
∙intk=i;
∙inttemp=pDataArray[i];
∙while(k>j)//挪动位置
∙{
∙pDataArray[k]=pDataArray[k-1];
∙k--;
∙}
∙pDataArray[k]=temp;//插入
∙}
∙}
∙}
但楼主发现从后面查找插入的方式,代码复杂程度较低:
[cpp]viewplaincopy
∙/********************************************************
∙*函数名称:
InsertSort
∙*参数说明:
pDataArray无序数组;
∙*iDataNum为无序数据个数
∙*说明:
插入排序
∙*********************************************************/
∙voidInsertSort(int*pDataArray,intiDataNum)
∙{
∙for(inti=1;i∙{
∙intj=i-1;
∙inttemp=pDataArray[i];//记录要插入的数据
∙while(j>=0&&pDataArray[j]>temp)//从后向前,找到比其小的数的位置
∙{
∙pDataArray[j+1]=pDataArray[j];//向后挪动
∙j--;
∙}
∙
∙if(j!
=i-1)//存在比其小的数
∙pDataArray[j+1]=temp;
∙}
∙}
四.算法优化
插入排序中,总是先寻找插入位置,然后在实行挪动和插入过程;寻找插入位置采用顺序查找的方式(从前向后或者从后向前),既然需要插入的数组已经是有序的,那么可以采用二分查找方法来寻找插入位置,提高算法效率,但算法的时间复杂度仍为O(n2)。
[cpp]viewplaincopy
∙//查找数值iData在长度为iLen的pDataArray数组中的插入位置
∙intFindInsertIndex(int*pDataArray,intiLen,intiData)
∙{
∙intiBegin=0;
∙intiEnd=iLen-1;
∙intindex=-1;//记录插入位置
∙while(iBegin<=iEnd)
∙{
∙index=(iBegin+iEnd)/2;
∙if(pDataArray[index]>iData)
∙iEnd=index-1;
∙else
∙iBegin=index+1;
∙}
∙if(pDataArray[index]<=iData)
∙index++;
∙returnindex;
∙}
∙
∙/*********************************