前言
整理下排序的算法模板。
一、快速排序
1. 思想
对元素在排序后的位置进行定位。 比如倒序排序时,对一个元素定位的策略为:大于该元素则放到元素左侧,小于该元素则放到元素右侧。一次定位一个元素,定位所有元素后整个数组变有序。
2. 模板
public class QuickSort {
/**
* 数组元素交换位置
*/
public void swap(int[] score,int left ,int right) {
int temp = score[left];
score[left] = score[right];
score[right] = temp;
}
/**
* 定位一个元素位置,并返回
*/
public int locate(int[] nums, int left, int right) {
int key = left;
while (true) {
while (left == key && left < right && nums[right] <= nums[key]) {
right--;
}
while (right == key && left < right && nums[left] >= nums[key]) {
left++;
}
if (left == right) {
break;
}
swap(nums, left ,right);
if (key == right) {
key = left;
} else {
key = right;
}
}
return key;
}
/**
* 递归排序
*/
public void sort(int[] nums, int left, int right) {
if (left >= right) {
return;
}
int key = locate(nums, left,right);
sort(nums,left,key-1);
sort(nums, key + 1, right);
}
/**
* 测试--倒序排序
*/
public static void main(String[] args) {
int[] arr = new int[] {10,3,8,9,4};
QuickSort quickSort = new QuickSort();
quickSort.sort(arr, 0 , arr.length - 1);
for (int i : arr) {
System.out.print(i + " ");
}
}
}
还有种写法(从小到大排序)
static BiPredicate<int[], int[]> function = (int[] a, int[] b) -> a[0] > b[0] || a[0] == b[0] && a[1] > b[1];
public static int locate(int[][] points, int left, int right) {
while (left < right) {
while (function.test(points[right], points[left])) {
right--;
if (left >= right) {
return left;
}
}
swap(left, right, points);
while (function.test(points[right], points[left])) {
left++;
if (left >= right) {
return left;
}
}
swap(left, right, points);
right--;
}
return left;
}
3. 参考
二、归并排序
例题:Ultra-QuickSort poj2299
直接冒泡会超时,交换次数太多。采用归并排序省略交换过程,直接排序。
题目实际要求求逆序对的个数,在归并排序的过程中记录一个逆序对交换位置需要交换的次数
如:
a1 数组 4 6 8
a2 数组 1 5 7
4,1逆序,需要交换三次(4后面两个数以及与1交换)
6,5逆序,需要交换两次(6后面一个以及与5交换)
8,7逆序,交换一次(8与7交换)
共六次
主要就是归并排序的思想,并在这个过程中计数。
#include<iostream>
using namespace std;
int arr[500001];
int s[500001];
long long int cnt = 0;
void merSort(int start, int mid, int end){
int m, n;
int c = end - start + 1;
m = start; n = mid + 1;
int i = start;
while (m <= mid&&n <= end){
if (arr[m] <= arr[n]){
s[i++] = arr[m++];
}
else {
s[i++] = arr[n++];
cnt += mid - m + 1;
}
}
while (m <= mid)s[i++] = arr[m++];
while (n <= end)s[i++] = arr[n++];
for (int j = start; j <= end; j++){
arr[j] = s[j];
}
}
void Sort(int start, int end){
if (start < end){
int mid = (start + end) / 2;
Sort(start, mid);
Sort(mid + 1, end);
merSort(start, mid, end);
}
}
int main()
{
int n;
while (cin >> n&&n){
cnt = 0;
for (int i = 0; i < n; i++)scanf("%d", &arr[i]);
Sort(0, n - 1);
cout << cnt << endl;
}
return 0;
}