《数据结构和算法》【数组元素排序】

概述

通过这篇博文,你将清楚的知道如何对无序数组进行排序。
我会讲的很清晰透彻,完整。
有C/C++的代码附上给你参考,如果你不会C/C++,没关系,只要看下去,你一定能用自己掌握的语言写出解决代码。

问题描述

数组a中的元素无序,要求将a中的元素由小到大排序。

解决方法

先求出该数组中每个元素的名次,再根据名次进行排序。

名次求解法

1.要想得到每个元素的名次,首先要知道什么是一个元素的名次。一个元素的名次是所有比它小的元素以及在它左边出现的与它相同的元素个数。比如:数组a[]={3,7,8,7,2},各元素的排名如下(由小到大)r[]={1,2,4,3,0}。这就是元素的名次。
2.然后,根据名次的定义按照一个方法求解。
以数组a为例:3 7 8 7 2。
每一个元素都需要与其它元素比较,根据大小,在r中的对应下标位置++,所以,在这之前,r需要将元素初始化为0.
从下标为0的元素开始,下标为1、2、3、4的元素进行比较,如果a[0]更大,则r[0]++,否则,让下标为i的元素对应的名次r[i]++。在这一轮比较中,a[0]与所有元素都比较了,而所有元素也都与a[0]比较了。所以,在下一轮,a[1]只需要与之后的元素进行比较,不需要与a[0]进行比较了。
3.现在,让我们把2中介绍的比较方法稍微变通一下。
第一轮:a[0]与a[1]比较
第二轮:a[0]与a[2]比较,a[1]与a[2]比较
第三轮:a[0]、a[1]、a[2]与a[3]比较
第四轮:a[0]、a[1]、a[2]、a[3]与a[4]比较
这样也能完成比较,你是不是发现了这就是2中介绍的方法的倒版?

名次求解的C++代码实现

2和3中介绍的方法都可以用代码实现,这里实现3中的代码。有兴趣可以尝试实现2中的代码,只需要让i从0开始,让j从大于i开始

template<class T>
void rank(T a[], int len, int r[])
{
	int i = 0;
	//首先,让r中的元素初始化为0
	for (i; i < len; ++i)
		r[i] = 0;
	//开始排序
	for (i = 1; i < len; ++i)
	{
		for (int j = 0; i < i; ++j)
		{
			if (a[j] <= a[i])//所有比它小的元素以及在它左边出现的与它相同的元素个数
				++r[i];
			else
				++r[j];
		}
	}
}

名次求解总比较次数计算

外层for循环执行len-1次。
内层for循环第一次执行1次(这时i为1),最后一次执行len-1次(这时i为len-1)。所以,平均下来,内层for循环每次执行(len-1+1)/2=len/2。
总的比较次数是:(len-1)*len/2。

根据求得的名次排序

求得名次是为了排序,那么,怎么根据名次来排序呢?
要解决这个问题,首先,要知道什么是排序。先观察一个顺序序列:
a[5]={1,2,3,4,5}。下标是0的元素排序是0,下标是1的元素排序是1,a[2]排序是2,…,下标是n的元素排序是n。
没错,你发现了,下标就对应着元素的名次。而名次,刚才已经得到了,只需要根据这个名次来重新排序。为此,我们需要一个新的数组,让新的数组每个下标都对应着一个值,也就是名次,再让这个名次等于相应的值。
举例如下:
数组a[3,7,8,7,2],各元素的排名如下(由小到大)r=[1,2,4,3,0]。
新的数组temp。temp[1]=a[0],temp[2]=a[1],temp[4]=a[2],
temp[3]=a[3],temp[0]=a[4]。
接下来,换一种方式表示:
temp[r[0]]=a[0],temp[r[1]]=a[1],temp[r[2]]=a[2],
temp[r[3]]=a[3],temp[r[4]]=a[4]。
数组r中已经存储了数组a中对应下标位的名次,相同的下标,就能表示要求得的有序序列temp的下标和值。

