冒泡排序
/*
* 冒泡排序
* 依次比较左右两个元素的大小,如果左边的元素大于右边,那么两者交换位置
* 在第一次的比较过程,将所有元素的最大元素放置最后一个位置
* 后续依次将第二大元素放置倒数第二,第三大放置倒数第三...
* 时间复杂度:最坏情况o(n^2) 最好情况o(n)
* 空间复杂度:o(1),只需要一个额外空间
* 稳定的排序算法
* */
void bubblesort(vector<int>&ans)
{
int n = ans.size();
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n-i-1;j++)
{
if(ans[j]>ans[j+1])
{
swap(ans[j],ans[j+1]);
}
}
}
}
插入排序
/*
* 插入排序
* 通过构建有序序列,对于未排序的数据,可以从有序数列中从后往前查找,找到相应位置并插入
* 从第一个元素开始,可以看成是已排序数据
* 取出下一个元素,从已排序数据中从后往前查找
* 如果已排序数据中某个元素大于新元素,那么就新元素插入这个元素之前
* 重复步骤三,直至找到已排序数据中小于或等于新元素的位置
* 将新元素插入该位置后
* 时间复杂度:平均 o(n^n) 最好情况o(n)
* 空间复杂度 o(1)
* 稳定的排序算法
* */
void insertion_sort(vector<int>& ans)
{
int i,j,key;
int n = ans.size();
for(i = 1;i<n;i++)
{
if(ans[i]>ans[i-1])
{
continue;
}
key = ans[i];
j = i-1;
while(j>=0 &&(ans[j]>key))
{
ans[j+1] = ans[j];
j--;
}
ans[j+1] = key;
}
}
希尔排序
/*
* 希尔排序
* 将待排序序列按照一定的增量,分为若干个组,对每个组实行直接插入排序
* 随着增量的减少,每组包含的元素越来越多,同样对每个组实行直接插入排序
* 当增量为1时,所有元素被分为一组,再实现直接插入排序,算法终结
* 时间复杂度:平均o(nlogn) 最坏 o(n^n)
* 空间复杂度: o(1)
* 不稳定的排序算法
* */
void Shellsort(vector<int>& ans)
{
int count = 1;
int n = ans.size();
for(int i = n/2;i>0;i/=2)
{
//循环分治每一个分组
for(int j = i;j<n;j++)
{
int index =j;
int temp = ans[index];
if(ans[index]<ans[index-i])
{
while((index-i)>=0 && temp<ans[index-i])
{
ans[index] = ans[index-i];
index-=i;
}
ans[index] = temp;
}
}
}
}
选择排序
/*
* 选择排序
* 首先在未排序序列中找到最小(大)的元素,放到序列的起始位置
* 接着找到未排序序列中的最小元素,放到已排序序列的末尾
* 重复第二步,直到全部元素排序
* 时间复杂度:任何情况 o(n^2)
* 不稳定
* */
void select_sort(vector<int>& ans)
{
int n = ans.size();
for(int i = 0;i<n;i++)
{
int min_value = ans[i];
int k = i;
for(int j = i+1;j<n;j++ )
{
if(ans[j]<min_value)
{
min_value = ans[j];
k = j;
}
}
swap(ans[i],ans[k]);
}
}
归并排序
//已排序部分合并
void merge(vector<int>& ans,vector<int>& tempArr,int left,int right,int mid)
{
//标记左半区未被排序的第一个元素
int l_pos = left;
//标记右半区未被排序的第一个元素
int r_pos = mid+1;
//临时数组元素的下标,要从该区域的最左边起开始合并
int pos = left;
while(l_pos<=mid && r_pos<=right)
{
if(ans[l_pos]<=ans[r_pos])
tempArr[pos++] = ans[l_pos++];//左边的第一个元素比右边第一个的元素小
else
tempArr[pos++] = ans[r_pos++];//右边的第一个元素比坐边第一个的元素小
}
//合并左半区剩余元素
while(l_pos<=mid)
{
tempArr[pos++] = ans[l_pos++];
}
//合并右半区剩余元素
while(r_pos<=right)
{
tempArr[pos++] = ans[r_pos++];
}
while(left<=right)
{
ans[left] = tempArr[left];
left++;
}
}
//归并排序
void msort(vector<int>& ans,vector<int>& tempArr,int left,int right)
{
//如果只有一个元素,就没有必要再继续分
//只有一个元素的区域,本身就是有序的,只需要等着被归并即可
if(left<right)
{
//中间位置
int mid = (left+right)/2;
//递归划分左半区
msort(ans,tempArr,left,mid);
//递归划分右半区
msort(ans,tempArr,mid+1,right);
//合并已经排好序的部分
merge(ans,tempArr,left,right,mid);
}
}
/*
* 归并排序是一种分治的思想,将大问题拆解成小问题,将一个大的数组先拆分成小子数组,另子数组内是有序的,再将有序的子数组合并,得到完全有序的序列
* 时间复杂度:任何情况都是o(nlogn)
* 空间复杂度:o(n) 在归并排序中需要额外辅助数组
* 稳定的排序算法
* */
//归并函数入口
void MergeSort(vector<int> &ans)
{
int n =ans.size();
vector<int> tempArr(10);
msort(ans,tempArr,0,n-1);
}
快速排序
/*
* 快速排序
* 从待排序数列中找一个元素作为基准
* 将所有比基准小的元素放到它的前面,所有比基准大的元素放在它后面。这个时候基准就到了它该在的位置
* 然后递归的将大于 和 小于基准的子序列进行排序
* 时间复杂度:o(nlogn)
* 空间复杂度:o(1)
* 不稳定
* */
void msort(vector<int>& ans,int left,int right)
{
//一个元素的情况下,默认有序
if(left>=right)
{
return;
}
int i = left;
int j = right;
int baseval = ans[left];
while(i<j)
{
//从后往前,找到比baseval小的值
while(i<j&&ans[j]>=baseval)
{
j--;
}
if(i<j)
{
ans[i] = ans[j];
i++;
}
//从前往后,找比基准大的值
while(i<j && ans[i]<baseval)
{
i++;
}
if(i<j)
{
ans[j] = ans[i];
j--;
}
}
ans[i] = baseval;
msort(ans,left,i-1);
msort(ans,i+1,right);
}
//快速排序的入口
void quicksort(vector<int>& ans)
{
int n = ans.size();
msort(ans,0,n-1);
}
堆排序
/*
* 维护堆的性质
* @param ans存储堆的数组
* @param 数组长度
* @param 待维护结点的下标
* 在堆排序中,一般是用数组存储堆
* 因此数组位置为i的元素,那么它的左孩子在i*2+1位置 右孩子在i*2+2位置
* 数组位置为i的元素,它的父节点在(i-1)/2
* */
void heafify(vector<int>& ans,int n,int i)
{
int largest = i;
int lson = i*2+1;
int rson = i*2+2;
if(lson<n && ans[largest]< ans[lson])
largest=lson;
if(rson<n && ans[largest]<ans[rson])
largest = rson;
//如果子节点比父节点大
if(largest!=i)
{
//交换两者的位置
swap(ans[i],ans[largest]);
//此时继续维护交换过位置的子堆
heafify(ans,n,largest);
}
}
/*
* 堆排序是一种利用堆所设计的排序算法
* 首先将待排序序列构建成大顶堆,此时堆是无序区
* 将堆顶元素和最后一个元素交换,得到新的无序区和新的有序区
* 由于新交换后的堆不满足大顶堆的性质,需要对新的堆重新构建为打定堆,然后再将堆顶元素和最后一个元素交换,得到新的无序区和新的有序区
* 不断重复此过程,指导有序区的元素个数为n-1,也就是所有元素有序
* */
void heaf_sort(vector<int>& ans)
{
int n = ans.size();
//建堆
for(int i = (n/2)-1;i>=0;i--)
{
heafify(ans,n,i);
}
//排序
for(int i = n-1;i>0;i--)
{
swap(ans[i],ans[0]);
//因为第一次的时候,最后一个元素就有序,所以从N-1开始
heafify(ans,i,0);
}
}
计数排序
/*
* 计数排序
* 找出待排序数组中的最大值N
* 构建一个N+1大小的额外空间tempArr
* 统计待排序数组中元素出现的次数,纪录在额外空间中
* 对额外空间中的每个元素依次累加
* 反向填充数组,遍历待排序数组中元素,看它在tempArr[该元素]的大小,将它放在结果序列的该位置,tempArr[该元素]--
* 得到的结果就是有序序列
*
* 计数排序不是比较排序,它的时间复杂度是线性的
* 时间复杂度: o(n+k) 待排序序列是n个0到k之间的整数
* 计数排序对空间的占用比较多,所以对于数据范围很大的数组不合适
* 稳定排序算法
* */
void count_sort(vector<int>& ans)
{
int len = ans.size();
if(len<=1)
{
return;
}
int max_value = 0;
for(auto a:ans)
{
max_value = max(a,max_value);
}
vector<int> tempArr(max_value+1);
for(auto a:ans)
{
tempArr[a]++;
}
for(int i = 1;i<=max_value;i++)
{
tempArr[i]+=tempArr[i-1];
}
vector<int> output(len);
for(auto a:ans)
{
output[--tempArr[a]] = a;
}
for(int i = 0;i<len;i++)
{
ans[i] = output[i];
}
}
桶排序
/*
* 桶排序
* 假定数组中元素服从均匀分布
* 按照一定的规则,创建一定数量的桶
* 将元素按照范围,依次放到对应的桶中
* 对桶中的元素进行排序(任何排序算法都行)
* 在将桶中的元素连接到一块
* 算法时间复杂度 o(n+k) n个数据分到k个桶中
* 空间复杂度 o(n+k)
* 稳定
* */
void bucket_sort(vector<int>& ans)
{
int n = ans.size();
int max_value = 0;
for(auto a:ans)
{
max_value = max(a,max_value);
}
vector<int> tempArr1;
vector<int> tempArr2;
vector<int> tempArr3;
vector<int> tempArr4;
for(auto a:ans)
{
if(0<=a&& a<=max_value/4)
{
tempArr1.push_back(a);
}
else if((max_value/4)<a && a<=(2*max_value/4))
{
tempArr2.push_back(a);
}
else if((2*max_value/4)<a && a<=(3*max_value/4))
{
tempArr3.push_back(a);
}
else
{
tempArr4.push_back(a);
}
}
count_sort(tempArr1);
count_sort(tempArr2);
count_sort(tempArr3);
count_sort(tempArr4);
ans.clear();
for(auto a:tempArr1)
{
ans.push_back(a);
}
for(auto a:tempArr2)
{
ans.push_back(a);
}
for(auto a:tempArr3)
{
ans.push_back(a);
}
for(auto a:tempArr4)
{
ans.push_back(a);
}
}
基数排序
/*
* 基数排序
* 基数排序是桶排序的扩展
* 首先确定数组中最大元素有几位
* 创建0-9这10个桶,每个数组都是0-9组成
* 按照数字的位数,依次存放到对应的桶中
* 按照队列的方式依次将桶中的元素取出
* 接着继续执行上一步骤
* 时间复杂度o(n*k)
* 空间复杂度o(n+k)
* 稳定
* */
void mysort(vector<int>&ans,int n,int exp)
{
vector<int> output(n);
vector<int> bucket(10);
for(auto a:ans)
{
bucket[(a/exp)%10]++;
}
for(int i = 1;i<10;i++)
{
bucket[i]+=bucket[i-1];
}
for(int i = n-1;i>=0;i--)
{
output[bucket[(ans[i]/exp)%10]-1] = ans[i];
bucket[(ans[i]/exp)%10]--;
}
for(int i = 0;i<n;i++)
{
ans[i] = output[i];
}
}
int getMax(vector<int>&ans)
{
int n = ans[0];
for(auto a:ans)
{
n = max(n,a);
}
return n;
}
void radix_sort(vector<int>&ans)
{
int n = ans.size();
int max_value = getMax(ans);
for(int exp=1;max_value/exp>0;exp*=10)
{
mysort(ans,n,exp);
}
}