lionel chang

导航

内部排序总结(一)插入排序

所谓内部排序是指在内存中的排序,而外部排序则是待排数据过大以至于内存中一次性不能容纳全部记录,排序过程中需要对外存进行访问。

根据所依据的原则,可以将内排分为插入排序,交换排序,选择排序,归并排序,基数排序五类。

以下将对每种排序方法从算法的基本思想,时间复杂度,空间复杂度,稳定性上进行讨论。

其中稳定性是指如果按照某种排序算法排序后,两个关键字相同的记录的顺序不发生变化,则这种排序算法是稳定的;否则,不稳定。

一。插入排序

1.直接插入排序

是最简单的排序算法。每次将待插入数据插入到已经排序好的有序表中。

i.空间复杂度

 因为只用到arr[0],i,j这三个辅助空间,所以空间复杂度为O(1)。

ii.时间复杂度

当所有数据都按顺序排序,比较次数为len-2,移动次数为0,这是最好的时间复杂度;

当所有数据都按逆序排序,比较次数为len-2,移动次数为(len-1)*len/2,这样达到最坏的时间复杂度。

所以,直接插入的时间复杂度为O(N^2)

iii.稳定性

直接插入并不改变关键字相同的记录的顺序。所以是稳定的。

#include<stdio.h>
#define NO_NUM 0 ///arr[0]中不能存放待排序的数据。作用有2点:1,保存待排数据,2,防止数组越界
void insertSort(int arr[],int len)
{
///升序
        int i,j;
        for(i=2;i<len;i++)
                if(arr[i]<arr[i-1])///若待排数据已经满足升序,则进行下一次循环
                {   
                        arr[0]=arr[i];
                        j=i-1;
                        while(arr[0]<arr[j])
                        {   
                                arr[j+1]=arr[j];
                                j--;
                        }   
                        arr[j+1]=arr[0];//arr[j+1]就是要插入的位置
                }   
}
int main(void)
{
        int i;
        int arr[8]={NO_NUM,49,38,65,97,76,13,27};
        insertSort(arr,8);
        for(i=1;i<8;i++)
        {   
                printf("%d  ",arr[i]);
        }   
        printf("\n");
}
2.折半插入排序

与直接插入整体思路相同,都是在有序表中一边后移,一边查找插入位置,找到后插入数据。基本步骤是:查找(后移)---插入;

只不过折半插入对查找进行了优化,采用折半查找插入位置。

时间复杂度,空间复杂度,稳定性都没有发生变化。

void binInsertSort(int arr[],int len)
{
        int i,j;
        int low,high,mid;
        for(i=2;i<len;i++)
                if(arr[i]<arr[i-1])
                {   
                        arr[0]=arr[i];
                        low=1;high=i-1;
                        while(low<=high)
                        {   
                                mid=(low+high)/2;
                                if(arr[i]<arr[mid])
                                        high=mid-1;
                                else
                                        low=mid+1;
                        }   
                        for(j=i-1;j>=high+1;j--)
                                arr[j+1]=arr[j];
                        arr[high+1]=arr[0];
                }   
}

3.希尔排序

通过前面对直接插入排序的分析,可以知道以下两点:

i.当待排序数组是”正序“时,就只要比较操作,不需要移动数组元素,时间复杂度由O(N^2)变为O(N)

ii.当n值很小时,插入效率比较高。

希尔排序利用以上两点:对数组分多次进行直接插入排序,每次待排数据都比较少。待排数据之间有一定的间隔,这个间隔是由delta[]数组决定的。等到最后一次排序时,就是一个间隔为1的直接插入排序,这时要移动的次数将大大减少。

必须注意一下几点:

i。各间隔数不能互相整除;最后一次排序间隔必须为1。

ii.arr[0]只能用于存放数据,不能起到防止数组越界的作用。

void shellInsert(int arr[],int len,int d)
{
        int i,j;
        for(i=d+1;i<len;i++)
        {   
                if(arr[i]<arr[i-d])
                {   
                        arr[0]=arr[i];
                        j=i-d;
                        while(arr[0]<arr[j]&&j>0)
                        {   
                                arr[j+d]=arr[j];
                                j-=d;
                        }   
                        arr[j+d]=arr[0];
                }   
        }   
}
void shellSort(int arr[],int len,int delta[],int n)
{
        int i;
        for(i=0;i<n;i++)
                shellInsert(arr,len,delta[i]);
}
i.时间复杂度,空间复杂度:

希尔排序的时间复杂度的分析与它的间隔数组有关系。但是空间复杂度仍是O(1),

ii。稳定性:

希尔排序是不稳定的。例如{2,4,1,(2)},采用间隔数组为{2,1}排序后会变为{1,(2),2,4}



参考:

《数据结构(c语言版)》              严蔚敏,吴伟民著

内部排序算法小结


《=======================完结======================================》

posted on 2012-08-24 12:50  woshizyl  阅读(146)  评论(0编辑  收藏  举报