数据结构之排序(上半部)

1、排序的概念以及简单介绍

1.1排序的概念

排序:顾名思义就是将一组数据按从小到大(从大到小)排列开来。

1.2排序的分类

(1)内部排序:就是将数据全部储存到内存中排序
(2)外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

1.3排序的应用

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

2、常见的排序与算法

在这里插入图片描述

2.1插入排序

2.1.1直接插入排序

(1)解释:这个过程类似整理扑克牌,当拿到一组数据后,首先就是从首元素开始排,然后去遍历前面的数据(这里拿升序来举例),遍历完以后,发现没有比他更小的数据,所以直接插入。然后开始第二个数据,然后在继续遍历前面的数剧,若比首元素的数据小,则把最小的数据插入到首元素的位置上,然后第二个元素就已经排好了,然后开始排第三个数据,就这样依此排序。(排之前就检查该数据是否存在比前面的数据小)
在这里插入图片描述
在这里插入图片描述
(2)代码实现:
在这里插入图片描述

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

}

2.1.2希尔排序(缩小增量排序)

(1)解释定义:希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。

也就是说希尔排序就是多组的插入排序,因为插入排序排一些接近有序的数据较为方便,希尔排序其实是插入排序的一种改造,先按一定分组将每组进行插入排序(也就是预排序),然后在进行插入排序
(2)代码实现
在这里插入图片描述
1.预排序
在这里插入图片描述
在这里插入图片描述
2、直接插入排序(希尔排序的完整版)
在这里插入图片描述

//希尔排序
void  ShellSort(int* a, int n)
{
	int gap = n;
	//当gap==1时就是直接插入排序
	while (gap > 1)
	{
		gap = (gap / 3) + 1;
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
				a[end + gap] = tmp;
			}

		}

	}
}

2.2选择排序

顾名思义就是选择,先去选择一个较小的数,然后依此排列。与插入排序不同的是,插入排序是比较完直接覆盖,然后插入那个位置。

2.21直接选择排序

(1)解释定义:这是一个极其暴力的求法,直接遍历数组,选择出最小的一个的数,然后将其插入第一个首元素的位置,然后在继续选最小插入第二个元素的位置,依此类推…
在这里插入图片描述
(2)代码实现
在这里插入图片描述
在这里插入图片描述

//直接选择排序
void SlectSort(int* a, int n)
{
	int end = n - 1, begin = 0;
	while (begin < end)
	{
		int max = begin, min = begin;
		for (int i = begin + 1; i <= end; ++i)
		{
			if (a[i] < a[min])
			{
				min = i;
			}
			if (a[i] > a[max])
			{
				max = i;
			}
		}
		swap(&a[begin], &a[min]);
		if (max == begin)
		{
			max = min;
		}
		swap(&a[end], &a[max]);
		++begin;
		--end;
	}
}

2.22堆排序

(1)解释定义:堆排序就是建造为堆以后(拿升序举例,所以这里是大堆),因为大堆的堆顶元素一定为最大值,所以将堆顶元素放入最后一个元素,然后堆范围【0,size-1-1】部分的进行向下调整堆,然后重复上述过程。
(2)代码实现:
1、建造堆
方法1:向上调整建堆

void AjustUP(int* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] > a[parent])
		{
			swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}
//建堆
	for (int i = 0; i < n; i++)
	{
		AjustUP(a, i);
	}

2、向下调整建堆
在这里插入图片描述

void AjustDown(int* a, int size, int parent)
{
	int child = parent * 2 + 1;
	while (child < size)
	{
		if (child + 1 < size && a[child + 1] > a[child])
		{
			child += 1;
		}
		if (a[child] > a[parent])
		{
			swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}

	}
}
//建堆
for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AjustDown(a, n - 1, i);
	}

2、排序
在这里插入图片描述

void HeadSort(int* a, int n)
{
	//建堆
	/*for (int i = 0; i < n; i++)
	{
		AjustUP(a, i);
	}*/
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AjustDown(a, n - 1, i);
	}
	//排序
	int end = n - 1;
	while (end > 0)
	{
		swap(&a[0], &a[end]);
		AjustDown(a, end, 0);
		--end;

	}

}

2.3交换排序

2.31冒泡排序

(1)解释定义:两两交换,将大最大的放后面
在这里插入图片描述
(2)代码实现

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

2.32快速排序

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

2.321Hoare版

(1)概念解释
在这里插入图片描述
在这里插入图片描述
(2)代码实现
在这里插入图片描述
(注意这上面的begin和end只是方便记忆,和下面的left和right等价)
在这里插入图片描述

void QuickSort(int* a, int begin, int end)
{
	if (begin >= end)
		return;
	int keyi = begin;
	int left = begin, right = end;
	while (left < right)
	{
		while(left < right && a[right] >= a[keyi])
		{
			--right;
		}
		while(left < right && a[left] <= a[keyi])
		{
			++left;
		}
		swap(&a[left], &a[right]);
	}
	swap(&a[left], &a[keyi]);
	keyi = left;
	QuickSort(a,begin,keyi-1);
	QuickSort(a, keyi+1, end);
}
  • 45
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值