暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

数据结构-插入排序-希尔排序-快速排序

两个菜鸟程序猿 2020-02-14
156


一、插入排序(Insertion Sort)这个是直接插入排序
基本思想:
在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。
过程:

平均时间复杂度:O(n^2)
代码的实现:
 public static void insert_sort(int array[],int lenth){
int temp;
for(int i=0;i<lenth-1;i++){
for(int j=i+1;j>0;j--){
if(array[j]<array[j-1]){
temp=array[j-1];
array[j-1]=array[j];
array[j]=temp;
}else{ //不需要交换
break;
}
}
}
}


如果是二分插入排序,和这个相比,仅仅是我们在找到插入数据位置的方法是不同的,采用的是二分查找。

二、希尔排序(Shell Sort)
前言:
数据序列1: 13-17-20-42-28 利用插入排序,13-17-20-28-42. Number of swap:1;
数据序列2: 13-17-20-42-14 利用插入排序,13-14-17-20-42. Number of swap:3;
如果数据序列基本有序,使用插入排序会更加高效。
基本思想:
在要排序的一组数中,根据某一增量分为若干子序列,并对子序列分别进行插入排序。
然后逐渐将增量减小,并重复上述过程。直至增量为1,此时数据序列基本有序,最后进行插入排序。(也就是说步的大小为N的插入排序)
过程:

时间复杂度:O(n^(1.3—2))
代码的基本实现:
public static void shell_sort(int array[],int lenth){


int temp = 0;
int incre = lenth;


while(true){
incre = incre/2;


for(int k = 0;k<incre;k++){ //根据增量分为若干子序列


for(int i=k+incre;i<lenth;i+=incre){


for(int j=i;j>k;j-=incre){
if(array[j]<array[j-incre]){
temp = array[j-incre];
array[j-incre] = array[j];
array[j] = temp;
}else{
break;
}
}
}
}


if(incre == 1){
break;
}
}
}


三、快速排序(Quicksort)
基本思想:(分治)
先从数列中取出一个数作为key值;
将比这个数小的数全部放在它的左边,大于或等于它的数全部放在它的右边;
对左右两个小数列重复第二步,直至各区间只有1个数。
辅助理解:挖坑填数

算法的基本过程:
初始时 i = 0; j = 9; key=72
由于已经将a[0]中的数保存到key中,可以理解成在数组a[0]上挖了个坑,可以将其它数据填充到这来。
从j开始向前找一个比key小的数。当j=8,符合条件,a[0] = a[8] ; i++ ; 将a[8]挖出再填到上一个坑a[0]中。
这样一个坑a[0]就被搞定了,但又形成了一个新坑a[8],这怎么办了?简单,再找数字来填a[8]这个坑。
这次从i开始向后找一个大于key的数,当i=3,符合条件,a[8] = a[3] ; j-- ; 将a[3]挖出再填到上一个坑中。
数组:72 - 6 - 57 - 88 - 60 - 42 - 83 - 73 - 48 - 85
0 1 2 3 4 5 6 7 8 9

此时 i = 3; j = 7; key=72
再重复上面的步骤,先从后向前找,再从前向后找。
从j开始向前找,当j=5,符合条件,将a[5]挖出填到上一个坑中,a[3] = a[5]; i++;
从i开始向后找,当i=5时,由于i==j退出。
此时,i = j = 5,而a[5]刚好又是上次挖的坑,因此将key填入a[5]。
数组:48 - 6 - 57 - 88 - 60 - 42 - 83 - 73 - 88 - 85
0 1 2 3 4 5 6 7 8 9

可以看出a[5]前面的数字都小于它,a[5]后面的数字都大于它。因此再对a[0…4]和a[6…9]这二个子区间重复上述步骤就可以了。
数组:48 - 6 - 57 - 42 - 60 - 72 - 83 - 73 - 88 - 85
0 1 2 3 4 5 6 7 8 9
平均时间复杂度:O(N*logN)
代码的实现:
public static void quickSort(int a[],int l,int r){
if(l>=r)
return;


int i = l; int j = r; int key = a[l];//选择第一个数为key


while(i<j){


while(i<j && a[j]>=key)//从右向左找第一个小于key的值
j--;
if(i<j){
a[i] = a[j];
i++;
}


while(i<j && a[i]<key)//从左向右找第一个大于key的值
i++;


if(i<j){
a[j] = a[i];
j--;
}
}
//i == j
a[i] = key;
quickSort(a, l, i-1);//递归调用
quickSort(a, i+1, r);//递归调用
}
key值的选取可以有多种形式,例如中间数或者随机数,分别会对算法的复杂度产生不同的影响。

更多的内容请访问:https://blog.breakpoint.vip/

喜欢就在看吧!!!


文章转载自两个菜鸟程序猿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论