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 = nums.size();
		HeapSort(nums, n);
		return nums;
	}
	void adjust(vector<int> &nums, int len, int index) {
		int left = 2 * index + 1; // index的左子节点
		int right = 2 * index + 2;// index的右子节点

		int maxIdx = index;
		if (left<len && nums[left] > nums[maxIdx])     maxIdx = left;
		if (right<len && nums[right] > nums[maxIdx])     maxIdx = right;

		if (maxIdx != index)//有交换需求
		{
			swap(nums[maxIdx], nums[index]);
			adjust(nums, len, maxIdx); //向下过滤
		}

	}

	// 堆排序
	void HeapSort(vector<int> &nums, int size) {
		for (int i = size / 2 - 1; i >= 0; i--) //从倒数第一个有儿子的父节点开始调整,一直调整到root
		{
			adjust(nums, size, i); 
		}
		for (int i = size - 1; i >= 1; i--) {
			swap(nums[0], nums[i]);//最大的哥们放到最后面,并且堆规模减一
			adjust(nums, i, 0);//继续调整
		}
	}
};

在这里插入图片描述

5.归并排序
算法核心是有序子列的归并Merge。也就是将左右两个子列分别比较每一个元素大小,将较小的填入Tmp数组中,然后将贡献出最小元素的那个原始数组的指针向后移一位。
然后有两种写法,递归和迭代。

递归归并:

/*归并排序*/

//有序子列归并函数
void Merge(long a[], long Tmpa[], int L, int R, int RightEnd)
{	
	int LeftEnd;
	int Tmp; //归并后数组指针
	int NumElements; //记录左右子列元素总数

	LeftEnd = R - 1;//左右子列紧挨着
	Tmp = L;//对齐Tmp数组和左数组
	NumElements = RightEnd - L + 1;

	while (L <= LeftEnd && R <= RightEnd)
	{
		if (a[L] <= a[R])
			Tmpa[Tmp++] = a[L++];	//L或者R在赋值后要记得也要移动
		else
			Tmpa[Tmp++] = a[R++];
	}

	while (L <= LeftEnd)  //若一边的数组有多出来的元素
		Tmpa[Tmp++] = a[L++];
	while (R <= RightEnd)
		Tmpa[Tmp++] = a[R++];
	for (int i = 0; i < NumElements; i++, RightEnd--)
		a[RightEnd] = Tmpa[RightEnd];
}

//递归归并,分而治之
void Msort(long a[], long Tmpa[], int L, int RightEnd)
{
	int Center;//一直递归对半分,分而治之
	if (L < RightEnd) //注意是小于,而不是小于等于,小于号才保证递归的部分里面有元素
	{
		Center = (L + RightEnd) / 2;
		Msort(a, Tmpa, L, Center); //对左边递归排序
		Msort(a, Tmpa, Center + 1, RightEnd);//对右边递归排序
		Merge(a, Tmpa, L, Center + 1, RightEnd);//把左右归并
	}
}

//统一接口
void Merge_sort(long a[], int N)
{
	long* Tmpa;//指向long的指针Tmpa(实际上就是Tmpa数组)

	Tmpa = (long*)malloc(N * sizeof(long));

	if (Tmpa != NULL)//能申请到空间
	{
		Msort(a, Tmpa, 0, N - 1);
		free(Tmpa); //记得释放空间
	}
	else
		cout << "No Space";
}

归并效率:
在这里插入图片描述

另外还有循环归并:

/* 归并排序 - 循环实现 */
/* 这里Merge函数在递归版本中给出 */
 
/* length = 当前有序子列的长度*/
void Merge_pass( ElementType A[], ElementType TmpA[], int N, int length )
{ /* 两两归并相邻有序子列 */
     int i, j;
       
     for ( i=0; i <= N-2*length; i += 2*length )
         Merge( A, TmpA, i, i+length, i+2*length-1 );
     if ( i+length < N ) /* 归并最后2个子列*/
         Merge( A, TmpA, i, i+length, N-1);
     else /* 最后只剩1个子列*/
         for ( j = i; j < N; j++ ) TmpA[j] = A[j];
}
 
