八大排序
一:排序分类
二、算法实现(内部排序)
1、插入排序之直接插入排序
排序步骤:
①从第一个元素开始,该元素可以认为已经被排序
②取出下一个元素,在已经排序的元素序列中从后向前扫描
③如果该元素小于前面的元素(已排序),则依次与前面元素进行比较如果小于则交换,直到找到大于该元素的就则停止;
④如果该元素大于前面的元素(已排序),则重复步骤2
重复步骤2~4 直到所有元素都排好序
例:3 4 7 1 5 2 6 9(排成递增序列)
排序过程:i = 1:3 4 7 1 5 2 6 9 (3和4比)
i = 2:3 4 7 1 5 2 6 9 (4和7比)
i = 3:①3 4 1 7 5 2 6 9(1和7比)
②3 1 4 7 5 2 6 9(1 和4比)
③1 3 4 7 5 2 6 9(1和3比)
......
i = 8:1 2 3 4 5 6 7 9
使用直接插入排序的优点是稳定,快速,缺点是:比较次数不一定,比较次数越多,插入点后的数据移动越多,特别是当数据总量庞大的时候,但用链表可以解决这个问题。平均时间复杂度O(n^2),适合于量级小于千的排序。
清单1:
int StraightInsertSort(int s[],int n)
{
int i,j;
int temp;
for(i = 1;i<n;i++)
{
for(j = i; j > 0;j--)
{
if(s[j] < s[j-1])
{
temp = s[j];
s[j] = s[j-1];
s[j-1] = temp;
}
else
break;
}
}
}
2、插入排序之希尔排序
原理:已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。发现当n不大时,插入排序的效果很好。首先取一增量d(d<n),将a[1]、a[1+d]、a[1+2d]……列为第一组,a[2]、a[2+d]、a[2+2d]……列为第二组……,a[d]、a[2d]、a[3d]……列为最后一组以此类推,在各组内用插入排序,然后取d'<d,重复上述操作,直到d=1。
优点:快,数据移动少
缺点:d值不确定,取什么值看经验
希尔排序的时间复杂度为 O(N*(logN)2),适合于中等规模排序
清单2:
int sheelsort(int a[],int n)
{
int k = n / 2;//k是增量
while (k > 0)
{
for (int i = k; i < n; i++)
{
int t = a[i];
int j = i - k;
while (j >= 0 && t < a[j])
{
a[j + k] = a[j];
j = j - k;
}
a[j + k] = t;
}
k /= 2;
}
}
3.选择排序之简单选择排序
①从左至右遍历,找到最小(大)的元素,然后与第一个元素交换。
②从剩余未排序元素中继续寻找最小(大)元素,然后与第二个元素进行交换。
③以此类推,直到所有元素均排序完毕。
有序区,无序区
int selectionsort(int a[],int n)
{
int i,j,temp;
//一趟一趟的找
for(i = 0; i < n;i++)
{
int min = i;
//找最小值,记录位置
for(j = i+1; j < n; j++)
{
if(a[min] > a[j])
min = j;
}
//找到后交换值
temp = a[min];
a[min] = a[i];
a[i] = temp;
}
}
4.堆排序
示例:
5、冒泡排序
一组数据,两两比较,大的放后面,小的放前面,就像冒泡一样,越大的泡会冒到最上面,一趟一趟比较,直到所有数据从小到大依次排列。
算法分析:
①相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。
②平均时间复杂度o(n^2)
清单5:
int Bubblesort(int a[],int n)
{
int i,j,min;
for(j = 1; j < n; j++) //控制排序的执行次数
{
for(i = 0; i < n-j; i++) //控制在一次排序中相邻记录的比较和交换
{
if(a[i] > a[i+1]) //如果前面元素大于后面元素则交换
{
min = a[i+1];
a[i+1] = a[i];
a[i] = min;
}
}
}
}
6、快速排序
快速排序又叫分区交换排序,是目前已知的平均速度最快的一种排序方法。基本思想:从待排序的n个记录中任意选取一个记录Ri(通常选取序列中的第一个记录)做标准,调整序列中各个记录的位置,使排在Ri前面的记录的关键字都小于Ri.key,排在Ri后面的记录的关键字都大于等于Ri.key,我们把这样的一个过程称作一次快速排序。在第一次快速排序过程中,确定了所选取的记录Ri最终在序列中的排列位置,同时也把剩余的记录分成了两个子序列。对两个子序列分别进行快速排序,又确定了两个记录在序列中应处的位置,并将剩余记录分成了四个子序列,如此重复下去,当各个子序列的长度为一时,全部记录排序完毕。
算法分析:
①是一种不稳定的排序方法
②递归形式的快速排序法需要栈空间暂存数据,其空间复杂度为O(n)
③时间复杂度是o(nlgn)
清单6:
int quicksort(int a[],int low,int high)
{
int i,j,temp;
i = low;
j = high;
temp = a[i];
while(i < j)
{
//从右向左找第一个比temp小的元素
while(i < j && temp <= a[j]) //如果满足此条件,即temp的值比a[j]小
j--; //则j向左移动
if(i < j) //当不满足while循环的条件,即找到了一个比temp小的数,只要i<j,
{
a[i++] = a[j]; //将找到的小的数a[j]的值赋给a[i],i = i+1
}
//同理从左向右找第一个比temp大的元素
while(i < j && temp >= a[i]) //如果满足此条件,即temp的值比a[i]大
i++; //则i向右移动
if(i < j) //当不满足while循环的条件,即找到了一个比temp大的数,只要i<j,
{
a[j--] = a[i]; //将找到的大的数a[i]的值赋给a[j],j = j-1
}
a[i] = temp;
//使用递归实现子序列的排序
if(low < i)
{
quicksort(a,low,i-1);
}
if(i < high)
{
quicksort(a,j+1,high);
}
}
}
7、归并排序
8、基数排序
总结:
待续~~