七种排序算法的实现:
1. 冒泡排序
#include<bits/stdc++.h>
using namespace std;
void BubbleSort(vector<int> &v, int left, int right) {
for(int i = left; i < right; i++) {
bool flag = false;
for(int j = 0; j < right-i-1; j++) {
if(v[j] > v[j+1]) {
swap(v[j], v[j+1]);
flag = true;
}
}
if(!flag) break;
}
}
int main() {
vector<int> v{6, 5, 4, 3, 2, 1};
BubbleSort(v, 0, v.size());
for(auto i : v) {
cout<<i<<endl;
}
return 0;
}
2. 插入排序
#include<bits/stdc++.h>
using namespace std;
void InsertionSort(vector<int> &v, int left, int right) {
for(int i = left+1; i < right; i++) {
int tmp = v[i];
int j = i-1;
for(; j>=left && v[j] > tmp; j--) {
v[j+1] = v[j];
}
v[j+1] = tmp;
}
}
int main() {
vector<int> v{6, 5, 4, 3, 2, 1};
InsertionSort(v, 0, v.size());
for(auto i : v) {
cout<<i<<endl;
}
return 0;
}
3. 选择排序
#include<bits/stdc++.h>
using namespace std;
void SelectionSort(vector<int> &v, int left, int right) {
for(int i = left; i < right; i++) {
int min_tmp = v[i];
int pos = i;
for(int j = i+1; j< right; j++) {
if(min_tmp > v[j]) {
min_tmp = v[j];
pos = j;
}
}
swap(v[i], v[pos]);
}
}
int main() {
vector<int> v{6, 5, 4, 3, 2, 1};
SelectionSort(v, 0, v.size());
for(auto i : v) {
cout<<i<<endl;
}
return 0;
}
4. 基数排序
#include<bits/stdc++.h>
using namespace std;
int GetMaxBit(vector<int> &v, int left, int right) {
int maxElement = *max_element(v.begin(), v.end());
//cout<<maxElement<<endl;
int bits =0;
while(maxElement) {
maxElement /= 10;
bits++;
}
//cout<<bits<<endl;
return bits;
}
void RadixSort(vector<int> &v, int left, int right) {
int bits = GetMaxBit(v, left, right);
int *tmp = new int[right-left+1];
int *cnt = new int[10];
int radix = 1;
for(int i = 0 ; i< bits; i++) {
for(int j = 0; j < 10; j++) {
cnt[j] = 0;
}
for(int j = left; j<=right; j++) {
int k = v[j] / radix % 10;
cnt[k]++;
}
for(int j = 1; j< 10; j++) {
cnt[j] = cnt[j-1] + cnt[j];
}
for(int j = right; j >=left; j--) {
int k = v[j] / radix % 10;
tmp[cnt[k]-1] = v[j];
cnt[k] --;
}
for(int j = left; j <=right; j++) {
v[j] = tmp[j];
}
radix = radix * 10;
}
delete[] tmp;
delete[] cnt;
}
int main() {
vector<int> v{61, 52, 43, 34, 22, 11, 101};
RadixSort(v, 0, v.size()-1);
for(auto i : v) {
cout<<i<<endl;
}
return 0;
}
5. 快速排序
#include<bits/stdc++.h>
using namespace std;
int Partition(vector<int> &v, int left, int right) {
int mid = left + (right - left) / 2;
int pivot = v[mid];
while(left <= right) {
while(v[left] < pivot) {
left++;
}
while(v[right] > pivot) {
right--;
}
if(left <= right) {
swap(v[left], v[right]);
left++;
right--;
}
}
return left;
}
int Partition2(vector<int> &v, int left, int right) {
int pivot = v[(left+right) / 2];
swap(v[(left+right) / 2], v[right]);
int index = left;
for(int i = left; i <right; i++){
if(v[i] <= pivot) {
swap(v[i], v[index]);
index++;
}
}
swap(v[index], v[right]);
return index;
}
void QuickSort(vector<int> &v, int left, int right) {
if(left < right) {
int index = Partition2(v, left, right);
QuickSort(v, left, index-1);
QuickSort(v, index+1, right);
//int index = Partition(v, left, right);
//QuickSort(v, left, index-1);
//QuickSort(v, index, right);
}
}
int main() {
vector<int> v{6, 5, 4, 3, 2, 1};
QuickSort(v, 0, v.size()-1);
for(auto i : v) {
cout<<i<<endl;
}
return 0;
}
6. 堆排序
#include<bits/stdc++.h>
using namespace std;
void Max_Heapify(vector<int> &v, int left, int right) {
int dad = left;
int son = dad*2+1;
while(son <= right) {
if(son+1 <=right && v[son] < v[son+1]) {
son++;
}
if(v[son] < v[dad]) return;
else {
swap(v[son], v[dad]);
dad = son;
son = dad *2+1;
}
}
}
void HeapSort(vector<int> &v, int left, int right) {
for(int i = left + (right-left)/2 - 1; i >=0; i--) {
Max_Heapify(v, i, right-1);
}
for(int i = right-1; i >=0; i--) {
swap(v[left], v[i]);
Max_Heapify(v, left, i-1);
}
}
int main() {
vector<int> v{6, 5, 4, 3, 2, 1};
HeapSort(v, 0, v.size());
for(auto i : v) {
cout<<i<<endl;
}
return 0;
}
7. 归并排序
#include<bits/stdc++.h>
using namespace std;
void Merge(vector<int> &v, int left, int mid, int right) {
vector<int> *tmp = new vector<int>(right-left+1, 0);
int s1= left;
int s2 = mid+1;
int index = 0;
while(s1 <=mid && s2 <=right) {
if(v[s1] < v[s2]) {
(*tmp)[index] = v[s1];
s1++;
}
else {
(*tmp)[index] = v[s2];
s2++;
}
index++;
}
while(s1 <=mid) {
(*tmp)[index] = v[s1++];
index++;
}
while(s2 <= right) {
(*tmp)[index] = v[s2++];
index++;
}
for(int i = right; i>=left; i--) {
v[i] = (*tmp)[--index];
}
delete tmp;
}
void MergeSort(vector<int> &v, int left, int right) {
if(left < right) {
int mid = left + (right - left) / 2;
MergeSort(v, left, mid);
MergeSort(v, mid+1, right);
Merge(v, left, mid, right);
}
}
int main() {
vector<int> v{6, 5, 4, 3, 2, 1};
MergeSort(v, 0, v.size()-1);
for(auto i : v) {
cout<<i<<endl;
}
return 0;
}
七种排序方式的简单比较:
算法名称 | 算法描述 | 比较操作 | 交换操作 | 赋值操作 | 空间 | 时间 | 特性 |
冒泡排序 | 每次比较相邻的两个,违反排序规则则交换,故每一趟得到的是此趟比较中最大的数字,置于数组尾端 | n(n-1)/2 | 0 n(n-1)/2 | 0 3*n(n-1)/2 | O(1) | O(n^2) | 稳定,通常不用 |
插入排序 | 每当插入一个元素,从排好序的数组尾部开始比较,找到合适的位置,则插入。每操作一个数后,数组都是有序的。 | n-1 n(n-1)/2 | 0 | 比较操作+(n-1) | O(1) | O(n^2) | 稳定,量级较小时,是个好的选择。量级小于8,应用在sort中,作为快速排序的辅助 |
选择排序 | 每一趟排序中找到数组中最小的数字的位置,与待排序数组中最前面数字交换。 | n(n-1)/2 | 0 n-1 | 0 3(n-1) | O(1) | O(n^2) | 不稳定,原地交换几乎是选择排序的唯一优点,当空间复杂度要求高时,可以用选择排序 |
基数排序 | 将待排序数字按位比较,从低位到高位逐渐排序,每一趟排序都会使得n个数趋向于更加有序的状态。 | 0 | 0 | 3kn | O(n) | O(kn) | 稳定,当k<logn时,优势还是很明显的 |
快速排序 | 找到枢纽x,小于x的放在枢纽左边,大于x的放在枢纽右边,递归对两边进行重复操作 | nlogn* | 0~nlogn/2* | * | O(logn)~O(n) | O(nlogn)、O(n^2) | 不稳定,通常最快的排序方式 |
堆排序 | 1.首先构建最大堆:从(n/2-1)到0节点依次向上调整;2.接下来交换堆顶和堆尾(即找到最大值),从上至下重新调整为最大堆,重复第2个步骤n次后,即得到有序数组 | 3nlogn* | nlogn* | * | O(1) | O(nlogn) | 不稳定,原地排序,占用空间少 |
归并排序 | 将相邻两个数字进行归并操作,形成n/2个有序的序列;然后将相邻四个数字进行归并,形成n/4个有序的序列,重复上述操作,最终会形成一个有序序列 | nlogn/2 ~nlogn-n+1 | 0 | 2nlogn | O(n) | O(nlogn) | 稳定,适用于在链表和存储在慢速访问媒体上的非常巨大数列,空间复杂度较高 |