void Merge_Sort( ElementType A[], int N )
{ 
     int length; 
     ElementType *TmpA;
      
     length = 1; /* 初始化子序列长度*/
     TmpA = malloc( N * sizeof( ElementType ) );
     if ( TmpA != NULL ) {
          while( length < N ) {
              Merge_pass( A, TmpA, N, length );
              length *= 2;
              Merge_pass( TmpA, A, N, length );
              length *= 2;
          }
          free( TmpA );
     }
     else printf( "空间不足" );
}

例二:09-排序2 Insert or Merge (25分)
According to Wikipedia:

Insertion sort iterates, consuming one input element each repetition, and growing a sorted output list. Each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there. It repeats until no input elements remain.

Merge sort works as follows: Divide the unsorted list into N sublists, each containing 1 element (a list of 1 element is considered sorted). Then repeatedly merge two adjacent sublists to produce new sorted sublists until there is only 1 sublist remaining.

Now given the initial sequence of integers, together with a sequence which is a result of several iterations of some sorting method, can you tell which sorting method we are using?

Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤100). Then in the next line, N integers are given as the initial sequence. The last line contains the partially sorted sequence of the N numbers. It is assumed that the target sequence is always ascending. All the numbers in a line are separated by a space.

Output Specification:
For each test case, print in the first line either “Insertion Sort” or “Merge Sort” to indicate the method used to obtain the partial result. Then run this method for one more iteration and output in the second line the resuling sequence. It is guaranteed that the answer is unique for each test case. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.

Sample Input 1:
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0

Sample Output 1:
Insertion Sort
1 2 3 5 7 8 9 4 6 0

Sample Input 2:
10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6

Sample Output 2:
Merge Sort
1 2 3 8 4 5 7 9 0 6

思路: 题目大意是让你判断一个排序排了一半的结果,是用的插入排序还是归并排序。首先观察数组最大值N才100,所以可以将排序算法每迭代一次进行一次判断,如果发现某次循环的时候结果完全相同,就可以下结论是某种排序方法了。然后再将这种循环再进行一次,就可以输出结果了。BTW,因为要在循环上做文章,所以需要将归并排序用循环的方式写出来。

需要注意的是:
1.这题主要在考两种排序方式的改写。特别是在最后的输出的过程中,必须搞清楚插入循环中的P(摸的新的那张牌,故下次执行从上次输出的P+1开始),以及归并循环中的length(当前有序的子序列长度,故下次执行从上次输出的length开始)。

2.在Merge_sort中,要想判断正确是否相同,要注意归并循环程序是在A和TmpA中来回互相倒。因此要注意IsSame的比较对象。并且,要记得如果是奇数次数的循环,TmpA中存放得才是奇数次时正确的值,要把TmpA整个复制到A上面(因为最后输出接口是A)。

#include <stdio.h>
#include <iostream>


using namespace std;

const int MaxNumber = 101;

//Insert排序直接在origin上排,meger在MergeA上排序
int OriginA[MaxNumber],  MergeA[MaxNumber];
int TargetA[MaxNumber];
int flag = 0;//用来区分是哪种排序的flag,1为插入,2为合并

bool IsSame(int Origin[], int Target[],int N)
{	
	for (int i = 0; i < N; i++)
	{
		if (Origin[i] != Target[i])
			return false;
		else
			continue;
	}
	return true;
}


/*插入排序*/
int Insertion_sort(int A[],int N,int Times)
{	
	int P ;
	if (flag == 1)
		P = Times+1;//二次执行时,摸后面一张牌
	else
		P = Times;

	for ( P ; P < N; P++)
	{
		int Tmp;
		int i;
		Tmp = A[P];
		for (i = P; i > 0 && Tmp < A[i - 1]; i--)
			A[i] = A[i - 1];
		A[i] = Tmp;

		if (flag == 1)//若flag等于1,则说明是第二次调用排序
			return P;  //跑一轮就直接强行结束

		if (IsSame(OriginA, TargetA, N)) {
			flag = 1;//如果相同则改变flag
			return P;
		}
	}
	
	return P;
}
/*迭代合并排序*/
void Merge(int A[], int TmpA[], int L, int R, int RightEnd)
{
	int LeftEnd, NumerElements,Tmp;
	LeftEnd = R - 1;
	NumerElements = RightEnd - L + 1;
	Tmp = L;

	while (L <= LeftEnd && R<=RightEnd)
	{
		if (A[L] <= A[R])
			TmpA[Tmp++] = A[L++];
		else
			TmpA[Tmp++] = A[R++];

	}
	while (L<=LeftEnd)
	{
		TmpA[Tmp++] = A[L++];
	}
	while (R <= RightEnd)
	{
		TmpA[Tmp++] = A[R++];
	}
}

