文章目录
排序过程
将数组第一个元素作为分界点,位置为l,逐渐遍历之后的元素,判断和第一个元素的大小;l代表第一个位置,那么[l+1…j]代表小于第一个值的数组,[j+1…i-1]代表大于第一个值的数组,i代表接下来要判断的位置;当i处的值大于第一个值,则直接i++判断下一个;当i的值小于第一个值,则 j++ i++判断下一个;当i等于n+1后,j的位置即是第一个值的位置。
归并排序和快速排序的衍生问题
两种算法都使用了分治算法:将大问题分为同样的小问题,小问题解决了就能解决大问题。
但两者的区别是分组的依据不同,一个是直接一分为二,一个是按照一个数值分开。
逆序对
可以用来衡量数组的有序程度。
暴力解法:考察每一个序对 O ( n 2 ) O(n^2) O(n2)
归并排序解决:在归并过程中,如果是右边的数组要小,此时左边剩下的数和这个数都是逆序对,只要再归并过程中按组的单位记录出来。
取出数组中第n大的数组
暴力解法:排序再索引 n l o g n nlog_n nlogn
快速排序解决:用第一位进行第一次快速排序,找到位置后与n进行比较,然后只需要n所在的组进行下一次快速排序,而另一部分不包含n位置的可以直接放弃。
代码
main.cpp
#include <iostream>
#include <algorithm>
#include "SortTestHelper.h"
#include "MergeSort.h"
#include "InsertionSort.h"
using namespace std;
// 对arr[l...r]部分进行partition操作,找出p值
// 函数作用:返回p,使得arr[l...p-1] < arr[p] ; arr[p+1...r] > arr[p]
template <typename T>
int __partition(T arr[], int l, int r){
T v = arr[l]; // 比较值
int j = l; // 初始值设置为1(第一位是0),arr[l+1...j] < v ; arr[j+1...i) > v
for( int i = l + 1 ; i <= r ; i ++ ) // i是用来考察的值,知道最后一个
if( arr[i] < v ){
j ++;
swap( arr[j] , arr[i] ); // 交换大于的数组第一位和正在考察位置的值
}
swap( arr[l] , arr[j]); // l还在第一个位置,换到第j个位置上
return j; // 返回索引值
}
// 对arr[l...r]部分进行快速排序,内部递归函数
template <typename T>
void __quickSort(T arr[], int l, int r){
// 参数代表数组,初始,末尾
if( l >= r ) // 停止条件
return;
int p = __partition(arr, l, r); // 返回索引值p,p将数组分为两部分
__quickSort(arr, l, p-1 );
__quickSort(arr, p+1, r);
}
template <typename T>
void quickSort(T arr[], int n){
__quickSort(arr, 0, n-1);
}
int main() {
int n = 1000000;
cout<<"Test for Random Array, size = "<<n<<", random range [0, "<<n<<"]"<<endl;
int* arr1 = SortTestHelper::generateRandomArray(n,0,n);
int* arr2 = SortTestHelper::copyIntArray(arr1,n);
SortTestHelper::testSort("Merge Sort", mergeSort, arr1, n);
SortTestHelper::testSort("Quick Sort", quickSort, arr2, n);
delete[] arr1;
delete[] arr2;
return 0;
}
MergeSort.h
#ifndef INC_05_QUICK_SORT_MERGESORT_H
#define INC_05_QUICK_SORT_MERGESORT_H
#include <iostream>
#include <algorithm>
#include "InsertionSort.h"
using namespace std;
template<typename T>
void __merge(T arr[], int l, int mid, int r){
T aux[r-l+1];
for( int i = l ; i <= r; i ++ )
aux[i-l] = arr[i];
int i = l, j = mid+1;
for( int k = l ; k <= r; k ++ ){
if( i > mid ) {
arr[k] = aux[j-l]; j ++;}
else if( j > r ){
arr[k] = aux[i-l]; i ++;}
else if( aux[i-l] < aux[j-l] ){
arr[k] = aux[i-l]; i ++;}
else {
arr[k] = aux[j-l]; j ++;}
}
}
template<typename T>
void __mergeSort(T arr[], int l, int r){
if( r - l <= 15 ){
insertionSort(arr, l, r);
return;
}
int mid = (l+r)/2;
__mergeSort(arr, l, mid);
__mergeSort(arr, mid+1, r);
if( arr[mid] > arr[mid+1] )
__merge(arr, l, mid, r);
}
template<typename T>
void mergeSort(T arr[], int n){
__mergeSort( arr , 0 , n-1 );
}
#endif //INC_05_QUICK_SORT_MERGESORT_H
InsertionSort.h
#ifndef INC_05_QUICK_SORT_INSERTIONSORT_H
#define INC_05_QUICK_SORT_INSERTIONSORT_H
#include <iostream>
#include <algorithm>
using namespace std;
template<typename T>
void insertionSort(T arr[], int n){
for( int i = 1 ; i < n ; i ++ ) {
T e = arr[i];
int j;
for (j = i; j > 0 && arr[j-1] > e; j--)
arr[j] = arr[j-1];
arr[j] = e;
}
return;
}
// 对arr[l...r]范围的数组进行插入排序
template<typename T>
void insertionSort(T arr[], int l, int r){
for( int i = l+1 ; i <= r ; i ++ ) {
T e = arr[i];
int j;
for (j = i; j > l && arr[j-1] > e; j--)
arr[j] = arr[j-1];
arr[j] = e;
}
return;
}
#endif //INC_05_QUICK_SORT_INSERTIONSORT_H
SortTestHelper.h
#ifndef INC_05_QUICK_SORT_ANOTHER_PARTITION_SORTTESTHELPER_H
#define INC_05_QUICK_SORT_ANOTHER_PARTITION_SORTTESTHELPER_H
#include <iostream>
#include <algorithm>
#include <string>
#include <ctime>
#include <cassert>
using namespace std;
namespace SortTestHelper {
int *generateRandomArray(int n, int range_l, int range_r) {
int *arr = new int[n];
srand(time(NULL));
for (int i = 0; i < n; i++)
arr[i] = rand() % (range_r - range_l + 1) + range_l;
return arr;
}
int *generateNearlyOrderedArray(int n, int swapTimes){
int *arr = new int[n];
for(int i = 0 ; i < n ; i ++ )
arr[i] = i;
srand(time(NULL));
for( int i = 0 ; i < swapTimes ; i ++ ){
int posx = rand()%n;
int posy = rand()%n;
swap( arr[posx] , arr[posy] );
}
return arr;
}
int *copyIntArray(int a[], int n){
int *arr = new int[n];
copy(a, a+n, arr);
return arr;
}
template<typename T>
void printArray(T arr[], int n) {
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
template<typename T>
void printArray(T arr[], int l, int r) {
for (int i = l; i <= r; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
template<typename T>
bool isSorted(T arr[], int n) {
for (int i = 0; i < n - 1; i++)
if (arr[i] > arr[i + 1])
return false;
return true;
}
template<typename T>
void testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) {
clock_t star