插入排序(一)—直接插入排序

    最近复习《数据结构》,复习到了内部排序,就把书上的算法用代码实现了。课本用的是严慧敏老师主编的那本。插入排序算法算法思想很简单,就是从第二个元素开始把每个元素逐个插入到前面已排好序的有序表中,渐增的实现排序。下面用一个伪代码来理解一下:

InsertSort(A)
for m← 2 to length[A]
   do key ← A[m]
      n ← m-1
      while n>0 and A[n]>key
	    do A[n+1] ← A[n]
	       n ← n-1
   A[n+1] ←key

     这个算法的时间复杂度是O(n^2)。时间消耗在了元素间的比较和移动上了,如果能减少元素间的比较或者是元素的移动那么就能提高了。后面的文章中用介绍用于减少元素间比较次数的折半插入排序;和用于减少元素的移动的2-路插入排序;以及不需要移动元素的表插入排序

     根据上面的伪代码很容易写出源代码,就像下面的这样:

//直接插入排序
//参数 numbers 是:指向要排序数的数组
//宏定义 COUNT 是:数组中元素的个数
void DirectInsertSort(int* numbers)
{
	int m,n=0;
	for(m=2;m<COUNT;m++)
	{
		int key = numbers[m];
		n=m-1;
		while( n>0 && numbers[n]>key)
		{
			numbers[n+1] = numbers[n];
			n--;
		}
		numbers[n+1] = key;	
	}
}
如果把存储数的数组的第一个元素用来当哨兵的话,很容易把函数改成如下的形式:

//直接插入排序
//参数 numbers 是:指向要排序数的数组
//宏定义 COUNT 是:数组中元素的个数
void DirectInsertSort(int* numbers)
{
	int i,j=0;
	for(i=2;i<COUNT;i++)
	{
		if(numbers[i] < numbers[i-1])
		{
			// numbers[0] 当哨兵
			numbers[0] = numbers[i];
			for(j=i-1; numbers[0]<numbers[j];j--)
			{
				numbers[j+1] = numbers[j];
			}
			numbers[j+1] = numbers[0];	
		}
	}
}

哨兵元素的好处:
从上面两段代码就能看出有了哨兵的好处:每次不必判断n>0了,也就是说不用检查数组是否越界了。这在很少数的排序中看不出效果,但当要排列的数很多的时候,

性能就能比较出来了。

下面贴出这次的整个代码,接下来几篇会介绍折半插入排序、2-路插入排序和表插入排序:

#include <iostream>
using namespace std;

#define COUNT 9

//输出排序后的数组
void PrintValues(int* numbers)
{
	for(int i=1;i<COUNT;i++)
	{
		cout<<numbers[i]<<"  ";
	}
}

//直接插入排序
//参数 numbers 是:指向要排序数的数组
//宏定义 COUNT 是:数组中元素的个数
void DirectInsertSort(int* numbers)
{
	int m,n=0;
	for(m=2;m<COUNT;m++)
	{
		int key = numbers[m];
		n=m-1;
		while( n>0 && numbers[n]>key)
		{
			numbers[n+1] = numbers[n];
			n--;
		}
		numbers[n+1] = key;	
	}

/*
	int i,j=0;
	for(i=2;i<COUNT;i++)
	{
		if(numbers[i] < numbers[i-1])
		{
			numbers[0] = numbers[i];
			for(j=i-1; numbers[0]<numbers[j];j--)
			{
				numbers[j+1] = numbers[j];
			}
			numbers[j+1] = numbers[0];	
		}
	}
*/

}

int main(int argc, char *argv[])
{
	//第一个元素当哨兵位,不用。
	int values[COUNT] = {0, 49, 38, 65, 97, 76, 13, 27, 49};
	DirectInsertSort(values);
	PrintValues(values);
	return EXIT_SUCCESS;
}

结果如下图:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Naruto

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值