//一趟归并
void Merge_pass(int A[], int TmpA[] , int N , int length)
{
	int i;
	for ( i = 0; i <= N - 2 * length; i += 2 * length)
		Merge(A, TmpA, i, i + length, i + 2 * length - 1);
	if (i + length < N)//若末尾还剩下一个多的位置空间,可以分为两个子数组
		Merge(A, TmpA, i, i + length, N - 1);//照常合并
	else
	{
		for (int j = i; j < N; j++)//若末尾只剩一个子数组的空间,则一一复制过去
			TmpA[j] = A[j];
	}
}

//统一接口,多次归并
int Merge_sort(int A[], int N , int length)
{	
	int NotFirstTime = 0;
	int *TmpA;
	TmpA = (int* )malloc( sizeof(int)*N);

	if (flag == 2)//设置一个新监控变量,因为while内部如果继续用flag可能直接跳出函数
		NotFirstTime = 1;//不需要改变length。length的意义是当前有序子序列长度。

	if (TmpA != NULL)
	{
		while (length < N)
		{
			Merge_pass(A, TmpA, N, length);
			length *= 2;
			//此轮排序存储在TmpA里
			if (IsSame(TmpA, TargetA, N)) {
				flag = 2;//如果相同则改变flag
				for (int i = 0; i < N; i++)//奇数次数运算后,记得把TmpA中的复制回A
					A[i] = TmpA[i];
				return length;
			}
			/*若不是第一次执行,则说明是第二次调用排序*/
			if (NotFirstTime == 1) {
				for (int i = 0; i < N; i++)//把TmpA中数值拷贝回A中
					A[i] = TmpA[i];
				return length;
			} //跑一轮就直接强行结束

			Merge_pass(TmpA, A, N, length);
			length *= 2;
			//此轮排序存储在A里面
			if (IsSame(A, TargetA, N)) {
				flag = 2;//如果相同则改变flag
				return length;
			}
		}
		free(TmpA);
	}

	else
		cout << "no enough space";
	return length;
}

int main()
{
	int N;
	cin >> N;
	for (int i = 0; i < N; i++)//读取原始数组
	{
		cin >> OriginA[i];
		MergeA[i] = OriginA[i];//同时复制一份
	}
	for (int i = 0; i < N; i++)//读入目标数组
	{
		cin >> TargetA[i];
	}

	int Times,length;

	Times = Insertion_sort(OriginA, N,1);//初始牌号给1
	length = Merge_sort(MergeA, N,1);//初始有序子数组的长度给1

	//如果是insert排序
	if (flag == 1) {
		cout << "Insertion Sort" << "\n";
		Insertion_sort(OriginA, N,Times);

		for (int i = 0; i < N; i++)
		{
			if (i != N - 1)
				cout << OriginA[i] << " ";
			else
				cout << OriginA[i];
		}
	}
	//如果是merge排序
	if (flag == 2) {
		cout << "Merge Sort" << "\n";
		Merge_sort(MergeA, N, length);

		for (int i = 0; i < N; i++)
		{
			if (i != N - 1)
				cout << MergeA[i] << " ";
			else
				cout << MergeA[i];
		}
	}

	return 0;
}

例三:09-排序3 Insertion or Heap Sort (25分)
According to Wikipedia:

Insertion sort iterates, consuming one input element each repetition, and growing a sorted output list. Each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there. It repeats until no input elements remain.

Heap sort divides its input into a sorted and an unsorted region, and it iteratively shrinks the unsorted region by extracting the largest element and moving that to the sorted region. it involves the use of a heap data structure rather than a linear-time search to find the maximum.

