冒泡排序
/**
* 冒泡排序
* 最坏时间复杂度:O(n^2)
* 平均时间复杂度:O(n^2)
* 空间复杂度:O(1)
* 算法稳定度:稳定
*/
template<class T>
void bubbleSort(T* start, T* end){
if(start >= end) return;
for(T* i = start; i != end; i++){
for(int j = 0; j <= int(end-i)-1; j++){
if(start[j] > start[j+1]) swap(start[j], start[j+1]);
}
}
}
选择排序
/**
* 选择排序
* 最坏时间复杂度:O(n^2)
* 平均时间复杂度:O(n^2)
* 空间复杂度:O(1)
* 算法稳定度:不稳定
*/
template<class T>
void selectSort(T* start, T* end){
if(start >= end) return;
for(T* i = start; i != end; i++){
int index = int(i-start);
for(int j = int(i-start); j <= int(end-i); j++){
if(start[j] > start[index]) index = j;
}
if(index != int(i-start)) swap(start[index], start[int(i-start)]);
}
}
插入排序
/**
* 插入排序
* 最坏时间复杂的:O(n^2)
* 平均时间复杂度:O(n^2)
* 空间复杂度:O(1)
* 算法稳定度:稳定
*/
template<class T>
void insertSort(T* start, T* end){
for(int i = 1; i <= int(end-start); i++){
int value = start[i], j = i;
for(; j-1 >= 0 && value < start[j-1]; j--){
start[j] = start[j-1];
}
start[j] = value;
}
}
归并排序
/**
* 归并排序
* 最坏时间复杂度:O(nlogn)
* 平均时间复杂度:O(nlogn)
* 算法稳定性:稳定
*/
template<class T>
void mergeSort(T* start, T* end, T* tmp){
if(start < end -1){
int mid = int(end - start) / 2;
int left = 0;
int right = mid+1;
int index = 0;
mergeSort(start, start+mid, tmp);
mergeSort(start+mid+1, end, tmp);
while(left <= mid && right <= int(end-start)){
if(start[left] <= start[right]) tmp[index++] = start[left++];
else tmp[index++] = start[right++];
}
while(left <= mid){
tmp[index++] = start[left++];
}
while(right <= int(end-start)){
tmp[index++] = start[right++];
}
for(int i = 0; i < index; i++){
start[i] = tmp[i];
}
}else if(start == end-1){
if(start[0] > start[1]) swap(start[0], start[1]);
}
}
希尔排序
/*
* 希尔排序
* 最坏时间复杂度:
* 不稳定
*/
template<class T>
void shellSort(T* start, T* end){
for(int i = int(end-start)/2; i >= 1; i/=2){
for(int j = i; j <= int(end-start); j++){
int value = start[j], k = j;
for(; k-i >= 0 && start[k-i] > value; k-=i){
start[k] = start[k-i];
}
start[k] = value;
}
}
}
堆排序
/*
* 堆排序
* 时间复杂度:nlogn
* 稳定性:稳定
*/
template<class T>
void MaxHeapify(int curr, T* array, int size){
if(curr >= size) return;
int lchild = curr*2+1; //左右子树
int rchild = lchild+1;
while(rchild < size){
//如果比左右子树都小的话,完成整理
if(array[curr] >= array[lchild] && array[curr] >= array[rchild])
return;
if(array[lchild] > array[rchild]){//左子树比较大
swap(array[lchild], array[curr]);
curr = lchild;
}else{
swap(array[rchild], array[curr]);//右子树比较大
curr = rchild;
}
lchild = curr*2+1;
rchild = lchild+1;
}
//最后一个元素只有左子树的情况
if(lchild < size && array[curr] < array[lchild]) swap(array[curr], array[lchild]);
}
template<class T>
void heapSort(T* array, int size){
if(size < 1) return;
for(int i = size-1; i >= 0; i--)
MaxHeapify(i, array, size);
while(size > 1){
swap(array[0], array[size-1]);
MaxHeapify(0, array, --size);
}
}
快速排序
/**
* 快速排序
* 时间复杂度:nlogn
* 稳定性:不稳定
*/
template<class T>
T getP(T* start, T* end){
int mid = int(end-start)/2;
int left = 0, right = int(end-start);
if(start[left] > start[mid]) swap(start[left], start[mid]);
if(start[left] > start[right]) swap(start[left], start[right]);
if(start[mid] > start[right]) swap(start[mid], start[right]);
return start[mid];
}
template<class T>
void quickSort(T* start, T* end){
if(start <= end-2){
int left = 1, right = int(end-start)-2;
int mid = int(end-start)/2;
int p = getP(start, end);
swap(start[mid], start[int(end-start)-1]);
while(1){
//无需在循环中检测越界
while(start[left] < p){left++;}
while(start[right] > p){right--;}
if(left < right) swap(start[left], start[right]);
else break;
}
//为什么结束后和left坐标的值交换呢,是因为循环结束后,left处的值肯定大于p,
//而且left左边的肯定小于p,右边的肯定大于p
swap(start[left], start[int(end-start)-1]);
quickSort(start, start+left-1);
quickSort(start+left+1, end);
}else
getP(start, end);
}
计数排序
/*
* 计数排序 (空间换时间)
* 时间复杂度:O(n)
*/
template<class T>
void countingSort(T* array, int length){
//找到最大的值
int max = 0;
for(int i = 0; i < length; i++)
max = (max < array[i]) ? array[i] : max;
//开辟空间并初始化
T* indexs = new T[max+1];
for(int i = 0; i < max+1; i++)
indexs[i] = 0;
//把待排序的数装入桶
for(int i = 0; i < length; i++)
indexs[array[i]]++;
//对桶进行标号
for(int i = 1; i < max+1; i++)
indexs[i] += indexs[i-1];
//倒出结果
T result[length];
for(int i = 0; i < length; i++){
result[--indexs[array[i]]] = array[i];
}
for(int i = 0; i < length; i++)
array[i] = result[i];
}
基数排序
/*
* 基数排序
* 时间复杂度:d(n+r)
*/
template<class T>
void radixSort(T* array, int length){
T tmp[length];
//找到所有数字中最大位数的数
int max = 0;
for(int i = 0; i < length; i++){
int number = array[i];
if(number < 0) number*=-1;
max = (max < number) ? number : max;
}
//计算多少位
int indexs = 0;
if(max == 0) indexs = 1;
else
while(max){
max /= 10;
indexs++;
}
for(int j = 0; j < indexs; j++){
vector<T> buck[20]; //桶 要考虑负数的情况
int bit = 10;
for(int k = 0; k < j; k++) bit*=10;
//按照位数进行装桶
for(int i = length-1; i >= 0; i--){
int number = 0;
//j位的数求j位的时候
if(!(array[i]/bit) && (array[i]/(bit/10))) number = array[i]/(bit/10);
else{
number = array[i] - (array[i]/bit * bit);
if(j != 0) number = number / (bit/10);//去掉第一位的情况
}
number+=9; //统统加9,这样就能包括负数的情况了
buck[number].push_back(array[i]);
}
//将各位排好序的数按顺序倒出来
int index = length-1;
for(int i = 19; i >= 0; i--)
for(int m = 0; m < buck[i].size(); m++)
array[index--] = buck[i][m];
}
}
经典例题
对一个序列排序,并求得排序后两数间最大差值
应用桶排序思想,找到最大数和最小数,
然后n个数,给定n个桶,第一个桶的范围是[min, min+(max-min)/n]
然后往下依次是[min+(max-min)/n*i, min+(max-min)/n*(i+1)]
最后一个的是范围是[min+(max-min)/n*(n-1), max],
这样正好把所有的数都包括进来,每个桶内的数差值肯定小于
两个桶之间数的差值,我们找前一个桶的最大值和后一个桶的最小值
来比较,这样就能求得排序后最大的差值
int shortestSubsequence(vector<int> rect, int n){
if(n < 2) return 0;
double min = rect[0], max = rect[0];
for(int i = 0; i < int(rect.size()); i++){
min = min > rect[i] ? rect[i] : min;
max = max < rect[i] ? rect[i] : max;
}
//初始化桶
vector<vector<int> > buck;
for(int i = 0; i < n+1; i++){
vector<int> v;
buck.push_back(v);
}
double value = (max-min)/n;
for(int i = 0; i < n; i++){//装桶
for(int j = 0; j < n; j++){//遍历桶,合适就装进去
double left = double(min + value*double(j));
double right = double(min + value*double(j+1));
if(double(rect[i]) >= left && double(rect[i]) <= right){
buck[j].push_back(rect[i]);
break;
}
}
}
//找最大差值
min = -1, max = -1;
int result = 0;
for(int i = 0; i < n+1; i++){
if(max != -1){
for(int k = 0; k < buck[i].size(); k++){
if(min == -1) min = buck[i][k];
else min = buck[i][k] < min ? buck[i][k] : min;
}
}
if(min != -1 && max != -1) {
result = min-max > result ? min-max : result;
max = min = -1;
}
if(max == -1){
for(int k = 0; k < buck[i].size(); k++){
if(max == -1) max = buck[i][k];
else max = buck[i][k] > max ? buck[i][k] : max;
}
}
}
return result;
}