数据结构--插入排序

**问题:**任意给定一组元素序列,利用直接插入排序、折半插入排序和希尔排序对该序列进行排序
分析:
插入排序最好可以类比为打扑克牌时,我们摸完牌后再将牌插到合适得位置。
主要有几个操作:

  1. 从未排序的序列里摸一张牌,也就是把未排序的第一张牌取出来;
  2. 和前面牌完序的牌进行大小比较,如果手里的牌比前面的小,就一直交换位置。

直接插入排序

void Insertion_sort(SqList *L)
/*输入待排序的数组和元素个数*/
{
	int p,i;
	ElementType Tmp;
	for (p = 1; p < L->Length; p++) //每次从后面待排序的序列里取出一张往前插,默认A[0]已经排好序
	{
		Tmp = L->data[p];
		for (i = p; i >= 0&&Tmp<L->data[i-1]; i--)
		{
			L->data[i] = L->data[i - 1];
		}
		L->data[i] = Tmp;
	}
}

折半插入排序
折半插入排序和直接插入排序相比,在确定插入位置的那一步采用折半查找,最后还是逐个移动位置,所以仅减小了关键字的比较次数,儿记录的移动次数没变,时间复杂度O(N2)


void BinInsertion_sort(SqList *L)
/*折半插入算法,插入更快,移动元素并未发生改变*/
{
	int p, i, Low, High, Mid;
	ElementType Tmp;
	for (p = 1; p < L->Length; p++)
	{
		Tmp = L->data[p];//取出后面一个元素
		Low = 0;
		High = p-1;
		while (Low<=High)
		{
			Mid = (Low + High) / 2;
			if (Tmp < L->data[Mid])
				High = Mid - 1;
			else
			{
				Low = Mid + 1;
			}
		}
		for (i = p; i >= Low; i--)
		{
			L->data[i] = L->data[i - 1];
		}
		L->data[Low] = Tmp;

	}
}

希尔排序
希尔排序,引入一个增量,每次不止消除一个逆序对,任何交换相邻元素的排序算法每交换一次只能消除一个逆序对。要提高效率,我们必须每次不仅消除一个逆序对。因此我们可以将序分成若干个子序列,子序列有相聚一定的距离的元素组成,对每个子序列进行插入排序,这样每次可以消除不止一个逆序对。

void Shell_Sort(SqList *L)
/*希尔排序*/
{
	int D;//增量
	int p, i;
	ElementType Tmp;
	for (D = L->Length/2; D>0; D/=2) // 增量每次缩小一半
	{
		for (p = D; p < L->Length; p++)
		{
			Tmp = L->data[p];
			for (i = p; i >= 0 && L->data[i - D] > Tmp; i--)
			{
				L->data[i] = L->data[i - D];
			}
			L->data[i] = Tmp;
		}
	}
}

完整的实例代码:

// Insertion_sort.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
constexpr auto MaxSize = 100;;

typedef int ElementType;

typedef struct
{
	ElementType data[MaxSize];
	int Length;

}SqList;

void Swap(ElementType *a, ElementType *b)
/*交换a,b*/
{
	ElementType tmp;
	tmp = *a;
	*a = *b;
	*b = tmp;
}

void Insertion_sort(SqList *L)
/*输入待排序的数组和元素个数*/
{
	int p,i;
	ElementType Tmp;
	for (p = 1; p < L->Length; p++) //每次从后面待排序的序列里取出一张往前插,默认A[0]已经排好序
	{
		Tmp = L->data[p];
		for (i = p; i >= 0&&Tmp<L->data[i-1]; i--)
		{
			L->data[i] = L->data[i - 1];
		}
		L->data[i] = Tmp;
	}
}


void BinInsertion_sort(SqList *L)
/*折半插入算法,插入更快,移动元素并未发生改变*/
{
	int p, i, Low, High, Mid;
	ElementType Tmp;
	for (p = 1; p < L->Length; p++)
	{
		Tmp = L->data[p];//取出后面一个元素
		Low = 0;
		High = p-1;
		while (Low<=High)
		{
			Mid = (Low + High) / 2;
			if (Tmp < L->data[Mid])
				High = Mid - 1;
			else
			{
				Low = Mid + 1;
			}
		}
		for (i = p; i >= Low; i--)
		{
			L->data[i] = L->data[i - 1];
		}
		L->data[Low] = Tmp;

	}
}

void Shell_Sort(SqList *L)
/*希尔排序,引入一个增量,每次不止消除一个逆序对,任何交换相邻元素的排序算法每交换一次只能消除一个逆序对。
要提高效率,我们必须每次不仅消除一个逆序对。因此我们可以将序分成若干个子序列,子序列有相聚一定的距离的元素组成
,对每个子序列进行插入排序,这样每次可以消除不止一个逆序对。
*/
{
	int D;//增量
	int p, i;
	ElementType Tmp;
	for (D = L->Length/2; D>0; D/=2) // 增量每次缩小一半
	{
		for (p = D; p < L->Length; p++)
		{
			Tmp = L->data[p];
			for (i = p; i >= 0 && L->data[i - D] > Tmp; i--)
			{
				L->data[i] = L->data[i - D];
			}
			L->data[i] = Tmp;
		}
	}

}

void DisPlay(SqList L)
{
	
	int i;
	for (i = 0; i < L.Length; i++)
	{
		printf("%-5d",L.data[i]);
	}
	printf("\n");
}


int main()
{
	int A[] = { 2,5,1,3,5,7,11 };
	int i,len;
	len = sizeof(A) / sizeof(A[0]);
	SqList L,L1,L2;
	for (size_t i = 0; i < len; i++)
	{
		L.data[i] = A[i];
	}
	L.Length = len; 
	L1 = L2 = L;
	printf("排序前:");
	DisPlay( L);
	printf("插入排序:");
	Insertion_sort(&L);
	DisPlay(L);
	printf("折半插入排序:");
	BinInsertion_sort(&L1);
	DisPlay(L1);
	printf("希尔排序:");
	Shell_Sort(&L2);
	DisPlay(L2);
	
}

程序运行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_38904904/article/details/89817178
今日推荐