Now given the initial sequence of integers, together with a sequence which is a result of several iterations of some sorting method, can you tell which sorting method we are using?

Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤100). Then in the next line, N integers are given as the initial sequence. The last line contains the partially sorted sequence of the N numbers. It is assumed that the target sequence is always ascending. All the numbers in a line are separated by a space.

Output Specification:
For each test case, print in the first line either “Insertion Sort” or “Heap Sort” to indicate the method used to obtain the partial result. Then run this method for one more iteration and output in the second line the resulting sequence. It is guaranteed that the answer is unique for each test case. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.

Sample Input 1:
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0

Sample Output 1:
Insertion Sort
1 2 3 5 7 8 9 4 6 0

Sample Input 2:
10
3 1 2 8 7 5 9 4 6 0
6 4 5 1 0 3 2 7 8 9

Sample Output 2:
Heap Sort
5 4 3 1 0 2 6 7 8 9

思路: 和上面那题思路几乎一模一样,只不过由归并排序改成了堆排序。只需要注意将堆排序规模减少的量返回出来,然后每次循环增加一次这个“规模减少量”就可以了。

需要注意的是:
堆排序模板代码本身要记清,最后交换堆顶和堆最后一个元素,那里的之后的调整只需要调整堆顶就可以了,因为只有堆顶是无序的

#include <stdio.h>
#include <iostream>


using namespace std;

const int MaxNumber = 101;

//Insert排序直接在origin上排,heap在HeapA上排序
int OriginA[MaxNumber],  HeapA[MaxNumber];
int TargetA[MaxNumber];
int flag = 0;//用来区分是哪种排序的flag,1为插入,2为堆排序

bool IsSame(int Origin[], int Target[],int N)
{	
	for (int i = 0; i < N; i++)
	{
		if (Origin[i] != Target[i])
			return false;
		else
			continue;
	}
	return true;
}


/*插入排序*/
int Insertion_sort(int A[],int N,int Times)
{	
	int P ;
	if (flag == 1)
		P = Times+1;//二次执行时,摸后面一张牌
	else
		P = Times;

	for ( P ; P < N; P++)
	{
		int Tmp;
		int i;
		Tmp = A[P];
		for (i = P; i > 0 && Tmp < A[i - 1]; i--)
			A[i] = A[i - 1];
		A[i] = Tmp;

		if (flag == 1)//若flag等于1,则说明是第二次调用排序
			return P;  //跑一轮就直接强行结束

		if (IsSame(OriginA, TargetA, N)) {
			flag = 1;//如果相同则改变flag
			return P;
		}
	}
	
	return P;
}
/*插入排序结束*/

/*堆排序*/
void Swap(int *a, int *b)
{
	int t = *a;
	*a = *b;
	*b = t;
}
void PerDown(int A[], int p, int N)
{
	int Parent, Child;
	int X;

	X = A[p];//取出根节点
	for (Parent = p; (Parent * 2 + 1) < N; Parent = Child)
	{
		Child = Parent * 2 + 1;//数组从0开始,故p*2+1才是左儿子
		if ((Child != N - 1) && (A[Child]) < A[Child + 1])
			Child++;
		if (X >= A[Child])
			break;
		else
			A[Parent] = A[Child];
	}
	A[Parent] = X;
}
int Heap_sort(int A[] ,int N , int ReduceNodes)
{
	int i;
	if(flag != 2)
		for (i = N / 2 - 1; i >= 0; i--)//建最大堆
			PerDown(A, i, N);

	for (i = N - ReduceNodes; i > 0; i--)//循环一次缩小一次规模
	{
		Swap(&A[0], &A[i]);//交换堆顶和最后一个元素
		PerDown(A, 0, i);	
		ReduceNodes++;//下一次需要再减少一个规模

		if (flag == 2)//若是第二次执行,直接跳出
			return ReduceNodes;

		if (IsSame(HeapA, TargetA, N))//若发现相等,改变flag
		{
			flag = 2;
			return ReduceNodes;
		}
	}
	return ReduceNodes;
}
/*堆排序结束*/



