各大排序算法C++代码实现
排序算法分类
排序算法比较表格
注:
1 归并排序可以通过手摇算法将空间复杂度降到O(1),但是时间复杂度会提高。
2 基数排序时间复杂度为O(N*M),其中N为数据个数,M为数据位数。
辅助记忆
---- 时间复杂度记忆-
- 冒泡、选择、直接 排序需要两个for循环,每次只关注一个元素,平均时间复杂度为O(
)O(
)(一遍找元素O(n)O(n),一遍找位置O(n)O(n))
- 快速、归并、希尔、堆基于二分思想,log以2为底,平均时间复杂度为O(nlogn)O(nlogn)(一遍找元素O(n)O(n),一遍找位置O(logn)O(logn))
---- 稳定性记忆-“快希选堆”(快牺牲稳定性)
关于所有排序的动画请参考:https://visualgo.net/en/sorting
【代码实现】
1 冒泡排序
//array[]为待排序数组,n为数组长度
void BubbleSort(int array[], int n)
{
int i, j, k;
for(i=0; i<n-1; i++)
for(j=0; j<n-1-i; j++)
{
if(array[j]>array[j+1])
{
k=array[j];
array[j]=array[j+1];
array[j+1]=k;
}
}
}
2.选择排序
#include <iostream>
#include<string>
using namespace std;
void print(int a[], int n ,int i){
cout<<i <<":";
for(int j= 0; j<8; j++){
cout<<a[j] <<" ";
}
cout<<endl;
}
void selectSort(int a[], int n)
{
for(int i=0;i<n;++i)
{
int index=i;
for(int j=i+1;j<n;++j)
{
if(a[j]<a[index])
index=j;
}
swap(a[index],a[i]);
print(a,n,i);
}
}
int main(){
int a[8] = {3,1,5,7,2,4,9,6};
selectSort(a,8);
print(a,8,8);
}
3.插入排序
#include <iostream>
using namespace std;
void print(int a[], int n ,int i){
cout<<i <<":";
for(int j= 0; j<8; j++){
cout<<a[j] <<" ";
}
cout<<endl;
}
void InsertSort(int a[], int n)
{
for(int i=1;i<n;i++)
{
int value=a[i];
int index=i-1;
while(index>=0&&a[index]>value)
{
a[index+1]=a[index];
index--;
}
a[index+1]=value;
print(a,n,i);
}
}
int main(){
int a[8] = {3,1,5,7,2,4,9,6};
InsertSort(a,8);
print(a,8,8);
}
4.归并排序
- 递归实现
#include<iostream>
using namespace std;
void Merge(int arr[], int l, int q, int r){
int n=r-l+1;//临时数组存合并后的有序序列
int* tmp=new int[n];
int i=0;
int left=l;
int right=q+1;
while(left<=q && right<=r)
tmp[i++] = arr[left]<= arr[right]?arr[left++]:arr[right++];
while(left<=q)
tmp[i++]=arr[left++];
while(right<=r)
tmp[i++]=arr[right++];
for(int j=0;j<n;++j)
arr[l+j]=tmp[j];
delete [] tmp;//删掉堆区的内存
}
void MergeSort(int arr[], int l, int r){
if(l==r)
return; //递归基是让数组中的每个数单独成为长度为1的区间
int q = (l + r)/2;
MergeSort(arr, l, q);
MergeSort(arr, q + 1, r);
Merge(arr, l, q, r);
}
int main(){
int a[8] = {3,1,2,4,5,8,7,6};
MergeSort(a,0,7);
for(int i=0;i<8;++i)
cout<<a[i]<<" ";
}
- 迭代实现
#include<iostream>
#include<vector>
using namespace std;
// 区间[head1, head2-1]和[head2, tail2]都是排好序的,现在需要合并
void mergeSortHelper(vector<int>& v, int head1, int head2, int tail2) {
int tail1 = head2 - 1, index = 0, len = tail2 - head1 + 1, start = head1;
vector<int> tmp(len);
while (head1 <= tail1 || head2 <= tail2) {
if (head1 > tail1)
tmp[index++] = v[head2++];
else if (head2 > tail2)
tmp[index++] = v[head1++];
else {
if (v[head1] <= v[head2])
tmp[index++] = v[head1++];
else
tmp[index++] = v[head2++];
}
}
for (int i = 0; i < len; ++i)
v[start+i] = tmp[i];
}
void mergeSort(vector<int>& v) {
int len = v.size();
// 倍进枚举步长1,2,4,……
for (int step = 1; step <= len; step <<= 1) {
int offset = step + step;
for (int index = 0; index < len; index += offset)
mergeSortHelper(v, index, min(index+step, len-1), min(index+offset-1, len-1));
}
}
int main(){
vector<int> a = {3,1,2,4,5,8,7,6};
mergeSort(a);
for(int i=0;i<8;++i)
cout<<a[i]<<" ";
}
5.快速排序
#include<iostream>
using namespace std;
int Parition(int a[], int low,int high){
int pivot=a[high];
int i=low;
for(int j=low;j<high;++j)
{
//j指向当前遍历元素,如果大于等于pivot,继续向前
//如果小于当前元素,则和i指向的元素交换
if (a[j]<pivot) {
swap(a[j], a[i]);
i++;
}
}
swap(a[i], a[high]);
return i;
}
void QuickSort(int a[], int low, int high){
if(low<high)
{
int q=Parition(a,low, high);
QuickSort(a, low, q-1);
QuickSort(a, q+1,high);
}
}
int main(){
int a[8] = {3,1,2,4,5,8,7,6};
QuickSort(a,0,7);
for(int i=0;i<8;++i)
cout<<a[i]<<" ";
}
6.堆排序
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
//建堆函数,该函数是堆排序的实现重点
void Maxheap(int arr[], int len, int index)
{
int left = 2*index + 1;
int right = 2*index + 2;
int maxIdx = index;
if(left<len && arr[left] > arr[maxIdx]) maxIdx = left;
if(right<len && arr[right] > arr[maxIdx]) maxIdx = right; // maxIdx是3个数中最大数的下标
if(maxIdx != index) // 如果maxIdx的值有更新
{
swap(arr[maxIdx], arr[index]);
Maxheap(arr, len, maxIdx); // 递归调整其他不满足堆性质的部分
}
}
void heapSort(int arr[], int size)
{
for(int i=size/2 - 1; i >= 0; i--) // 对每一个非叶结点进行堆调整(从最后一个非叶结点开始)
{
Maxheap(arr, size, i);
}
for(int i = size - 1; i >= 1; i--)
{
swap(arr[0], arr[i]); // 将当前最大的放置到数组末尾
Maxheap(arr, i, 0); // 将未完成排序的部分继续进行堆排序
}
}
int main()
{
int array[8] = {8, 1, 14, 3, 21, 5, 7, 10};
heapSort(array, 8);
for(auto it: array)
{
cout<<it<<endl;
}
return 0;
}
7.希尔排序
#include<iostream>
using namespace std;
const int INCRGAP = 3;
void shellSort(int a[],int len)
{
int insertNum = 0;
unsigned gap = len/INCRGAP + 1; // 步长初始化,注意如果当len<INCRGAP时,gap为0,所以为了保证进入循环,gap至少为1!!!
while(gap) // while gap>=1
{
for (unsigned i = gap; i < len; ++i) // 分组,在每个子序列中进行插入排序
{
insertNum = a[i];//将当前的元素值先存起来方便后面插入
unsigned j = i;
while (j >= gap && insertNum < a[j-gap])//寻找插入位置
{
a[j] = a[j - gap];
j -= gap;
}
a[j] = insertNum;
}
gap = gap/INCRGAP;
}
}
int main()
{
int array[11] = {2, 1, 4, 3, 11, 6, 5, 7, 8, 10, 15};
shellSort(array, 11);
for(auto it: array)
{
cout<<it<<endl;
}
return 0;
}