排序是算法中很基础的部分,必须要掌握。很多人也做过排序合集并且总结归纳了代码和各个排序方法的思路,看过不少之后我觉得终究还是要靠自己理解消化思想后独立地敲一遍,才能确保真正化为自己知识的一部分。
所以就有了这个合集,记录我自己的学习进度。
总计八个排序(依旧在学习中):
①选择排序
②插入排序
③冒泡排序
④快速排序
⑤归并排序
⑥shell排序(希尔排序)
⑦堆排序
⑧基数排序
代码实现均为升序排序
先放张总结图(来自其他博客)
①选择排序:
基本思想: 最外层循环每次都会按顺序选定一个数作为“基准”,内层循环则负责从基准数后一位开始,遍历整个数组寻找比基准数小的值,若找到则将该数与基准数交换(此时基准数就被更新成了我们找到的该数)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
void SelectSort(int a[],int l)
{
for (int i=0;i<l-1;i++) //外层循环执行到最后一个数据时,整个数组必然已处理完毕,故处理到倒数第二个即可
{
for (int j=i+1;j<l;j++)
{
if (a[i]>a[j]) swap(a[i],a[j]);
}
}
}
int main()
{
int t[]={10,9,1,3,0,0,7,2,8,22,0};
int n;
n=sizeof(t)/sizeof(t[0]);
SelectSort(t,n);
for (int i=0;i<n;i++) printf("%d ",t[i]);
return 0;
}
②插入排序:
基本思想: 将数组分为两部分看待:有序区与无序区,每趟都会从无序区选取第一个数据作为待插入数,然后从有序区末尾开始向前遍历整个有序区寻找插入位置,在插入过程中需要把有序区的数据后移,为待插入数腾出位置。
最初,有序区只有一个数据a[0],单个数据显然是有序的,那么插入数据过程直接从a[1]开始
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
void InsertSort(int a[],int l)
{
int wait,j;
for (int i=1;i<l;i++)
{
wait=a[i]; // 获取待插入数据
j=i; // j为插入位置,此处初始化
//若待插入数刚好大于已有序序列末尾的数的话,直接插入到其后即可
if (wait<a[i-1]) //否则就要在已有有序序列里从后往前遍历寻找插入位置
{
while(j>0 && wait<a[j-1])
{
a[j]=a[j-1]; // 后移腾空间
j--; // 继续向前寻找插入位置
}
}
a[j]=wait; // 插入数据
}
}
int main()
{
int t[]={10,9,1,3,0,0,7,2,8,22,0};
int n;
n=sizeof(t)/sizeof(t[0]);
InsertSort(t,n);
for (int i=0;i<n;i++) printf("%d ",t[i]);
return 0;
}
③冒泡排序
基本思想: 就像水中气泡上升,或者"石沉大海"一样,每一趟排序会逐个两两比较数据,大的往后面丢。第一趟将整个数组中最大的值移动到了数组末尾,第二趟将第二大的移动到了数组的倒数第二位,第三趟…以此类推,每一趟都会令一个当前趟数最大的数据沉底,已经"沉底"的就不需要再管它了,因此,遍历趟数越多,遍历数据次数越少。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
void BubbleSort(int a[],int l)
{
for (int i=0;i<=l-1;i++)
{
for (int j=0;j<=l-i-1;j++)
{
if (a[j]>a[j+1]) swap(a[j],a[j+1]);
}
}
}
int main()
{
int t[]={10,9,1,3,0,0,7,2,8,22,0};
int n;
n=sizeof(t)/sizeof(t[0]);
BubbleSort(t,n);
for (int i=0;i<n;i++) printf("%d ",t[i]);
return 0;
}
④快速排序
基本思想:基于"分而治之"思想,在数据中选取一个基准数(一般来说是数组最左边的数),保证让基准数左边的数据都比基准数小,右边的都比基准数大,然后将整个数据分成两份,递归,再度重复以上过程
这里的讲解很不错,对理解很有帮助 http://developer.51cto.com/art/201403/430986.htm
每次敲快排时脑子里就浮现出左右哨兵移动的过程…然后自然而然就敲完了
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
void QuickSort(int a[],int l,int r)
{
if (l<r)
{
int i=l,j=r; //左哨兵和右哨兵
int key=l; //基准数下标
while (i!=j)
{
//基准数选在最左边,则右哨兵先行动,选在最右边,则左哨兵先行动
while (i<j && a[j]>=a[key]) j--;
while (i<j && a[i]<=a[key]) i++;
if (i<j) swap(a[i],a[j]);
}
swap(a[key],a[i]); //此时左右哨兵已经"碰头"了
QuickSort(a,l,i-1);
QuickSort(a,i+1,r);
}
}
int main()
{
int t[]={10,9,1,3,0,0,7,2,8,22,0};
int n;
n=sizeof(t)/sizeof(t[0]);
QuickSort(t,0,n-1);
for (int i=0;i<n;i++) printf("%d ",t[i]);
return 0;
}
⑤归并排序
(待填坑)
⑥shell排序(希尔排序)
(待填坑)
⑦堆排序
(待填坑)
⑧基数排序
(待填坑)