【Data_Structure笔记3】排序算法之插入排序常见的三种算法

/************************************************************************************************************************
文件说明:
        【1】内部排序:是指在排序期间元素全部存放在内存中的排序
		【2】外部排序:是指在排序期间元素无法全部同时存放在内存中,必须在排序的过程中根据要求,不断的在内、外存之间移动的
		         排序
		【3】排序算法的稳定性
		【4】内部排序算法的性能取决于算法的【时间复杂度】和【空间复杂度】,而时间复杂度一般是由【比较】和【移动】的次数来
		         决定的
详细说明:
        【1】插入排序算法
		        (1)直接插入排序
				(2)折半插入排序
				(3)希尔排序(shell sort)
		【2】交换类排序
		        (1)冒泡排序
				(2)快速排序
		【3】选择类排序
		        (1)简单选择排序
				(2)堆排序
		【4】二路归并排序
		【5】基数排序
插入排序:
        【1】插入排序是一种简单直观的排序算法,其基本思想在于每次将一个待排序的记录,按其关键字大小插入到前面已经排好的子
		         序列中,直到全部记录插入完成。
		【2】由插入排序的算法思想可以扩展出三个具体的排序算法:
		        (1)直接插入排序
				(2)折半插入排序
				(3)希尔排序
*************************************************************************************************************************/
#include<iostream>
using namespace std;

/************************************************************************************************************************
函数原型:
        【函数模板】template<typename ElemType>void InsertSort(ElemType arrayT[],int iLength)
		【适用性】【直接插入排序算法】适用于【顺序存储】和【链式存储】的线性表。并且一般适用于记录数较少且基本有序的线性表
函数说明:
        【1】对记录数组arrayT做直接插入排序
		【2】iLength为数组中待排序记录的数目
直接插入排序算法:
        【1】从空间角度来看,直接插入排序算法只需要设置监视哨兵tempT来帮助实现即可。
		【2】从时间角度来看,主要的时间耗费在关键字比较和元素的移动操作上。
		【3】【直接插入排序算法】并不是任意使用的,它比较适用于待排序记录数目较少且基本有序的情形
		       (1)记录数目较少
			   (2)基本有序
		【4】直接插入排序使用【就地排序】
*************************************************************************************************************************/
template<typename ElemType>void InsertSort(ElemType arrayT[],int iLength)
{
	ElemType    tempT;                               //【1】定义一个监视哨兵
	int         j   = 0;
	for(int i=1;i<iLength;i++)
	{
		tempT = arrayT[i];
		j     = i-1;
		while (tempT<arrayT[j])
		{
			arrayT[j+1] = arrayT[j];
			j = j-1;
		}
		arrayT[j+1] = tempT;
	} 
}
/************************************************************************************************************************
函数原型:
        函数模板:template<typename ElemType>void BinSort(ElemType arrayT[],int iLength)
函数说明:
        【1】对记录数组arrayT做【折半插入排序】
		【2】iLength为数组中待排序记录的数目
算法思想:
        【1】从查找算法的讨论中可知,对于【有序的顺序表】进行折半查找,其性能优于顺序查找。所以,可以将【折半查找】的思想
		     应用于在有序的记录中确定插入的位置,相应的排序算法称为【折半插入排序算法】
		【2】采用折半插入排序算法,
		【3】采用折半插入排序算法,可以减少关键字的比较次数。没插入一个元素,需要比较的次数最大为折半判定树的深度
*************************************************************************************************************************/
template<typename ElemType>void BinSort(ElemType arrayT[],int iLength)
{
	ElemType tempT;

	int j    = 0;
	int iLow = 0;
	int iHigh= 0;
	int iMid = 0;

	for(int i=1;i<iLength;i++)
	{
		tempT = arrayT[i];

		iLow  = 0;
		iHigh = i-1;
		while (iLow<=iHigh)
		{
			iMid = (iLow+iHigh)/2;
			if(tempT<arrayT[iMid])
			{
				iHigh = iMid-1;
			}
			else
			{
				iLow = iMid+1;
			}
		}//while

		for(j = i-1;j>=iLow;j--)
		{
			arrayT[j+1] = arrayT[j];
		}
		arrayT[iLow] = tempT;
	}//for i
}
/************************************************************************************************************************
函数原型:
        【函数模板】template<typename ElemType>void BinSort(ElemType arrayT[],int iLength)
		【适用性】希尔排序算法仅适用于当线性表为【顺序存储】的情况
函数说明:
        【1】对记录数组arrayT做【折半插入排序】
		【2】iLength为数组中待排序记录的数目
希尔排序:
        【1】从前面的讲解,不难看出,【直接插入排序算法】适用于【基本有序的排序表】和【数据量不大的排序表】。
		【2】基于这两点。1959年D.L.Shell提出了希尔排序,又称为"缩小增量排序"。
希尔排序的思想:
        【1】先将【待排序表】分割成若干个形如L[i,i+d,i+2d,i+3d,........i+kd]的特殊子表。
		【2】分别直接进行【插入排序】
		【3】当整个表中元素已呈"基本有序"时,再对全体记录进行一次【直接插入排序】
算法性能:
        【1】【适用性】:希尔排序算法仅适用于当线性表为【顺序存储】的情况。
		【2】希尔排序算法的时间复杂度一般认为O(nlogn),在最坏情况下为O(n*n)
*************************************************************************************************************************/
template<typename ElemType>void ShellInsertSort(ElemType arrayT[],int iLength)
{
	for(int d=iLength/2;d>=1;d=d/2)                                 //【1】设置(起始增量;循环条件;艘小增量的规则)
	{
		for(int k=0;k<d;k++)                                        //【2】增量为N,就有N个子序列,遍历所有的子序列
		{
			//===========================================================================================================
			for(int i=k+d;i<iLength;i+=d)                           //【3】对每个子序列进行【插入排序】
			{
				int iTemp = arrayT[i];
				int j     = i -d;
				while (j>=k&&iTemp<arrayT[j])
				{
					arrayT[j+d]=arrayT[j];
					j = j-d;
				}
				arrayT[j+d] = iTemp;
			}//i
			//=============================================================================================================
		}//for k
	}
}
int main(int argc,char* argv[])
{

	int arrayT[15] = {22,32,44,34,56,21,24,345,213,234,245,127,113,119,933};
	//InsertSort<int>(arrayT,15);   
	//BinSort<int>(arrayT,15);
	ShellInsertSort<int>(arrayT,15);
	for(int i=0;i<15;i++)
	{
		std::cout<<arrayT[i]<<std::endl;
	}

	std::system("pause");
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值