插入排序

本文详细介绍了插入排序算法的工作原理及其实现过程。通过示例展示了如何逐步将无序数组转化为有序数组,同时分析了该算法的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

输入:N个数,<a1,a2,a3,a4....an>

输出:输出序列为一个有序排列<b1,b2,b3....bn>   (b1 <= b2<=b3....<=bn 或者 b1>=b2>=b3...>=bn>

要求:在过程中,这N个数存储在长度为N的数组A[n]中,并且只允许有常数个数字储存在数组之外,也就是说对这N个数实现就地排序。下边的算法以升序为例介绍。

算法:假设我们现在有一个排好序的数组,现在需要将一个元素插入到这个排好序的数组中,那么我们需要找到这个要插入的位置,然后依次的将数据进行移动。插入排序正是用到了这种思想。一个元素必定是有序的,那么我们选取关键元素(即要插入有序数组的当前元素)为第二个元素,即key=A[1];此时我们要比较key与A[0]的大小,来确定key需要插入到A[0]的位置还是A[1]的位置,如果key比A[0]大的话,那么要实现升序就应当将其放置在A[1]的位置;反之,就应当位于A[0]的位置。下一次插入就要选取key为第三个元素......依照此规则,直到插入完毕这中间的所有元素为止。

代码:

/*插入排序
输入:n个数<a1,a2,a3...an>
输出:一个新排列<a1',a2',...an'>
要求:数据存放在一个数组中,在排列的过程中,至多有常数个数据存储在数组外,
      当排好之后,所有数字都存放在数组中。
时间:2014年4月20日
*/
#include<iostream>
using namespace std;
void insertSort(int A[],int n)
{
    int j;
    int i;
    int key;
    for(j=1;j<n;j++)
    { 
        if(A[j]< A [j-1])
        {            
        
        key = A[j];
        i = j-1;
        while(i >=0 && A[i]>key)
        {
            A[i+1]=A[i];
            i--;
        }
        A[i+1]=key;
        }
    }
}
int main()
{
    cout <<"您将为几个整数进行排序?"<<endl;
    int n;
    cin >> n;
    int * A = new int[n];
    cout<<"输入数组"<<endl;
    for(int i = 0 ;i < n ;i++)
    {
        cin >> A[i];
    }
    //int A[6] = {2,3,34,2,18,1};
    insertSort(A,n);
    int i;
    for(i = 0;i<n;i++)
    {
       cout << A[i]<<"  ";
    }
    delete A[];
    return 0;
}

A[6]=(38,47,65,11,22,33)

第一趟:key = 38  

47和38比较不用移动

第二趟:key = 38

65和47比较不用移动

第三趟:key = 11

11  38  47 65

第四趟:key = 22

11 22 38 47 65 

第五趟:key = 33

11 22 33 38 47 65

直接插入排序算法简洁,容易实现,那么它的效率如何呢?

首先从看见上来看,只需要多增加一个保存记录的空间,可以另外设置一个变量来保存或者直接在数组中增加一个哨兵元素A[0]使其直接等于目标排序元素即可。

从时间来看,排序的关键就是关键字的大小和移动记录。最好的情况就是数组已经按照顺序排列好,那么即可实现0次移动以及n-1次比较。最坏的情况就是倒序,第i躺要比较i-1次要移动i-1个单元。

综合最好和最坏的情况,直接插入排序算法的时间复杂度为O(N^2)。

在进行插入排序时,除了逐个查找位置之外还可以采用折半查找找位置,这样可以减少比较的次数但是并不能减少移动的次数,不能减少时间复杂度。若想要减少移动次序,则要考虑K-路插入排序即与归并排序方法类似,建立多个辅助数组,然后分别排序之后,进行有序数组的归并。



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值