根据名次排序的C++代码实现

template<class T>
void sortByRank(T a[], int len, int r[])
{
	T * tempArr = new T[len];
	int i = 0;
	//把a中的元素按照名次赋值给tempArr
	for (i; i < len; ++i)
		tempArr[r[i]] = a[i];
	for (i = 0; i < len; ++i)
		a[i] = tempArr[i];
	delete[] tempArr;
}

总的时间复杂度计算

rank中,总的比较次数是:(len-1)*len/2。
在sortByRank中,总的移动次数是2len次。
所以,完成排序需要(len-1)*len/2次比较和2len次元素移动。
所以,时间复杂度为:
(len-1)*len/2=O(len2)

最后,给出完整的代码,你可以在vs2013中直接运行

#include "stdafx.h"
#include<iostream>
using namespace std;
template<class T>
void rank(T a[], int len, int r[])
{
	int i = 0;
	//首先,让r中的元素初始化为0
	for (i; i < len; ++i)
		r[i] = 0;
	//开始排序
	for (i = 1; i < len; ++i)
	{
		for (int j = 0; j < i; ++j)
		{
			if (a[j] <= a[i])
				++r[i];
			else
				++r[j];
		}
	}
}

template<class T>
void sortByRank(T a[], int len, int r[])
{
	T * tempArr = new T[len];
	int i = 0;
	//把a中的元素按照名次赋值给tempArr
	for (i; i < len; ++i)
		tempArr[r[i]] = a[i];
	for (i = 0; i < len; ++i)
		a[i] = tempArr[i];
	delete[] tempArr;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int a[5] = { 3, 7, 8, 7, 2 };
	int len = 5;
	int r[5] = { 0, 0, 0, 0, 0 };
	cout << "排序前:" << endl;
	for (int i = 0; i < len; ++i)
		cout << a[i] << ' ';
	cout << endl;
	::rank(a, len, r);
	cout << "名次:" << endl;
	for (int i = 0; i < len; ++i)
		cout << r[i] << ' ';
	cout << endl;

	::sortByRank(a, len, r);
	cout << "排序后:" << endl;
	for (int i = 0; i < len; ++i)
		cout << a[i] << ' ' ;
	cout << endl;
	return 0;
}

如果你发现了问题,请评论或者私信

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中,可以使用以下几种方法对数据进行降序排序: 1. 使用Arrays.sort()方法: Java的Arrays类提了一个sort(),可以对数组进行排序。要实现降序排序,可以使用Comparator.reverseOrder()方法作为参数传递sort()方法。 示例代码如下 ```java import java.util.Arrays; import java.util.Comparator; public Main { public static void main(String[] args) { Integer[] arr = {5, 2, 8, 1, 6}; Arrays.sort(arr, Comparator.reverseOrder()); System.out.println(Arrays.toString(arr)); } } ``` 2. 使用Collections.sort()方法: 如果要对集合进行排序,可以使用Java的Collections类的sort()方法。同样地,可以使用Comparator.reverseOrder()方法作为参数传递给sort()方法。 示例代码如下: ```java import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(5); list.add(2); list.add(8); list.add(1); list.add(6); Collections.sort(list, Comparator.reverseOrder()); System.out.println(list); } } ``` 3. 自定义Comparator: 可以自定义一个Comparator类来实现降序排序。Comparator接口有一个compare()方法,可以根据自定义的比较规则对元素进行排序。 示例代码如下: ```java import java.util.Arrays; import java.util.Comparator; public class Main { public static void main(String[] args) { Integer[] arr = {5, 2, 8, 1, 6}; Arrays.sort(arr, new DescendingComparator()); System.out.println(Arrays.toString(arr)); } } class DescendingComparator implements Comparator<Integer> { @Override public int compare(Integer a, Integer b) { return b - a; } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值