数据结构-八大排序
稳定的排序算法:
直接插入排序、折半插入排序、归并排序、冒泡
不稳定的算法:
堆排序、简单选择排序、希尔排序、快速排序
插入排序
时间复杂度为平均情况下\(O(n^2)\),最坏情况下\(O(n^2)\),最好情况\(O(n)\)
//插入排序 (下标从1开始存放元素) (王道数据结构)
void InsertSort(int a[], int n) {
int i, j;
for ( i = 2; i <= n; i++) {
if (a[i] < a[i - 1]) {
a[0] = a[i]; //数组首位位缓存区,也就是哨兵
for ( j = i - 1; a[0] < a[j]; j--) //从后往前找其插入位置
a[j + 1] = a[j]; //若当前比较到这个数比哨兵来的大,这个数往后挪
a[j + 1] = a[0]; //复制到插入的位置
}
}
/*也可以写成这样子*/
for (int i = 1; i < n; i++) {
int end = i;
int temp = a[end + 1];
while (end >= 1) {
if (temp < a[end]) {
a[end + 1] = a[end];
end--;
} else break;
}
a[end + 1] = temp;
}
}
希尔排序
时间复杂度为最差\(O(n^2)\),平均约为\(O(n^{1.3})\)
本质上就是在插入排序的基础上加入对应的增量
void ShellSort(int a[], int n) {
//a[0]位暂存位置
int dk, i, j; //dk为增量
for (dk = n / 2; dk >= 1; dk /= 2) { //增量变化,根据题意去修改
for ( i = dk + 1; i <= n; i++)
if (a[i] < a[i - dk]) {
a[0] = a[i]; //暂存元素
for (j = i - dk; j >= 1 && a[0] < a[j]; j -= dk)
a[j + dk] = a[j]; //若当前元素大于a[0]挪对应增量的位置
}
a[j + dk] = a[0];//插入对应位置
}
}
/*也可以写成这样子*/
void ShellInsert(int a[], int dk) { //这个是传入增量
//
int n = lena; //假设已知a的长度
for (int i = 1; i <= n - dk; i++) {
int id = i;
int tmp = a[id + dk];
while (id >= 1) {
if (tmp < a[id]) {
a[id + dk] = a[id];
id -= dk;
} else break;
}
a[id + dk] = tmp;
}
}
冒泡排序
时间复杂度最好为\(O(n)\),最坏和平均情况下都为\(O(n^2)\)
void BubbleSort(int a[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = n - 1; j > i; j--) {
if (a[j - 1] > a[j]) swap(a[j - 1], a[j]);
//要得到从小到大排序,从后往前扫,如果前面的元素大于后面的元素就交换
}
}
}
选择排序
时间复杂度最好、最坏、平均都是\(O(n^2)\)
void SelectSort(int a[],int n)
{
for(int i=0;i<n-1;i++)//一共进行n-1趟
{
int mi=i;//记录最小元素位置
for(int j=i+1; j<n; j++)
if(a[j]<a[mi]) mi=j;//更换最小值位置
if(mi!=i) swap(a[i],a[mi]);//交换元素
}
}
快速排序
时间复杂度为最好为\(o(nlog_2n)\),最坏\(O(n^2)\)
int Part(int a[],int l,int r)
{
int piv=a[l]; //将当前表中的第一个元素设为枢轴,对表进行划分
while(l<r){
while(l<r && a[r]>=piv) r--; //找到比枢轴小的元素
a[l]=a[r];//把小的元素移动到左端
while(l<r&& a[r]<=piv) l++;
a[r]=a[l];//把大的元素移动到右端
}
a[l]=piv;
return l;
}
void QuickSort(int a[],int l,int r)
{
if(l<r){
int pivpos=Part(a,l,r);//划分
QuickSort(a,l,pivpos);//对子表进行递归的排序
QuickSort(a,pivpos+1,r);
}
}
归并排序
时间复杂度为最好为\(o(nlog_2n)\)
//int tmp[]
void MergeSort(int a[],int l,int r)
{
if(l>=r) return ;
int mid= (l+r) >>1;
MergeSort(a,l,mid);//左侧子序列递归排序
MergeSort(a,mid+1,r);//右侧子序列递归排序
int k=0,i=l,j=mid+1;
while(i<=mid &&j<=r)
{
if(a[i]<=a[j] ) tmp[k++]=a[i++];
else tmp[k++] =a[j++];
}
//未检测完的继续复制进去
while(i<=mid) tmp[k++]=a[i++]; //所有的索引记得都要++ 不然就段错误了
while(j<=r) tmp[k++]=a[j++];
for(i=l,j=0;i<=r;i++,j++) a[i]=tmp[j];
}
posted on 2024-12-06 15:30 swj2529411658 阅读(4) 评论(0) 编辑 收藏 举报