int main()
{
	int N;
	cin >> N;
	for (int i = 0; i < N; i++)//读取原始数组
	{
		cin >> OriginA[i];
		HeapA[i] = OriginA[i];//同时复制一份
	}
	for (int i = 0; i < N; i++)//读入目标数组
	{
		cin >> TargetA[i];
	}

	int Times , ReduceNodes;

	Times = Insertion_sort(OriginA, N,1);//初始牌号给1
	ReduceNodes = Heap_sort(HeapA, N, 1);

	//如果是insert排序
	if (flag == 1) {
		cout << "Insertion Sort" << "\n";
		Insertion_sort(OriginA, N,Times);

		for (int i = 0; i < N; i++)
		{
			if (i != N - 1)
				cout << OriginA[i] << " ";
			else
				cout << OriginA[i];
		}
	}
	//如果是heap排序
	if (flag == 2) {
		cout << "Heap Sort" << "\n";
		Heap_sort(HeapA, N, ReduceNodes);

		for (int i = 0; i < N; i++)
		{
			if (i != N - 1)
				cout << HeapA[i] << " ";
			else
				cout << HeapA[i];
		}
	}
	return 0;
}
### 插入排序归并排序的区别 插入排序是一种简单直观的排序方法,其核心思想是从左至右逐步构建有序序列。在每一步中,算法会从待排序部分选取一个元素,并将其放置到已排序部分中的适当位置[^3]。这种特性使得插入排序适合处理接近有序的数据集。 相比之下,归并排序采用分治策略来完成排序任务。它通过反复分割原始数组为较小的部分,直至每个子数组仅含单个元素(自然有序),然后再依次合并这些子数组形成更大的有序数组[^2]。这种方法能够保证即使面对无序程度较高的数据也能保持稳定的性能表现。 两者的主要区别体现在时间复杂度上:对于长度为n的列表, - **最坏情况下**,插入排序的时间复杂度为O()[^1]; - 而归并排序无论是在最好还是最坏情况下的平均时间复杂度均为O(n log n),这使其更适合大规模数据集合的操作需求[^5]。 然而,在实际应用过程中还需考虑空间消耗等因素——尽管归并排序效率更高,但它属于不稳定排序且需要额外存储空间用于临时保存被拆分出来的子数组;而插入排序则原地工作无需多余内存支持[^4]。 ### PTA题目中如何选择合适的算法? 当面临像PTA这样的编程实践平台所提供的问题时,“插入排序还是归并排序?”这类挑战可以通过分析给定条件来进行决策: 如果观察发现初始状态已经具备一定顺序特征,则可以尝试使用插入排序因为它能更高效利用现有秩序减少不必要的移动次数。反之,若输入数据较为混乱缺乏明显规律性,则应优先选用归并排序以确保稳定性和较优的整体运行效果。 另外值得注意的是具体实现细节也会影响最终判定依据。例如本题要求不仅识别当前所使用的排序方式还需要模拟下一步变化状况,这就意味着我们需要精确理解两种不同机制下各自推进逻辑差异所在以便准确预测后续发展态势。 ```python def is_insertion_sort_possible(original, intermediate): """ 判断是否可能由插入排序得到 """ sorted_part = original[:len(intermediate)] for i in range(1, len(sorted_part)): key = sorted_part[i] j = i - 1 while j >= 0 and sorted_part[j] > key: sorted_part[j + 1] = sorted_part[j] j -= 1 sorted_part[j + 1] = key return sorted_part == list(intermediate) def merge_sort_step(sequence): """ 执行一次归并排序步骤 """ length = len(sequence) step = 1 while step * 2 <= length: step *= 2 result = [] for start in range(0, length, step*2): mid = min(start+step, length) end = min(start+step*2, length) merged = _merge(sequence[start:mid], sequence[mid:end]) result.extend(merged) return result def _merge(left, right): res = [] i = j = 0 while i < len(left) and j < len(right): if left[i] <= right[j]: res.append(left[i]); i += 1 else: res.append(right[j]); j += 1 res.extend(left[i:]) res.extend(right[j:]) return res ``` 上述代码片段展示了如何检测某个中间态能否经由特定类型的排序过程达成以及执行单一阶段归并操作的方法示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值