PTA 排序(冒泡,插入,希尔,堆排序,归并排序)

排序效率一览:在这里插入图片描述

本章介绍了五种常见排序方法,每种方法各有利弊。

1.冒泡排序
一个指针一开始指向最后一个位置,将之前两两比较出来的最大的那个值一步步交换到这个位置上。并且加入监控是否全程没有发生交换的变量flag,可以提前终止循环,代表完成了排序。

/*冒泡排序*/
void Bubble_sort(long a[], int N)
{
   
	int flag;//一趟冒泡是否发生交换
	for (int P = N - 1; P >= 0; P--)
	{
   
		flag = 0;
		for (int i = 0; i < P; i++)
		{
   
			if (a[i] > a[i + 1]) {
   
				swap(a[i],a[i+1]);
				flag = 1;
			}
			if (flag = 0) //全程无交换,跳出循环
				break;
		}
	}
}

用几组特征如下的数据来检测排序算法效率(下例也一样):
数据1:只有1个元素;
数据2:11个不相同的整数,测试基本正确性;
数据3:103个随机整数;
数据4:104个随机整数;
数据5:105个随机整数;
数据6:105个顺序整数;
数据7:105个逆序整数;
数据8:105个基本有序的整数;
数据9:105个随机正整数,每个数字不超过1000。

冒泡排序效率:
在这里插入图片描述

2.插入排序
相当于打扑克的排序,每次新摸一张牌,就从手牌的末尾处依次比较过去并腾出一格的位置,直到找到合适的位置完成一次插入。

/*插入排序*/
void Insertion_sort(long a[], int N)
{
   
	for (int P = 1; P < N; P++) 
	{
   
		long Tmp;
		int i;
		Tmp = a[P];
		for ( i = P; i > 0 && Tmp < a[i - 1] ; i--)
			a[i] = a[i - 1];
		a[i] = Tmp;
	}
}

插入排序效率
在这里插入图片描述

3.希尔排序
升级版的插入排序,以某种特定的间隔来依次进行插入,在某种情况下有助于提高效率。

/*希尔排序,间隔插入排序*/
void Shell_sort(long a[], int N)
{
   
	int Si, D, P, i;
	long Tmp;

	//使用sedgewick间隔增量
	int Sedgewick[] = {
    929, 505, 209, 109, 41, 19, 5, 1, 0 };

	for (Si = 0; Sedgewick[Si] >= N; Si++)
		;//一开始的间隔量小于排序总数

	for(D = Sedgewick[Si]; D>0 ; D = Sedgewick[++Si])
		for (P = D; P < N; P++) 
		{
   
			Tmp = a[P];
			for (i = P; i >= D && Tmp < a[i - D]; i -= D) //注意是i-D而不是i-1 并且是i>D而不是i>0
				a[i] = a[i - D];
			a[i] = Tmp;
		}
}

在这里插入图片描述

4.堆排序
(若你要排从小到大序列)先构建一个最大堆(在数组中就是一个个整理子树,整理到根节点为止),然后将堆顶最大元素和当前堆的最后一个元素交换位置。最后将最后一个元素整个踢出堆(也就是将堆的规模缩小一位)。

/*堆排序*/
void Swap(long *a, long *b)
{
   
	long t = *a;
	*a = *b;
	*b = t;
}

void PerDown(long a[], int p, int N)//向下过滤函数
{
   
	int Parent, Child;
	long X;

	X = a[p]; //取出根节点的值
	for (Parent = p; (Parent * 2 + 1) < N; Parent = Child)
	{
   
		Child = Parent * 2 + 1;//因为从0开始的,所以左儿子要加一
		if ((Child != N - 1) && (a[Child] < a[Child + 1]))
			Child++;//child指向左右儿子中较大者
		if (X >= a[Child])
			break; //若根节点大于此时的最大的儿子,则找到合适位置
		else
			a[Parent] = a[Child];
	}
	a[Parent] = X;

}

void HeapSort(long a[],int N)
{
   
	int i;
	/*从0开始的树,所以最后一个父节点是N/2-1,把10带进去很好理解。
	建树的时候所有点都是乱的,所以每个子树都要向下过滤调整,
	但交换后就不一样了,只有堆顶的元素是乱的,所以不用写循环了*/
	for (i = N / 2 - 1; i >= 0; i--)
		PerDown(a, i ,N );//向下过滤,整理树

	for (i = N - 1; i > 0; i--)//每循环一次缩小一次堆的规模
	{
   
		Swap(&a[0], &a[i]);//交换堆顶和最后一个元素
		PerDown(a, 0, i);
	}

c++背诵版:

class Solution {
   
public:
	vector<int> sortArray(vector<int>& nums) {
   
		int n 
  • 3
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值