插入排序法

每一次将一个待排序的元素,按照其排序码的大小,插入到前面已经排好序的一组元素的合适位置上去,直到元素全部插完为止。

这里其实是把一组元素看成两组,第一组是已经排好序的,而另一组就是无序的。第一次比较的时候,第一个元素被看为一组已序的,第二个元素往后就被看做是无序的。每次都用无序组的第一个元素与有序组的元素从后往前依次比较,当找到合适的位置的时候,就把它安插进去。

下图就是插入排序的部分过程图。当end>=0并且array[key]<array[end]的时候,才会进入while循环。否则,key就前进一步,因为array[key]=array[i],end=i-1,所以end也会前进一步。在进行到第三步的时候进入到了while循环中,array[key]和array[end]的值交换了(key=i,end=i-1,所以key=end+1),但是end和key所在的位置下标没变,但是直叫唤之后并不能保证前面的顺序就是按照升序或者降序来的(本文中是升序),所以,要把key和end的位置向前一步继续比较,最明显的例子就是当end指向7,key指向0的时候。

#include <stdio.h>
#include <assert.h>
#include <windows.h>

void PrintArray(int* array, int size)
{
    int i = 0; 
    for(; i < size; i++)
        printf("%d ", array[i]);

    printf("\n");
}

void Swap(int* pLeft, int* pRight)
{
    int temp = 0;
    assert(pLeft);
    assert(pRight);

    temp = *pLeft;
    *pLeft = *pRight;
    *pRight = temp;
}

void InsertSort(int* array, int size)
{
    int i = 1;
    for(; i < size; i++)
    {
        int key = array[i];//标记array[1],也就是第二个元素,第一次比较的时候,他是无序数组的第 
                           //一个元素
        int end = i - 1;//这里的end标记的是已序数组中的最后一个元素。第一次比较的时候,他是        
                        //array[0]

        while(end >= 0 && key < array[end])//end>=0的含义是:由于是从后往前比较的,每比一次, 
                                           //若没有找到合适位置,end标记就向前走一步,向前走的 
                                           //最后一步就是array[0]的地方;key < array[end]的 
                                           //含义是用无序数组的第一个元素与有序数组从后往前进 
                                           //行比较,每次比较一个元素
        {
            array[end+1] = array[end];//加入满足上面的条件,每次把比较之后的元素向后挪一个位 
                                      //置,由于array[end+1]已经被key标记,所以没有错误。
            --end;//每比一次,end标记往前走一个。因为没满足条件,就去和已序组的倒数第二个元素相 
                  //比,每次就向前走一个,直到找到比自己小的才停下来。就插在这个比自己小的元素之 
                  //后
        }
        array[end+1] = key;//因为是找到比自己小的元素的时候才停下来的,这时候end也在标记着这个 
                           //比key小的元素,而可以要插在array[end]之后,所以,把key放在 
                           //array[end+1]的位置上
    }
}

void InsertSort_OP(int* array, int size)//插入排序的优化算法,与二分查找相似
{
    int i = 1;
    for(; i < size; ++i)
    {
        int key = array[i];
        int begin = 0;
        int end = i - 1;

        while(begin < end)
        {
            mid = begin + ((end-begin)>>1);
            if(key >= array[mid])
                begin = mid+1;
            else
                end = mid-1;
        }
        end = i-1;
        while(end >= begin)
        {
            array[end+1] = array[end];
            --end;
        }

        array[begin] = key;
    }
}

void TestSort()
{
    int array[] = {2, 5, 4, 9, 3, 6, 8, 7, 1, 0};
    PrintArray(array, sizeof(array)/sizeof(array[0]));
    InsertSort(array, sizeof(array)/sizeof(array[0]));
    PrintArray(array, sizeof(array)/sizeof(array[0]));
}

int main()
{
    TestSort();
    system("pause");
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值