【数据结构】C语言实现排序算法------直接插入排序

直接插入排序(Straight Insertion Sort):将一个数据插入到已经排序的数据中,从而得到一个新的有序数据。

图例:
在这里插入图片描述

1.直接插入排序

代码实现:

  1. 直接插入
void InsertSort_1(int *arr, int left, int right)
{
	for (int i = left + 1; i < right; i++)
	{
		int end = i;
		while (end > 0 && arr[end] < arr[end - 1])
		{
			Swap(&arr[end], &arr[end - 1]);//交换
			end--;
		}
	}
}
  1. 上述代码进行修改,减少交换次数
void InsertSort_2(int *arr, int left, int right)
{
	for (int i = left + 1; i < right; i++)
	{
		int tmp = arr[i];
		int end = i;
		while (end > 0 && tmp < arr[end - 1])
		{
			arr[end] = arr[end - 1];
			end--;
		}
		arr[end] = tmp;//end记录的是最后一次需要改变的位置
	}
}
  1. 设置哨兵位:避免数组下标越界
void InsertSort_3(int *arr, int left, int right)
{
	for (int i = left + 1; i < right; i++)
	{
		arr[0] = arr[i];//arr[0]为哨兵
		int end = i;
		while (arr[0] < arr[end - 1])
		{
			arr[end] = arr[end - 1];
			end--;
		}
		arr[end] = arr[0];
	}
}

2.折半插入排序

折半插入:利用“折半查找”来找到插入位置。
代码实现:

void BinInsertSort(int *arr, int left, int right)
{
	for (int i = left + 1; i < right; i++)
	{
		int tmp = arr[i];
		int end = i;
		int start = left;
		int mid;
		while (start <= end)//寻找插入位置
		{
			mid = (start + end) >> 1;
			if (tmp > arr[mid])
				start = mid + 1;
			else
				end = mid - 1;
		}
		for (int j = i; j > end + 1; j--)//移动数据
			arr[j] = arr[j - 1];
		arr[end + 1] = tmp;
	}
}

3. 2路插入排序

基本原理:以第一个元素作为比较元素,后续元素比首元素大,往前插入,比首元素小,往后插入。采用循环数组的方式实现。

void TwoWayInsertSort(int *arr, int left, int right)
{
	int n = right - left;
	int *tmp = (int *)malloc(sizeof(int) * n);//开辟数组
	assert(tmp != NULL);
	int front = 0, rear = 1;//头,尾指针
	tmp[0] = arr[left];//首元素
	for (int i = left + 1; i < right; i++)
	{
		if (arr[i] <= tmp[front])//比首元素还小
		{
			front = (front - 1 + n) % n;//更改首元素位置
			tmp[front] = arr[i];
		}
		else if(arr[i] >= tmp[rear - 1])//比尾元素还要大
		{
			tmp[rear++] = arr[i];
		}
		else// 插入位置在中间
		{
			int j = rear - 1;
			while (arr[i] < tmp[j])//寻找插入位置
			{
				tmp[(j + 1) % n] = tmp[j];
				j = (j - 1 + n) % n;
			}
			tmp[(j + 1)%n] = arr[i];//插入
			rear++;
		}
	}
	int k = front;
	for (int i = left; i < right; i++)//赋给原数组
	{
		arr[i] = tmp[k];
		k = (k + 1) % n;
	}
	free(tmp);//释放临时空间,避免内存泄漏
	tmp = NULL;
}

三种插入排序总结:

  1. 时间复杂度:均为O(N^2)
  2. 空间复杂度:直接插入排序:O(1),折半插入排序:O(1),2路插入排序:O(n)
  3. 稳定性:均为稳定排序
  4. 元素越接近有序,算法时间效率越高
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值