三种常用的插入排序算法--直接插入排序、二分插入排序、希尔排序

来源:互联网 发布:php urlencode 在线 编辑:程序博客网 时间:2024/04/29 08:24

本文介绍三种常用的插入排序算法:

1、直接插入排序算法 复杂度o(n^2)

2、二分插入排序算法(在直接插入排序的基础上使用二分查找优化了插入点的查找效率) 最好o(nlog2(n)) 最差o(n^2)

3、希尔排序算法(利用直接插入排序的一些特点设计的一种排序算法) 大约为o(n^1.3)


下面用java代码来说明思路

1、直接插入排序:

public class Ranker {    //直接插入排序 稳定 复杂度o(n^2) 只需要一个元素的辅助空间用于交换 因此也称为原地(In Place)排序算法    private static void DirectlyInsertSort(int[] arr){        /*         * 对n个元素 由n-1次排序组成,第i趟是将第i+1个元素个元素插入到前面的i个元素中去         * 第i趟完成之后前i+1个元素都是有序的         * */        int i = 0 , j = 0;        for(i = 1; i<arr.length ; i++){//从第1个元素开始一趟一趟地插入元素 第i趟插入之后 要保证前i个元素有序            int temp = arr[i];//待插入元素            for(j = i - 1; j >= 0 && arr[j] > temp ; j--){//第i个元素temp与前面元素进行比较直到比到头或者找到一个元素比他小                arr[j+1] = arr[j];//如果arr[j]比temp大,就一直往后移 直到找到一个合适第i个元素的位置            }            arr[j+1] = temp;//找到了相应的位置j+1 放进去 因为第j号元素不满足arr[j]>temp 所以放在arr[j+1]        }    }}

原理上就是对n个元素进行n-1次排序,第i趟将第i+1个元素插入到前面的i个元素中去,第i趟完成之后保证前i+1个元素都是有序的,是稳定的排序算法,复杂度o(n^2)。


2、二分插入排序算法:

public class Ranker{    private static void BinaryInsertSort(int[] arr){        /*         * 和直接插入思路基本一致 只不过是用二分法来找第i+1个元素的插入位置 left就是这个元素需要放入的位置         * */        int left,right,mid = 0,i,j;        for( i = 1; i<arr.length ; i++ ){//从第1个元素开始一趟一趟地插入元素 第i趟插入之后 要保证前i个元素有序            int temp = arr[i];//待插入元素            left = 0;//查找范围左端            right = i-1;//查找范围右端            while(left<=right){//只要left不要出现在right右端 算法都可以继续                mid = (left+right)>>1;//找到left和right的中间点                if(arr[mid]>temp)                    right = mid - 1;//缩小查找范围到[left,mid-1]                else                    left = mid + 1;//缩小查找范围到[mid+1,right]            }//循环结束时left出现在了right的右边 这个时候[0,right]是比temp小的,而[left,i]是比temp大的数             for( j = i-1 ; j >= left ; j-- ){                arr[j+1] = arr[j];//将比temp大的元素统统往后移一位            }            arr[left] = temp;//在arr[left]这个地方放下temp元素即可        }    }    }

这个的思路和直接插入排序思路大体一致,关键在于在第i趟插入元素的时候,查找应该插入的位置的时候使用了二分法进行查找。


3、希尔排序算法:

public class Ranker{    //希尔排序 利用直接插入排序的一些特点做出了改进 复杂度大约在o(n^1.3) 不稳定    public static void ShellSort(int[] arr){        /*         * 将待排序列划分为若干子序列分别进行直接插入排序 待整个序列的数据基本有序后,再进行一次直接插入排序         * 相当于每一次排序之后都要缩小子序列的增量         * */        int d = arr.length >> 1;//增量 初始值为数组长度的一半        while(d>=1){//增量小于1退出 注意等号 d=1的时候仍然要进行排序 而且是最后一次排序            for(int k = 0; k<d ; k++){//遍历所有子序列                for( int i = k+d ; i<arr.length ;i+=d){ //对每个子序列直接插入                    int temp = arr[i];//存放这个子序列的这次插入的第i个元素                    int j = 0;                    for(j = i - d ;j >= k && arr[j] > temp ; j-=d){                        arr[j+d] = arr[j];                    }                    arr[j+d] = temp;//找到temp适合的位置 放下这个元素                }            }            d >>=1;//较小增量 减为上次的一半        }    }}

希尔排序算法是利用直接插入排序算法特点做出的一些改进,将整个序列分成若干个子序列分别进行直接插入排序,逐渐减小每个子序列的增量,直到增量等于1,使得整个序列逐渐趋于有序,最后当增量等于1的时候对整个基本有序的序列进行排序,整个算法复杂度大约在o(n^1.3)

阅读全文
1 0
原创粉丝点击