HDUOJ #2020 绝对值排序+总结排序

本文详细介绍了几种常见的排序算法,包括插入排序、希尔排序、选择排序、堆排序、冒泡排序、快速排序、归并排序和基数排序等。文章通过具体实例展示了每种排序算法的工作原理,并分析了它们的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

拿到这道题看着很简单,可是却很难下手,把之前学的排序什么的都忘得差不多了

所以又回去复习一下排序算法,在这总结一下。

首先定义排序算法中的抽象数据类型,例子中keytype是int型

struct DataType{
    KeyType key;
};

1.插入排序(从初始有序的子集合开始不断把新的数据元素插入已排列有序子集合的合适位置)

1.1直接插入排序(顺序插入,倒着比)

void InsertSort(DataType a[],int n)
{
	int i,j;
	DataType temp;
	for(i=0;i<n-1;i++){
		temp=a[i+1];
		j=i;
		while(j>-1 && temp.key<a[j].key){
			a[j+1]=a[j];
			j--;
		}
		a[j+1]=temp;
	}
}

1.2希尔排序(分组用直接插入法,小组的个数逐次缩小)

void ShellSort(DataType a[],int n,int d[],int numOfD) //d[]为增量数组
{
	int i,j,k,m,span;
	DataType temp;
	for(m=0;m<numOfD;m++){
		span=d[m];
		for(k=0;k<span;k++){   //span个小组
			for(i=k;i<n-span;i=i+span){ //增量是span而不是1
				temp=a[i+span];
				j=i;
				while(j>-1&& temp.key<a[j].key){
					a[j+temp]=a[j];
					j=j-span;
				}
				a[j+span]=temp
			}
		}
	}
}

2.选择排序(待排数组中选取最小(大)的放到最前(后)面)

2.1 直接选择排序

void SlectSort(DataType a[],int n){
	int i,j,small;
	DataType temp;

	for(i=0;i<n-1;i++){
		small=i;   //small是最小值的位置
		for(j=i+1;j<n;j++){
			if(a[j].key<a[small].key){small=j;}
		}//在i+1-n之间选择最小的

		if(small!=i){
			temp=a[i];              //交换i和最小的
			a[i]=a[small];
			a[small]=temp;
		}
	}
}

2.2堆排序

首先创建最大堆,从也在节点开始看,每个分叉,最大值都要在根节点上,从而调整。

排序:堆顶a[0]和当前最大堆的最后一个元素互换,最大堆个数减一;

代码比较复杂,暂时不贴上来。


3.交换排序

3.1冒泡排序

n个数据,循环n-1躺,每一趟比较相邻元素,逆序则交换,最后一个值为最大值,数组长度减一,再走一趟

void BubbleSort(DataType a[],int n){
	int i,j,flag=1;
	DataType temp;

	for(i=1;i<n&&flag==1;i++){
		flag=0;  //有交换的即为1,没交换说明顺序排好了

		for(j=0;j<n-i;j++){ //相当于末尾i-1个数排好顺序了,因为交换i-1和i交换,所欲只需要走到i-1;
			if(a[j].key>a[j+1].key){
				flag=1;
				temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp;
			}
		}
	}
}

3.2快速排序

二叉树结构的交换排序

void QuickSort(DataType a[],int low,int high){
	int i=low,j=high;
	DataType temp=a[low];

	while(i<j){ //low<high的时候
		while(i<j&&temp.key<=a[j].key)j--;    //从数组右端开始扫描
		if(i<j){
			a[i]=a[j];
			i++;
		}

		while(i<j&& a[i].key<temp.key)i++; // 扫描左端
		if(i<j){
			a[j]=a[i];
			j--;
		}
	}
	a[i]=temp;
	if(low<i)QuickSort(a,low,i-1);
	if(i<high)QuickSort(a,j+1,high);
}

4.归并排序

主要是二路归并排序

5.基数排序(分好桶,桶中数据先进先出,对数的每一位做模运算。)


稳定的排序:直接插入排序,冒泡排序,归并排序,基数排序

时间优的排序:堆排序,快速排序,归并排序  O(nlog2n)


#2020

在比较的时候加上abs()函数

#include<iostream>
#include<string>
using namespace std;

int shu[106];

void QuickSort(int a[],int low,int high){
	int i=low,j=high;
	int temp=a[low];

	while(i<j){ //low<high的时候
		while(i<j&&abs(temp)<=abs(a[j]))j--;    //从数组右端开始扫描
		if(i<j){
			a[i]=a[j];
			i++;
		}

		while(i<j&& abs(a[i])<abs(temp))i++; // 扫描左端
		if(i<j){
			a[j]=a[i];
			j--;
		}
	}

	a[i]=temp;
	if(low<i)QuickSort(a,low,i-1);
	if(i<high)QuickSort(a,j+1,high);
}

int main()
{
	int n,t;
	int flag=0;
	while(cin>>n &&n){
		for(int i=0;i<n;i++){
			cin>>shu[i];
		}
		

		QuickSort(shu,flag,n-1);

		for(int i=n-1;i>0;i--){
			cout<<shu[i]<<" ";
		}
		cout<<shu[0]<<endl;
	}

}


 


### 关于2020绝对值排序的快速排序算法实现与分析 #### 快速排序算法概述 快速排序是一种基于分治法的高效排序算法。该算法通过选择一个基准元素(pivot),将待排序序列划分为两部分,一部分小于等于基准值,另一部分大于基准值,之后递归地对这两部分继续执行相同的操作直到整个序列有序。 对于特定场景下的优化版本——针对绝对值排序问题,可以通过调整比较逻辑来适应需求。在处理绝对值排序时,主要关注数值大小而非正负号的影响[^1]。 #### 时间复杂度分析 通常情况下,如果输入数据接近随机分布,则快速排序表现出良好的性能特征,具有较好的期望时间复杂度\( O(n\ log\ n)\)。然而,在某些特殊情形下,比如已经完全升序或降序排列的数据集上,若总是选取第一个或最后一个元素作为枢轴点(pivot),则可能导致最差情况的发生,此时的时间复杂度会退化到 \(O(n^{2})\) 。为了避免这种情况发生,可以选择更合理的策略挑选枢纽元,例如三数取中法或是随机选取等方法。 #### 空间复杂度考量 尽管快速排序属于就地(in-place)排序方式之一,意味着理论上不需要额外分配大量辅助存储空间;但由于采用了递归来完成子数组分割过程,所以实际上还是需要用到一定量的栈内存用于保存每次调用的状态信息。理想状态下所需的空间开销大约为 \(O(\log\ n)\),但在极端条件下可能会增长至线性级别即 \(O(n)\)[^1]。 #### 不稳定性的解释 值得注意的是,由于存在元素互换操作,使得原本相等项之间的相对顺序可能发生变化,故而快速排序并不保证稳定性。这意味着如果有多个相同的键值存在于列表之中,它们原始次序未必能在最终结果里得以保持不变。 #### C++代码实例展示 下面给出一段适用于解决“2020 绝对值排序”的C++程序片段: ```cpp #include <iostream> #include <vector> using namespace std; // 定义按绝对值比较函数对象 struct AbsCompare { bool operator()(int a, int b){ return abs(a)<abs(b); } }; void quickSort(vector<int>& nums,int low ,int high){ if(low >=high )return ; // 随机选取中间节点并交换到low处 srand((unsigned)time(NULL)); int randIndex=low+rand()%(high-low+1); swap(nums[randIndex],nums[low]); int pivot = nums[low]; int i = low; for(int j=low+1;j<=high;++j){ if(abs(nums[j])<abs(pivot)){ ++i; swap(nums[i],nums[j]); }else if(abs(nums[j])==abs(pivot)&&nums[j]<pivot){ ++i; swap(nums[i],nums[j]); } } swap(nums[low],nums[i]); quickSort(nums,low,i-1); quickSort(nums,i+1,high); } int main(){ vector<int> data={-7,-9,5,6,-3}; cout<<"Before sorting:"<<endl; for(auto& num :data ) cout<<num<<"\t"; cout<<endl; quickSort(data,0,data.size()-1); cout<<"After sorting by absolute value:"<<endl; for(auto &num:data) cout<<num<<"\t"; cout<<endl; } ``` 此段代码实现了带有自定义比较器`AbsCompare`结构体以及改进版分区方案的快速排序功能,能够有效地按照整型变量的绝对值从小到大进行重排,并且加入了简单的测试样例验证效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值