基于排序算法的特性划分的排序

一.基于排序算法的特性,大概可分为以下三种

二.例题

1.线性排序

输入 :

5 3

1 -4 6 -3 5

输出:

6 5 1

分析题目:基于比较的排序的算法f时间复杂度为O(nlogn),给定范围的线性排序需要O(n);

本题元素给定了范围,所有的值都在[-500000,500000],则本题可通过线性排序来实现。以后做题时需注意排序的数据是否有范围哦!

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring> 

using namespace std;

const int MAXN = 1e6 + 10;
const int RANGE = 5e5;

int arr[MAXN];
int number[MAXN];
int main(){
	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF){
		//清空数组中的数据,以防上次的数据残留 
		memset(number,0,sizeof(number)) ;
		//输入一组数 
		for(int i = 0; i < n; ++i){
			scanf("%d",&arr[i]);
            //数组下标是从0开始,所以这里每个数据+500000,则可以保证最小的数为0
			number[arr[i]+RANGE]++;
		}
		//处理数据 
		int index = 0;
		for(int i = 0; i < MAXN; ++i){
			while(number[i]--){
                //恢复成它原来输入的数据
				arr[index++] = i - RANGE;
			}
		}
		//输出数据 
		for(int i = n-1;i >= n-m;--i){
			if(i==n-m){
				printf("%d\n",arr[i]);
			}else{
				printf("%d ",arr[i]);
			}
		} 
	}
	return 0;
} 

2.逆序数对

输入:

4

4 2 8 0 3

10 0 1 2 3 4 5 6 7 8 9

6 -42 23 6 28 -100 65537

5 0 0 0 0 0

输出:(用的devc++,输出就是这样)

分析:理解归并排序是重点!!!

下面是动态图:

代码如下:

#include<iostream>
#include<cstdio>

using namespace std;

const int MAXN=1010; 

int arr[MAXN];
int temp[MAXN];
int number;
//合并 
void Combine(int left,int middle,int right){
	int i = left;
	int j = middle + 1;
	int k = left;
	while(i <= middle && j <= right){
		if(arr[i] <= arr[j]){
			temp[k++] = arr[i++];
		}else{
			//求逆序对的数目 
			number += middle-i+1;
			temp[k++] = arr[j++];
		}
	}
	//处理左边和右边剩余的数据 
	while(i <= middle){
		temp[k++] = arr[i++];
	}
	while(j <= right){
		temp[k++] = arr[j++];
	}
	for(k = left; k <= right; ++k) {
		arr[k] = temp[k];
	}
	return;
} 
//排序 
void MergeSort(int left,int right){
	if(left < right){
		//这种写法容易导致溢出当left和right都比较接近整型上界时 
		//int middle = (left+right) / 2;
		int middle = left + (right - left) / 2;
		MergeSort(left, middle);
		MergeSort(middle + 1, right);
		Combine(left, middle, right);
	}
	return;
}
int main(){

	int caseNumber;
	scanf("%d",&caseNumber);
	for(int current = 1; current <= caseNumber; ++current){
		int n;
	    scanf("%d",&n);
    	for(int i = 0; i<n; ++i){
		   scanf("%d",&arr[i]);
    	} 
    	number = 0;
    	//进行归并排序 
	    MergeSort(0,n-1);
	    printf("Scenario #%d:\n",current);
	    //输出逆序对的数目 
    	printf("%d\n\n",number);
	}
	return 0;
}

3.第K大数

主要运用了快速排序的思想!

下面来看一下快速排序的动态图,有助于更好的理解。

下面是求第K大数的代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>

using namespace std;

int arr[100];

int Partition(int left, int right){
	//生成一个(在左和右之间)随机值 ,即中心值 
	int random = left + rand() % (right - left);
	//交换最左端的和随机值 
	swap(arr[left], arr[random]); 
	//循环,把大的放到右边,把小的放在中心值得左边 
	while(left < right){
		//当左边的值小于等于右边的值时,右指针左移 
		while(left < right && arr[left] <= arr[right]){
			--right;
		}
		//直到不能移动时,即左边的值大于右边的,则交换 ,此时中心值在右边 
		swap(arr[left], arr[right]);
	    //当左边的值小于等于右边的值时,左指针右移 
		while(left < right && arr[left] <=arr[right]){
			++left;
		}
		//直到不能移动时,即左边的值大于右边的,则交换
		swap(arr[left], arr[right]);
	}
	//最后左指针和右指针指向同一个地方 
	return left;
}

int QuickSort(int left, int right, int k){
	if(left < right){
		int position = Partition(left, right);
		//比较位置,确定找的范围 
		if (position == k - 1){
		    return arr[position];	
		} else if (position < k - 1){
			return QuickSort(position + 1,right,k);
		} else {
			return QuickSort(left,position - 1,k);
		}
	
	}
}


int main(){
	//输入数据 
	int n;
	scanf("%d",&n);
	for(int i = 0; i < n; ++i){
		scanf("%d",&arr[i]);
	}
	//获取第K大的数 
	int k;
	scanf("%d",&k);
	//输出结果 
    printf("%d\n",QuickSort(0,n-1,k));
	return 0; 
} 

附十大经典排序算法动态图和代码链接:https://www.cnblogs.com/onepixel/articles/7674659.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值