void InsertSort(int R[],int n)
{
int i,j,tmp;
//右边,从第一个数字开始
for(i=1,i<n,++i)
{
tmp = R[i]; //将待插入关键字暂存与temp中
j = i-1;
//和左边从右到左比较,如果R[j]>tmp,将它向后移
//直到找到小于自己的数,将自己放到这个数的后边
while(j>=0 && tmp<R[j])
{
R[j+1] = R[j];
--j;
}
R[j+1] = tmp;//找到插入位置
}
}
思想:
步骤:
时间复杂度:
空间复杂度:
int main() {
int len ;
scanf("%d", &len);
int* nums = (int*)malloc(sizeof(int) * len);
for (int i = 0; i < len; i++) {
scanf("%d", &nums[i]);
}
int gap = len / 2;
while (gap > 0) { //每完成一次while循环,代表完成了一次分组后的插入排序
for (int i = 0; i <= gap; i++) {
for (int j = i+gap; j < len; j += gap) { //对间隔为gap的数组成员进行插入排序
if (nums[j] < nums[j - gap]) {
int t = nums[j];
nums[j] = nums[j - gap];
nums[j - gap] =t;
}
}
}
gap /= 2;
}
for (int i = 0; i < len; i++) {
printf("%d\n", nums[i]);
}
return 0;
}
思想:
步骤:
时间复杂度:
空间复杂度:
void BubbleSort(int R[], int n){
int i,j,flag;
int temp;
for(i = n-1;i >=1;--i){
flag = 0;
for(j = 1;j <= i;++j){
if(R[j-1] > R[j]){
temp = R[j];
R[j] = R[j-1];
R[j-1] = temp;
flag = 1;
}
if(flag == 0)
return;
}
}
}
1、每一趟选择当前所有子序列中的一个关键字作为枢轴
2、将子序列中比枢轴小的移到枢轴前边,比枢轴大的移到枢轴后边
3、以上述规则划分完毕后会得到新的一组更短的子序列
4、继续以上述规则划分子序列
注意:快速排序中对每一个子序列的一次划分算作一趟排序,每一趟结束之后有一个关键字到达最终位置
void QuickSort(int R[],int low,int high)
{
int tmp;
int i=low,j=high;
if(low<high)
{
temp=R[low];
//小于temp的关键字放在左边,大于temp的关键字放在右边
while(i<j)
{
while(j>i&&R[j]>=temp) --j;
if(i<j)
{
R[i]=R[j];
++i;
}
while(i<j&&R[i]<temp) ++i;
if(i<j)
{
R[j]=R[i];
--j;
}
}
R[i]=temp;
QuickSort(R,low,i-1);
QuickSort(R,i+1,high);
}
}
思想:
步骤:
时间复杂度:
空间复杂度:
void SelectSort(int R[],int n)
{
int i,j,k;
int temp;
for(i=0;i<n;++i)
{
k=i;
//从无序序列中挑出一个最下的关键字
for(j=i+1;j<n;++j)
if(R[k]>R[j])
k=j;
//交换
temp = R[i];
R[i] = R[k];
R[k] = temp;
}
}
举个例子,原始序列为: 49 38 65 97 76 13 27 49
1、下边为原始序列对应的完全二叉树,第一步先将这个树调整为一个大顶堆
2、排序
步骤总结:
1)从无序序列所确定的完全二叉树的最后一个非叶子结点开始,从右至左,从下至上,对每个结点
进行调整,最终将得到一个大顶堆。
对结点的调整方法:将当前结点(假设为a)的值与其孩子结点进行比较,如果存在大于a值的孩
子结点,则从中选出最大的一个与a交换。当a来到下一层的时候重复上述过程,直到a的孩子结点值
都小于a的值为止。
2)将当前无序序列中的第一个关键字,反映在树中是根结点(假设为)与无序序列中最后一个关
键字交换(假设为b)。进入有序序列,到达最终位置。无序序列中关键字减少1个,有序序列中关键
字增加1个。此时只有结点b可能不满足堆的定义,对其进行调整。
3)重复第2步,直到无序序列中的关键字剩下1个时排序结束。
时间复杂度:
空间复杂度:
void Sift(intR[],int low,int high)//这里关键字的存储设定为从数组下标1开始
{
int i=low,j=2*i; //R[j]是R[i]的左孩子结点
int temp=R[i];
while(j<=high)
{
if(j<high&&R[j]<R[j+1]) //若右孩子较大,则把j指向右孩子
++j; //行变为2*i+1
if (temp<R[j])
{
R[i]=R[j];//将R[5]调整到双亲结点的位置上
i=j;//修改1和j的值,以便继续向下调整
j=2*i;
}
else
break; //调整结束
}
R[i]=temp; //被调整结点的值放入最终位置
}
/*堆排序函数*/
void heapsort(int R[],int n)
{
int i;
int temp;
for(i=n/2;i>=1;--1) //建立初始堆
Sift (R,i,n);
for(i=n;i>=2;--1) //进行n-1次循环,完成堆排序
{
/*以下3句换出了根结点中的关键字,将其放入最终位置*/
temp=R[1];
R[1]=R[i]:
R[i]=temp;
Sift(R,1,i-1); //在减少了1个关键字的无序序列中进行调整
}
}
思想:
步骤:
时间复杂度:
空间复杂度:
//int A[size],B[size]
void mergeSort(int A[],int low,int high)
{
if(low<high)
{
int mid = (low+high)/2;
mergeSort(A,low,mid); //前部分
mergeSort(A,mid+1,high); //后部分
merge(A,low,mid,high); //合并
}
}
void merge(int A[],int low,int mid,int high){
//B里暂存A的数据
for(int k = low ; k < high + 1 ; k++){
B[k] = A[k];
}
int i = low , j = mid + 1 , k = low;
while(i < mid + 1 && j < high + 1) {
//A的元素暂存在B里,因为不能再A上原地操作,会打乱数据
//这也是为什么二路归并排序(合并排序)空间复杂度是O(n)的原因
//我们这里把值小的放在前面,最后排序结果就是从小到大
if(B[i] > B[j]){
A[k++] = B[j++];
}else{
A[k++] = B[i++];
}
}
//循环结束后,会有一个没有遍历结束的数组段。
while(i < mid + 1)
A[k++] = B[i++];
while(j < high + 1)
A[k++] = B[j++];
}
1、每一个元素的每一位都是 0~9 数字,所以准备10个桶
2、进行第一趟分配,按照最后一位
3、按桶 0~9顺序收集,从桶下边出:930 063 083 184 505 278 008 109 589 269
4、进行第二趟分配,按照中间位
5、收集:505 008 109 930 063 269 278 083 184 589
6、进行第三趟分配,按照最高位
7、收集:008 063 083 109 184 269 278 505 589 930,最终整个序列有序。