数据结构中排序算法-插入排序(1)

1,直接插入排序

  • 主要操作是比较和移动。
  • 时间复杂度为最差和平均都为O(n^2),最好为O(n)。
  • 辅助空间为O(1)。
  • 稳定的排序算法。
  • 当初始序列为正序时,比较次数为n-1,移动次数为0;当初始序列为逆序时,比较次数为(n+2)(n-1)/2,移动次数为(n+4)(n-1)/2。
  • 适用于n很小的排序记录。
  • 对初始排序序列敏感。

         代码如下:

#include "stdafx.h"
#include<iostream>
using namespace std;
#define MAXSIZE 30

struct SqList{
	int list[MAXSIZE+1];
	int length;
};

void insertSort(SqList &L){
	int i,j;
	for(i=2;i<=L.length;i++)
	{
		if(L.list[i]<L.list[i-1])//是<,而不是<=
		{
			L.list[0]=L.list[i];
			L.list[i]=L.list[i-1];//i-1这个位置是空出来的
			for(j=i-2;L.list[0]<L.list[j];j--)//是<,而不是<=
			   L.list[j+1]=L.list[j];
			L.list[j+1]=L.list[0];
		}
	}
}
void main()
{ 
	SqList St;
	printf("**********************************\n");
	printf("         直接插入排序算法         \n");
	printf("**********************************\n");
	printf("请输入需要排序的关键字个数N (N<30):");
	scanf("%d",&St.length);
	printf("\n");
	printf("请第一个数应输入为0,为哨兵,再输入%d无序数:\n",St.length);
	for (int i=0;i<=St.length;i++)
		scanf("%d",&St.list[i]);
	insertSort(St);
	printf("\n");
	printf("输出排序结果:");
	for(int j=1;j<=St.length;j++)
		printf("%d ",St.list[j]);
	printf("\n");
	printf("\n");
}

运行结果如下:


 

2,折半插入排序

  • 主要操作是比较和移动,相比较直接插入排序,比较次数减少,移动次数不变。先找好位置,再移动。而直接插入排序是边找位置,边移动。
  • 时间复杂度为最差,平均都为O(n^2),最好为O(n)。
  • 辅助空间复杂度为O(1)。
  • 稳定的排序算法。
  • 对初始排序序列敏感。

    代码如下:

#include "stdafx.h"
#include<iostream>
using namespace std;
#define MAXSIZE 40

struct SqList{
	int list[MAXSIZE+1];
	int length;
};

void BinsertSort(SqList &L){
	int i,j,m;
	for(i=2;i<=L.length;i++)
	{
		L.list[0]=L.list[i];//这里的L.list[0]是暂存单元,不是哨兵。
		int low=1,high=i-1;
		while(low<=high)
		{ 
			m=(low+high)/2;
			if(L.list[0]<L.list[m])//找到的就是待插关键字大于或等于中间关键字的位置,也就是high这个位置。
				high=m-1;
			else
				low=m+1;
		}
		//跳出循环,一定是low=high+1
		for(j=i-1;j>=low;j--)//那么移动时,一定是需要将high位置后面的关键字后移,也就是从high+1开始,每个关键字后移一位。
			L.list[j+1]=L.list[j];
		L.list[high+1]=L.list[0];//最后肯定会空出来high+1这个位置。将待插元素放到这个位置。
	}
}
void main()
{ 
	SqList St;
	printf("**********************************\n");
	printf("         折半插入排序算法         \n");
	printf("**********************************\n");
	printf("请输入需要排序的关键字个数N (N<%d):",MAXSIZE);
	scanf("%d",&St.length);
	printf("\n");
	printf("请第一个数应输入为0,为暂存单元,再输入%d个无序数:\n",St.length);
	for (int i=0;i<=St.length;i++)
		scanf("%d",&St.list[i]);
	BinsertSort(St);
	printf("\n");
	printf("输出排序结果:");
	for(int j=1;j<=St.length;j++)
		printf("%d ",St.list[j]);
	printf("\n");
	printf("\n");
}


运行结果如下:


  3,希尔排序

  • 基本思想 :现将待排序列分成若干个子序列,对各个子序列进行直接插入排序,当待排序列基本有序时,再对全体记录进行一次插入排序。这样做的原因是:当关键字记录很少和基本有序时,直接插入排序效率很高,所以希尔排序就是结合这两点对直接插入排序进行改进的。
  • 时间复杂度:O(nlogn)。
  • 空间复杂度为O(1)。
  • 不是稳定的排序算法。
  • 对初始排序序列敏感。

        代码如下 :

#include "stdafx.h"
#include<stdio.h>
#define MAXSIZE 40
#define times 10

struct SqList{
	int list[MAXSIZE+1];
	int length;
};

void shellInsert(SqList &L,int d){
	int i,j;
	for( i=d+1;i<=L.length;i++)
		if(L.list[i]<L.list[i-d])
		{
		   L.list[0]=L.list[i];//L.list[0]为暂存单元,不是哨兵。
	    for(j=i-d;j>0&&L.list[0]<L.list[j];j-=d)//这里相距间隔为d,j>0保证不溢出
		    L.list[j+d]=L.list[j];
	    L.list[j+d]=L.list[0];
		}
}
void shellSort(SqList &L,int delt[],int t)
{
	for(int k=0;k<t;k++)
		shellInsert(L,delt[k]);
}
void main()
{ 
	SqList St;
	int t;
	int delta[times];
	printf("***********************************************\n");
	printf("               希尔排序算法                    \n");
	printf("***********************************************\n");
	printf("请输入需要排序的关键字个数N (N<%d):",MAXSIZE);
	scanf("%d",&St.length);
	printf("\n");
	printf("请第一个数应输入为0,不参与排序,为暂存单元,再输入%d个待排序的关键字:\n",St.length);
	for (int i=0;i<=St.length;i++)
		scanf("%d",&St.list[i]);
	printf("\n");
	printf("请输入希尔排序的趟数times(times<%d):",times);
	scanf("%d",&t);
	printf("\n");
	printf("请输入希尔排序的增量序列,最后一个增量必须为1:");
	for(int m=0;m<t;m++)
	   scanf("%d",&delta[m]);
	shellSort(St,delta,t);
	printf("\n");
	printf("输出排序结果:");
	for(int j=1;j<=St.length;j++)
		printf("%d ",St.list[j]);
	printf("\n");
	printf("\n");
}

    运行结果如下:












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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值