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

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

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

首先定义排序算法中的抽象数据类型,例子中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;
	}

}


 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
绝对值排序的概念通常涉及到将一组数字按照它们的绝对值大小进行升序或降序排列。在C++中,实现这一功能的关键步骤包括读取输入、计算每个数的绝对值、进行排序并输出结果。 ### C++ 程序示例 下面是一个简单的C++程序,演示如何对一组整数数组按照其绝对值进行排序: ```cpp #include <iostream> #include <vector> #include <algorithm> // For sort function and abs() #include <cmath> // For fabs() which is used for float numbers int main() { int n; std::cout << "请输入元素数量: "; std::cin >> n; std::vector<double> nums(n); std::cout << "请输入" << n << "个数值: "; // 输入数值 for (int i = 0; i < n; ++i) { std::cin >> nums[i]; } // 使用abs函数转换成绝对值,并使用sort函数排序 std::sort(nums.begin(), nums.end(), [](double a, double b){ return std::fabs(a) < std::fabs(b); // 按照绝对值排序 }); std::cout << "按绝对值排序后的数组为: \n"; for (const auto &num : nums) { std::cout << num << " "; } std::cout << "\n"; return 0; } ``` ### 运行说明: 1. **输入元素数量**: 首先提示用户输入元素的数量`n`。 2. **输入数据**: 用户随后可以输入这`n`个数。 3. **绝对值排序**: - 数组内的每个数使用`std::fabs()`(对于双精度浮点数)或`std::abs()`(对于整型数)计算其绝对值。 - 利用`std::sort`标准库函数,通过提供自定义比较器,按照绝对值的大小进行排序。 4. **输出排序后的数组**: - 打印出排序后的数组。 ### 相关问题: 1. 如何确定程序是否正确实现了绝对值排序的功能? 2. 如果需要处理负数和零的情况,程序应该如何优化? 3. 当数组非常大时,如何考虑性能优化问题? --- 请尝试运行上述代码以理解其工作原理,并根据实际需求调整输入和输出部分以适应各种情况。如果在理解和实现过程中遇到困难,可以进一步提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值