排序算法_C++(一)插入排序之直接插入排序

本文介绍排序算法系列的第一篇——直接插入排序。通过实例详细解释了直接插入排序的工作原理,包括如何遍历无序数组并将其元素插入有序表。使用C++在VS2008下实现,讨论了不同输入情况下比较和移动次数,并指出其时间复杂度为O(n^2),是一种稳定的排序方法。
摘要由CSDN通过智能技术生成

        排序算法主要分为:插入排序,选择排序,交换排序,堆排序,基数排序等。本文想将这些排序写成一个系列,算法是按照自己的思路写的,没有把它作为教材的意图。水平一般,力图说的直白,易懂。

        首先从插入排序写,第一篇是直接插入排序。

        直接插入排序的思想简单说一下。将一个无序的数组a[n]看成两部分:有序表和无序表,通常是讲第一个元素a[0]作为有序表,a[1,..,n-1]是无序的。

排序开始:从i = 1,...n-1遍历,首先比较a[1] 与a[0]的大小(递增排列)a[1]>a[0],说明把a[1]从无序表中放入有序表中时,有序表内元素不需要移动,有序表变成{a[0],a[1]}。如果a[1] < a[0],说明有序表的元素应该是{a[1],a[0]},这就需要移动(大数往后移动,小数往前站),将a[1]存入临时变量,把a[0]放入a[1]的位置(a[0]往后撤一步),然后把临时变量里存的a[1]放到a[0]中,第一次遍历结束。红色表示元素是有序表中的元素,黑色表示是无序表的元素。

             i              0        1        2        3        4        5

       初始序列     21       25     3     *25    16       08

       第一趟         21       25     3     *25    16       08

        然后从无序表中拿出a[2],跟有序表中的元素比较,倒着比较,先跟a[1]比较,如果a[2]>a[1],说明有序表中的元素不需要移动,有序表变成{21,25,49},如果a[2]小于a[1],说明,a[2]应该放在a[1]的前边,将a[2]放入临时变量,a[1]后移一位,此时是否立即将a[2]放入a[1]空出来的位置里呢,这还要看a[2]和a[0]孰大孰小,如果a[2]>a[0],直接将a[2]放入a[1]的位置即可,a[0]后移。如果a[2]<a[0],则a[0]需要后移一位,然后将a[2]放入空位。

           i               0        1        2        3        4        5

        第二趟       3        21     25     *25      16       08

        第三趟从无序表中拿出a[3](*25),首先跟a[2](25)比较,因为惯例上a[3]<a[2]的时候才会将a[2]后移,如果a[3]>=a[2],则无需移动,这既减少移动次数,还保证了数据的稳定性。

          i                0        1        2        3        4        5

    第三趟            3        21      25    *25      16        08

第四趟从无序表中取出a[4]和有序表中的数据倒序比较,小于a[3],a[2],a[1],所以吧a[4]存入临时变量,把a[3],a[2],a[1],以此后移一位,a[4]>a[0]因此a[0]无需移动,a[4]插入a[1]的位置即可。

        i                0        1        2        3        4        5

    第四趟          3       16      21      25     *25       08

同理,第五趟,拿无序表中的a[5]与有序表中的元素倒序比较,小于a[4],a[3],a[2].a[1],则将这四个元素依次后移,a[5](08)>a[0](3),a[0]不动,a[5]存入a[1]结束。

      i                0        1        2        3        4        5

第五趟            3       16      21      25    *25       08

                       3        16     21     25     *25                  08——>存入临时变量,a[4],a[3],a[2],a[1]依次后移

        数组大小是6(n),排序趟数是5(n-1).外层循环i从1开始到n-1,内层循环j是从i-1到0,同时还要比较a[i]的值与它前面的有序表的值得大小。

在vs2008 下c++写的

1、新建类class Sort   "Sort.h"

#pragma once

typedef struct node{
	int key;
}DataType;

typedef struct {
	DataType *elem;
	int maxSize;
	int num;
}DataList;

class Sort
{
public:
	Sort(void);
	~Sort(void);
	void insertSort(DataList & L); //直接插入排序 想简单的话,参数直接写成 void(insertSort(int arr[], int n);
};


2、方法实现文件  ”Sort.cpp“

#include "StdAfx.h"
#include "Sort.h"

Sort::Sort(void)
{
}

Sort::~Sort(void)
{
}

void Sort::insertSort( DataList & L )
{
	DataType temp;
	int i = 0, j = 0;

	for(i = 1; i < L.num; i++)  // 第一层循环从i=1...n-1;
	{
		if (L.elem[i].key < L.elem[i-1].key)                 // 每次从无序表中拿出一个元素a[i]跟有序表的最后一个元素比较,如果大于有序表的最后一个                                                                     //<span style="font-family: Arial, Helvetica, sans-serif;">元素,则无需移</span><span style="font-family: Arial, Helvetica, sans-serif;">动,本次循环结束,a[i]成为有序表的最后一个元素。否则</span>
			temp.key = L.elem[i].key;                     //将a[i]存入临时变量temp中。

			for(j = i-1; j >= 0 && L.elem[j].key > temp.key; j-- )  //用a[i]即temp依次跟有序表[0,...,i-1]中的元素倒序比较。如果temp小于有序
			{
				L.elem[j+1] = L.elem[j];                        //表中的元素,则将有序表中的元素后移一位。知道temp遇到比他小的元素,
			}
			L.elem[j+1] = temp;                                     //无需移动,将temp放入空位即可。
		}
	}
}


分析:直接插入排序主要有两个动作:比较和移动。

    如果原始列表是有序的,这是最好情况,只需n-1次比较即可O(n)。移动次数为0。

    如果原始列表是逆序的。则是最坏情况,需要n(n-1)/2次比较O(n^2)。移动次数约(n^2)/2(即O(n^2))。

    平均的时间复杂度是O(n^2)。

    是稳定的排序方法。
    辅助空间O(1)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值