直接插入排序

最简单的排序方法。它的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录增1的有序表。

把n个待排序的元素看成一个有序表和一个无序表,开始时有序表中只有一个元素,无序表中有n-1个元素;排序过程即每次从无序表中取出第一个元素,将它插入到有序表中,使之成为新的有序表,重复n-1次完成整个排序过程。

——————————那一季的银杏叶:https://www.cnblogs.com/snowcan/p/6244128.html

        0.初始状态 3,1,5,7,2,4,9,6(共8个数)

     有序表:3;无序表:1,5,7,2,4,9,6

  1.第一次循环,从无序表中取出第一个数 1,把它插入到有序表中,使新的数列依旧有序

     有序表:1,3;无序表:5,7,2,4,9,6

  2.第二次循环,从无序表中取出第一个数 5,把它插入到有序表中,使新的数列依旧有序

     有序表:1,3,5;无序表:7,2,4,9,6

  3.第三次循环,从无序表中取出第一个数 7,把它插入到有序表中,使新的数列依旧有序

     有序表:1,3,5,7;无序表:2,4,9,6

  4.第四次循环,从无序表中取出第一个数 2,把它插入到有序表中,使新的数列依旧有序

     有序表:1,2,3,5,7;无序表:4,9,6

  5.第五次循环,从无序表中取出第一个数 4,把它插入到有序表中,使新的数列依旧有序

     有序表:1,2,3,4,5,7;无序表:9,6

  6.第六次循环,从无序表中取出第一个数 9,把它插入到有序表中,使新的数列依旧有序

     有序表:1,2,3,4,5,7,9;无序表:6

  7.第七次循环,从无序表中取出第一个数 6,把它插入到有序表中,使新的数列依旧有序

     有序表:1,2,3,4,5,6,7,9;无序表:(空)

——————————那一季的银杏叶:https://www.cnblogs.com/snowcan/p/6244128.html

程序:

//直接插入排序
//升序排序 
#include<stdio.h> 

void InsertSort(int *a,int n) 
{
	int i,j,tmp;
	for(i=1;i<n;i++)
	{
		if(a[i-1]>a[i])
		{
			tmp=a[i];
			j=i;
			while(j&&tmp<a[j-1])
			{
				a[j]=a[j-1];
				j--;
			}
			a[j]=tmp;
		}
	}
} 

int main()
{
	int i;
	int a[]={1,2,8,5,6,9,4,2,7,5};
	int n=sizeof(a)/sizeof(int);
	InsertSort(a,n);
	for(i=0;i<n;i++)
		printf("%d ",a[i]);
	return 0;
}

直接插入排序的时间复杂度是o(n2) ;

 

 

 

 

折半插入排序

由于直接插入排序的前方数据已经基本有序,有时顺序查找很费时。因而产生了“折半”查找的排序。

排序算法——插入排序

——————————来自:百度文库https://wenku.baidu.com/view/0e6dc051a76e58fafab003e1.html

程序:

//折半插入排序
//升序排列
#include<stdio.h>

using namespace std; 

void BInsertSort(int *a,int n)
{
	int i,j,low,high,m,tmp;
	for(i=1;i<n;i++)
	{
		if(a[i]<a[i-1])
		{
			low=0;
			high=i-1;
			tmp=a[i];
			m=(low+high)/2;			
			while(low<high)//最后low==high跳出时,m=low=high 
			{	            //因而总体来说,m最后记录的是插入位置 
				if(tmp<a[m])
					high=m-1;
				else if(tmp>a[m])
					low=m+1;
				else
					break;	
				m=(low+high)/2;
			}
			for(j=i;j>m;j--)
				a[j]=a[j-1]; 
			a[j]=tmp;
		}
	}
} 

int main()
{
	int i;
	int a[]={4,5,9,6,3,8,2,8,2,8,6,6,5,4,2,8,9,5};
	int n=sizeof(a)/sizeof(int);
	BInsertSort(a,n);
	for(i=0;i<n;i++)
		printf("%d ",a[i]);
	return 0;
}

 

 

 

希尔排序

插入排序在基本有序的情况下效率挺高,希尔排序可使程序部分逐渐变得有序。

一. 算法描述

希尔排序:将无序数组分割为若干个子序列,子序列不是逐段分割的,而是相隔特定的增量的子序列,对各个子序列进行插入排序;然后再选择一个更小的增量,再将数组分割为多个子序列进行排序......最后选择增量为1,即使用直接插入排序,使最终数组成为有序。

增量的选择:在每趟的排序过程都有一个增量,至少满足一个规则 增量关系 d[1] > d[2] > d[3] >..> d[t] = 1 (t趟排序);根据增量序列的选取其时间复杂度也会有变化,这个不少论文进行了研究,在此处就不再深究;本文采用首选增量为n/2,以此递推,每次增量为原先的1/2,直到增量为1;

下图详细讲解了一次希尔排序的过程:

 

排序算法——插入排序

排序算法——插入排序

--------------------- 本文来自 love小仙 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/jianfpeng241241/article/details/51707618?utm_source=copy

代码:

//希尔排序(升序)
#include<stdio.h>

void ShellInsert(int *a,int n)
{
	int dk[]={5,3,1};
	int dk_len=sizeof(dk)/sizeof(int);
	int i,j,k,tmp1,tmp2;
	for(i=0;i<dk_len;i++)
	{
		for(j=0;j<dk[i];j++)
		{
			for(k=j+dk[i];k<n;k+=dk[i])
			{
				if(a[k]<a[k-dk[i]])
				{
					tmp1=k;
					tmp2=a[k];
					while(tmp1>j&&tmp2<a[tmp1-dk[i]])
					{
						a[tmp1]=a[tmp1-dk[i]];
						tmp1-=dk[i];
					}
					a[tmp1]=tmp2;
				} 
			}
		}
	}
} 

int main()
{
	int i;
	int a[]={8,2,5,8,7,4,2,6,3,85,62,5,4,3,2,22,25,87};
	int n=sizeof(a)/sizeof(int);
	ShellInsert(a,n);
	for(i=0;i<n;i++)
		printf("%d ",a[i]);
	return 0;
}

 

参考文章:

直接插入排序算法

经典排序算法(4)——折半插入排序算法详解

折半插入排序

希尔排序理解

 

相关文章: