0 复杂度总结
![](https://i-blog.csdnimg.cn/blog_migrate/64ec0b0999fd3a34f5014f05266f3ce0.png)
稳定:排序后相同关键字的相对位置不变
不稳:快些选堆
快 快速
些 希尔
选 简单选择
堆 堆排序
注意:
对于简单选择排序有两种版本:1交换板、2插入板
交换版 就是不稳的
插入版 就是稳定的(简单想想即知)
以下排序均默认升序
1 直接插入
思路:将每个元素插入已排好序的部分(前半部分)
有 for 和 while 两种形式,本质一样
代码第三行 cmp 控制升序 或降序
#include<bits/stdc++.h>
#define num 100
#define cmp <
using namespace std;
typedef struct
{
int data[num];
int length;
}sqlist;
void init(sqlist &a)
{
a.length = 0;
cout << "初始化完成!" << endl << endl;
}
void creat(sqlist &a)
{
int length = rand()%num;
cout << "length = " << length << endl;
int i;
for(i = 0; i < length; i++)
{
a.data[i]= rand()%num;
}
a.length = length;
cout << "创建完成" << endl << endl;
}
void print(sqlist a)
{
int length = a.length;
int i;
cout << "输出:" << endl;
if(length != 0)
{
for(i = 0; i < length; i++)
{
printf("%-3d", a.data[i]);
if((i + 1)%20 == 0)
cout << endl;
}
cout << endl << endl;
}
else
cout << "为空!" << endl << endl;
}
void insertSort(sqlist &a)
{
int i, j, temp;
cout << "直接插入排序(for):" << endl;
for(i = 1; i < a.length; i++)
{
temp = a.data[i];
for(j = i-1; j >= 0; j--)
{
if(temp cmp a.data[j])
a.data[j + 1] = a.data[j];
else
break;
}
a.data[j + 1] = temp;
}
cout << "完成!" << endl << endl;
}
void insertSort2(sqlist &a)
{
int i, j, temp;
cout << "直接插入排序(while):" << endl;
for(i = 1; i < a.length; i++)
{
temp = a.data[i];
j = i - 1;
while(j >= 0 && temp cmp a.data[j])
{
a.data[j + 1] = a.data[j];
j--;
}
a.data[j + 1] = temp;
}
cout << "完成!" << endl << endl;
}
int main()
{
sqlist a;
srand(time(NULL));
init(a);
print(a);
creat(a);
print(a);
insertSort(a);
print(a);
creat(a);
print(a);
insertSort2(a);
print(a);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/1e177310064e96010d1c98ee06a8a911.png)
2 折半插入
思路
序列分为两部分,有序部分在前,无序部分在后,对于无序部分某元素 在 有序部分总以折半查找的方式找到对应位置,然后插入
#include<bits/stdc++.h>
#define num 100
#define cmp <= // >= 或 <= 保证排序稳定
using namespace std;
typedef struct
{
int data[num];
int length;
}sqlist;
void init(sqlist &a)
{
a.length = 0;
cout << "初始化完成!" << endl << endl;
}
void creat(sqlist &a)
{
int length = rand()%num;
cout << "length = " << length << endl;
int i;
for(i = 0; i < length; i++)
{
a.data[i]= rand()%num;
}
a.length = length;
cout << "创建完成" << endl << endl;
}
void print(sqlist a)
{
int length = a.length;
int i;
cout << "输出:" << endl;
if(length != 0)
{
for(i = 0; i < length; i++)
{
printf("%-3d", a.data[i]);
if((i + 1)%20 == 0)
cout << endl;
}
cout << endl << endl;
}
else
cout << "为空!" << endl << endl;
}
int search(sqlist a, int low, int high, int temp)
{
int mid;
while(low <= high)
{
mid = (low + high)/2;
if(a.data[mid] cmp temp)
low = mid + 1;
else
high = mid - 1;
}
return low;
}
void ensqlist(sqlist &a, int p, int high, int temp)
{
int i;
for(i = high; i >= p; i--)
a.data[i+1] = a.data[i];
a.data[p] = temp;
}
void BinsertSort(sqlist &a)
{
int i, j, p, temp;
cout << "折半插入排序:" << endl;
for(i = 1; i < a.length; i++)
{
temp = a.data[i];
p = search(a, 0, i - 1, temp);
ensqlist(a, p, i-1, temp);
}
cout << "完成!" << endl << endl;
}
int main()
{
sqlist a;
srand(time(NULL));
init(a);
print(a);
creat(a);
print(a);
BinsertSort(a);
print(a);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/ed956c7ef8cdbeb2e6e9b1350de8b929.png)
3 冒泡插入
思路
升序:两两交换,大数会浮到最右边,依次进行
#include<bits/stdc++.h>
#define num 100
#define cmp > // > 或 < 保证排序稳定
using namespace std;
typedef struct
{
int data[num];
int length;
}sqlist;
void init(sqlist &a)
{
a.length = 0;
cout << "初始化完成!" << endl << endl;
}
void creat(sqlist &a)
{
int length = rand()%num;
cout << "length = " << length << endl;
int i;
for(i = 0; i < length; i++)
{
a.data[i]= rand()%num;
}
a.length = length;
cout << "创建完成" << endl << endl;
}
void print(sqlist a)
{
int length = a.length;
int i;
cout << "输出:" << endl;
if(length != 0)
{
for(i = 0; i < length; i++)
{
printf("%-3d", a.data[i]);
if((i + 1)%20 == 0)
cout << endl;
}
cout << endl << endl;
}
else
cout << "为空!" << endl << endl;
}
void exchange(int &a, int &b)
{
int c;
c = a;a = b;b = c;
}
void bSort(sqlist &a)
{
int i, j, temp, flag;
cout << "冒泡排序:" << endl;
for(i = a.length-1; i > 0; i--)
{
flag = 0;
for(j = 0; j < i; j++)
{
if(a.data[j] cmp a.data[j+1])
{
exchange(a.data[j], a.data[j+1]);
flag = 1;
}
}
if(flag == 0)
break;
}
cout << "完成!" << endl << endl;
}
int main()
{
sqlist a;
srand(time(NULL));
init(a);
print(a);
creat(a);
print(a);
bSort(a);
print(a);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/356ccc38ab0834cddb4952aa629d30b1.png)
4 快速排序
其中cmp1 和 cmp2控制升序 和 降序
其中很重要的操作可以写成一个划分子函数 partition()
思路(升序):
以第 i=1个元素为参考点a,t=a值,从后面 j=high 向前(j- -)查看,若后面一元素 b 比 t 小,则 b 赋值给 i 位置元素,i++,
从 i位置元素向后(i++)查看,若比 t 大,则i位置值赋值给 j 位置值,j- -
循环,直到 i < j 不成立为止
但没结束!
把 t 值赋值给现在的i位置的元素
并将low - (i-1) 和 (i + 1) - high 这两部分再次递归快速排序一下
end
#include<bits/stdc++.h>
#define num 100
#define cmp1 <= // <= 或 >= 保证排序稳定
#define cmp2 < // < 或 > 保证排序稳定
//其中 cmp1,不带等号,会影响排序稳定性,但不影响升序或降序效果
//cmp1 和 cmp2 的组合只有{<=, <}、{>=, >}
using namespace std;
typedef struct
{
int data[num];
int length;
}sqlist;
void init(sqlist &a)
{
a.length = 0;
cout << "初始化完成!" << endl << endl;
}
void creat(sqlist &a)
{
int length = rand()%num;
cout << "length = " << length << endl;
int i;
for(i = 0; i < length; i++)
{
a.data[i]= rand()%num;
}
a.length = length;
cout << "创建完成" << endl << endl;
}
void print(sqlist a)
{
int length = a.length;
int i;
cout << "输出:" << endl;
if(length != 0)
{
for(i = 0; i < length; i++)
{
printf("%-3d", a.data[i]);
if((i + 1)%20 == 0)
cout << endl;
}
cout << endl << endl;
}
else
cout << "为空!" << endl << endl;
}
void qSort(sqlist &a, int low, int high)
{
int i = low, j = high, temp;
if(i < j)
{
temp = a.data[i];
while(i < j)
{
while(i < j && temp cmp1 a.data[j])
j--;
if(i < j)
{
a.data[i] = a.data[j];
i++;
}
while(i < j && a.data[i] cmp2 temp)
i++;
if(i < j)
{
a.data[j] = a.data[i];
j--;
}
}
a.data[i] = temp;
qSort(a, low, i - 1);
qSort(a, i + 1, high);
}
}
int main()
{
sqlist a;
srand(time(NULL));
init(a);
print(a);
creat(a);
print(a);
cout << "快速排序:" << endl;
qSort(a, 0, a.length - 1);
print(a);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/79d0adcea8075e3fb62a7045aa07f555.png)
5 简单选择
思路:
每次选最小的放在前面
有交换版 和 插入板
交换版,不稳定
插入版稳定
cmp1 控制 交换版的升降序
cmp2 控制 插入版的升降序
#include<bits/stdc++.h>
#define num 100
#define cmp1 < // 交换版,无论 < 或 <=均不能保证算法稳定,<降序, >升序
#define cmp2 < // 插入版,能保证算法稳定,<降序, >升序
using namespace std;
typedef struct
{
int data[num];
int length;
}sqlist;
void init(sqlist &a)
{
a.length = 0;
cout << "初始化完成!" << endl << endl;
}
void creat(sqlist &a)
{
int length = rand()%num;
cout << "length = " << length << endl;
int i;
for(i = 0; i < length; i++)
{
a.data[i]= rand()%num;
}
a.length = length;
cout << "创建完成" << endl << endl;
}
void print(sqlist a)
{
int length = a.length;
int i;
cout << "输出:" << endl;
if(length != 0)
{
for(i = 0; i < length; i++)
{
printf("%-3d", a.data[i]);
if((i + 1)%20 == 0)
cout << endl;
}
cout << endl << endl;
}
else
cout << "为空!" << endl << endl;
}
void exchange(int &a, int &b)
{
int c;
c = a;a = b;b = c;
}
void selectSort1(sqlist &a) //交换
{
int i, j, temp;
cout << "简单选择排序(交换版):" << endl;
for(i = 0; i < a.length; i++)
{
temp = i;
for(j = i + 1; j < a.length; j++)
{
if(a.data[temp] cmp1 a.data[j])
temp = j;
}
exchange(a.data[i], a.data[temp]);
}
cout << "完成!" << endl << endl;
}
void endata(sqlist &a, int low, int high)
{
int temp = a.data[high];
--high;
for(; high >= low; high--)
{
a.data[high + 1] = a.data[high];
}
a.data[low] = temp;
}
void selectSort2(sqlist &a) // 插入
{
int i, j, temp;
cout << "简单选择排序(插入版):" << endl;
for(i = 0; i < a.length; i++)
{
temp = i;
for(j = i + 1; j < a.length; j++)
{
if(a.data[temp] cmp2 a.data[j])
temp = j;
}
endata(a, i, temp);
}
cout << "完成!" << endl << endl;
}
int main()
{
sqlist a;
srand(time(NULL));
init(a);
print(a);
creat(a);
print(a);
selectSort1(a); //交换
print(a);
creat(a);
print(a);
selectSort2(a); // 插入
print(a);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/9b54e3470023ec084a9e2e77ea803d72.png)
6 堆排序
大顶堆:父亲 > 孩子
小顶堆:父亲 < 孩子
![](https://i-blog.csdnimg.cn/blog_migrate/eced1d4cc34f35301807fce4bdbfa92b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c75fb3cd7e0ebc1682a2a099b29ef740.png)
建堆思路(升序):
i = n/2
i ~ n 建堆
(i- -) ~ n 建堆
…
直到
0 ~ n 建堆
end
排序:
i = n
对顶堆 i 就是最大元素,和堆尾交换调整
0 - (i- -)建堆,循环,直到 i == 1 成立(下标从0开始的!)
该排序不稳定
其中 cmp 控制升降序 , < 升序, > 降序
该算法综合性能很好,和下面的二路归并一样,因为最坏情况的复杂度比其他排序要好
但要比二路归并的 空间复杂度强,它是O(1),二路归并是O(n)
代码可能看起来有点陌生,用多了就好了吧
代码:
#include<bits/stdc++.h>
#define num 100
#define c(x) (x + 1)*2 - 1
#define cmp < // 排序不稳定, <升序, >降序
using namespace std;
typedef struct
{
int data[num];
int length;
}sqlist;
void init(sqlist &a)
{
a.length = 0;
cout << "初始化完成!" << endl << endl;
}
void creat(sqlist &a)
{
int length = rand()%num;
cout << "length = " << length << endl;
int i;
for(i = 0; i < length; i++)
{
a.data[i]= rand()%num;
}
a.length = length;
cout << "创建完成" << endl << endl;
}
void print(sqlist a)
{
int length = a.length;
int i;
cout << "输出:" << endl;
if(length != 0)
{
for(i = 0; i < length; i++)
{
printf("%-3d", a.data[i]);
if((i + 1)%20 == 0)
cout << endl;
}
cout << endl << endl;
}
else
cout << "为空!" << endl << endl;
}
void sift(sqlist &a, int low, int high) // 一趟建堆
{
int i = low, j = c(i), temp = a.data[i];
while(j <= high)
{
if(j < high && a.data[j] cmp a.data[j+1])
j++;
if(temp cmp a.data[j])
{
a.data[i] = a.data[j];
i = j;
j = c(i);
}
else
break;
}
a.data[i] = temp;
}
void heapSort(sqlist &a)
{
int i, j, temp;
cout << "堆排序:" << endl;
for(i = a.length/2; i >= 0; i--) // 建堆
sift(a, i, a.length - 1);
for(i = a.length-1; i > 0; i--)
{
temp = a.data[0];
a.data[0] = a.data[i];
a.data[i] = temp;
sift(a, 0, i-1);
}
cout << "完成" << endl << endl;
}
int main()
{
sqlist a;
srand(time(NULL));
init(a);
print(a);
creat(a);
print(a);
heapSort(a);
print(a);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/a89eb741625b90cc95483b2879043114.png)
7 归并排序
二路归并思路(来源)
注意:
其中子函数merge,的循环条件要特别注意!很容易出错
我这里用的是插入法,设计时费了些心思
还有种方法很简单:就是新建一个新的数组,依次把前后两有序部分从小到大取元素,放进新数组,再把该数组赋值给sqlist中的数组(参考合并两个链表的函数)
#include<bits/stdc++.h>
#define num 100
#define c(x) (x + 1)*2 - 1
#define cmp < // 排序不稳定, <升序, >降序
using namespace std;
typedef struct
{
int data[num];
int length;
}sqlist;
void init(sqlist &a)
{
a.length = 0;
cout << "初始化完成!" << endl << endl;
}
void creat(sqlist &a)
{
int length = rand()%num;
cout << "length = " << length << endl;
int i;
for(i = 0; i < length; i++)
{
a.data[i]= rand()%num;
}
a.length = length;
cout << "创建完成" << endl << endl;
}
void print(sqlist a)
{
int length = a.length;
int i;
cout << "输出:" << endl;
if(length != 0)
{
for(i = 0; i < length; i++)
{
printf("%-3d", a.data[i]);
if((i + 1)%20 == 0)
cout << endl;
}
cout << endl << endl;
}
else
cout << "为空!" << endl << endl;
}
void endata(sqlist &a, int low, int high)
{
int i = high - 1, temp = a.data[high];
for(; i >= low; i-- )
a.data[i+1] = a.data[i];
a.data[low] = temp;
}
void merge(sqlist &a, int low, int mid, int high)
{
int i = low, j = mid + 1;
while(i <= mid && j <= high)
{
while(a.data[i] <= a.data[j] && i <= mid)
i++;
if(a.data[i] > a.data[j] )
{
endata(a, i, j); // 插入操作,j位置插入i位置,中间元素均后移一位
mid++;
i++;
j++;
}
}
}
void mergeSort(sqlist &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);
}
}
int main()
{
sqlist a;
srand(time(NULL));
init(a);
print(a);
creat(a);
print(a);
cout << "二路归并排序:" << endl;
mergeSort(a, 0, a.length - 1);
cout << "完成" << endl << endl;
print(a);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/b660afc827c0d99222ad3832a2cba0c5.png)
8 基数排序(LSD / MSD)
参考于文章:
https://www.cnblogs.com/Braveliu/archive/2013/01/21/2870201.html
LSD - 数值的最右边(低位)开始
MSD - 数值的最左边(高位)开始
LSD - 适用 位数少 的数列
MSD - 适用 位数多 的数列
8.1 LSD
(来源):
思路:
低数位 向着 高位 依次在 ‘桶里’ 排序
依次 就是 循环
for(i = 1; i < 10; i++) // 不可省略,让对应元素是在其对应位置
b[i] += b[i-1];
for(i = a.length-1; i >= 0; i--) //从后向前排序,不可换方向!
{
output[ b[(a.data[i]/exp)%10] - 1 ] = a.data[i];
b[(a.data[i]/exp)%10]--;
}
上面代码在做的事:
白色部分 无元素
淡黄色部分 元素数为1
淡蓝色部分 元素数大于1
#include<bits/stdc++.h>
#define num 100
using namespace std;
typedef struct
{
int data[num];
int length;
}sqlist;
void init(sqlist &a)
{
a.length = 0;
cout << "初始化完成!" << endl << endl;
}
void creat(sqlist &a)
{
int length = rand()%num;
cout << "length = " << length << endl;
int i;
for(i = 0; i < length; i++)
{
a.data[i]= rand()%num;
}
a.length = length;
cout << "创建完成" << endl << endl;
}
void print(sqlist a)
{
int length = a.length;
int i;
cout << "输出:" << endl;
if(length != 0)
{
for(i = 0; i < length; i++)
{
printf("%-3d", a.data[i]);
if((i + 1)%20 == 0)
cout << endl;
}
cout << endl << endl;
}
else
cout << "为空!" << endl << endl;
}
int getmax(sqlist a)
{
int i, max = a.data[0];
for(i = 1; i < a.length; i++)
{
if(max < a.data[i])
max = a.data[i];
}
return max;
}
void countSort(sqlist &a, int exp)
{
int b[10] = {0}, output[a.length] = {0};
int i;
for(i = 0; i < a.length; i++) //对应位置的个数
b[ (a.data[i]/exp)%10 ]++;
for(i = 1; i < 10; i++) // 不可省略,让对应元素是在其对应位置
b[i] += b[i-1];
for(i = a.length-1; i >= 0; i--) //从后向前排序,不可换方向!
{
output[ b[(a.data[i]/exp)%10] - 1 ] = a.data[i];
b[(a.data[i]/exp)%10]--;
}
for(i = 0; i < a.length; i++)
a.data[i] = output[i];
}
void radixSort(sqlist &a)
{
int exp, max;
cout << "基数归并排序:" << endl;
max = getmax(a); //获取数组中最大值
for(exp = 1; max/exp > 0; exp *= 10) // 循环次数 = max的数字位数, 如2351就有4次
countSort(a, exp);
cout << "完成" << endl << endl;
}
int main()
{
sqlist a;
srand(time(NULL));
init(a);
print(a);
creat(a);
print(a);
radixSort(a);
print(a);
system("pause");
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/697d7659e0ba13822776adb4d19567b7.png)
8.2 MSD
图解:https://blog.csdn.net/xgf415/article/details/76595887
思路
1 先来一次最高位的 桶排(与LSD的前半部分基本一样,但注意此时排序的范围是:low - high,不是 0 - a.length)
2 此时 数组b[10]中的详细情况:( 0 <= i < 10)
2.1 若该位置 i 无元素,那么b[ i - 1 ] == b[ i ] 成立;
2.2.1 若有元素,个数为1,那么 b[ i - 1 ] == b[ i ] 也成立;
2.2.2 若个数 大于 1,那么就需要 MSD排序一下了!
2 的核心代码
for(i = 0; i < 10; i++)
{
p1 = low + b[i];
if(i < 9)
p2 = low + b[i + 1] - 1;
else
p2 = high;
if(p1 < p2 && (exp/10 > 0))
MSDradixSort(a, p1, p2, exp/10);
}
范围是p1 ~ p2
p1 = low + b[ i ]
p2 = high + b[ i + 1] - 1
i 位置元素个数等于0时,p1 > p2成立
i 位置元素个数小于等于1时,p1 == 2成立,不需要去MSD排序,MSD在此时只排序2个以上的元素!
i 位置元素个数大于1时,p1 < p2,要MSD,所以p1 < p2作为MSD的执行条件
下图为最高位排序后b[10]的情况
白色部分 无元素
淡黄色部分 元素数为1
淡蓝色部分 元素数大于1!这部分是我想去MSD的
此时low = 0
b[2]无元素
p1 = low + b[2] = 0 + 1 = 1
p2 = low + b[3] - 1 = 0 + 1 - 1= 0,p1 < p2 不成立
b[3]两个元素
p1 = low + b[3] = 0 + 1 = 1
p2 = low + b[4] - 1= 0 + 3 - 1= 2
所以在i = (2 - 1)的位置进行MSD
代码:
费了很多时间才改完一大堆bug…
#include<bits/stdc++.h>
#define num 100
using namespace std;
typedef struct
{
int data[num];
int length;
}sqlist;
void init(sqlist &a)
{
a.length = 0;
cout << "初始化完成!" << endl << endl;
}
void creat(sqlist &a)
{
int length = rand()%num;
cout << "length = " << length << endl;
int i;
for(i = 0; i < length; i++)
{
a.data[i]= rand();
}
a.length = length;
cout << "创建完成" << endl << endl;
}
void print(sqlist a)
{
int length = a.length;
int i;
cout << "输出:" << endl;
if(length != 0)
{
for(i = 0; i < length; i++)
{
printf("%-6d ", a.data[i]);
if((i + 1)%10 == 0)
cout << endl;
}
cout << endl << endl;
}
else
cout << "为空!" << endl << endl;
}
int getmax(sqlist a)
{
int i, max = a.data[0];
for(i = 1; i < a.length; i++)
{
if(max < a.data[i])
max = a.data[i];
}
return max;
}
int getexp(int max)
{
int exp;
for(exp = 1; max/exp > 0; exp *= 10);
return exp/10;
}
void countSort(sqlist &a, int b[], int low, int high, int exp)
{
int *output = (int *)malloc((high - low + 1)*sizeof(int));
int i;
for(i = low; i <= high; i++) //对应位置的个数
b[ (a.data[i]/exp)%10 ]++;
for(i = 1; i < 10; i++) // 不可省略,让对应元素是在其对应位置
b[i] += b[i - 1];
for(i = high; i >= low; i--) //从后向前排序,不可换方向!
{
output[ b[(a.data[i]/exp)%10] - 1 ] = a.data[i];
b[(a.data[i]/exp)%10]--;
}
for(i = low; i <= high; i++)
a.data[i] = output[i - low];
}
void MSDradixSort(sqlist &a, int low, int high, int exp)
{
int i;
int p1, p2;
int b[10] = {0};
countSort(a, b, low, high, exp); // 一次 按最高位在桶里排序,参考 LSD
// 数组b[]存放各元素一次排序后的位置
for(i = 0; i < 10; i++)
{
p1 = low + b[i];
if(i < 9)
p2 = low + b[i + 1] - 1;
else
p2 = high;
if(p1 < p2 && (exp/10 > 0))
MSDradixSort(a, p1, p2, exp/10);
}
}
void MSD(sqlist &a)
{
int max, exp;
cout << "基数归并排序:" << endl;
max = getmax(a); //获取数组中最大值
exp = getexp(max); // exp指的是 最大值最高位的整数,如 32324的exp=10000
MSDradixSort(a, 0, a.length - 1, exp); // 开始真正的基数排序
cout << "完成" << endl << endl;
}
int main()
{
sqlist a;
srand(time(NULL));
init(a);
print(a);
creat(a);
print(a);
MSD(a);
print(a);
system("pause");
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/c19ff40d5af515c1de04607f6c261620.png)
9 希尔排序
![](https://i-blog.csdnimg.cn/blog_migrate/00ded6af0c823b3ca351be61969a02ec.png)
代码:
#include<bits/stdc++.h>
#define num 100
#define cmp > // 排序不稳定, <降序, >升序
using namespace std;
typedef struct
{
int data[num];
int length;
}sqlist;
void init(sqlist &a)
{
a.length = 0;
cout << "初始化完成!" << endl << endl;
}
void creat(sqlist &a)
{
int length = rand()%num;
cout << "length = " << length << endl;
int i;
for(i = 0; i < length; i++)
{
a.data[i]= rand()%num;
}
a.length = length;
cout << "创建完成" << endl << endl;
}
void print(sqlist a)
{
int length = a.length;
int i;
cout << "输出:" << endl;
if(length != 0)
{
for(i = 0; i < length; i++)
{
printf("%-3d", a.data[i]);
if((i + 1)%20 == 0)
cout << endl;
}
cout << endl << endl;
}
else
cout << "为空!" << endl << endl;
}
void make(int k[], int length)
{
int i = 0;
for(; length > 0; length /= 2)
{
k[i++] = length;
}
}
void insertSort(sqlist &a, int length) //思想:和直接插入排序 一样,形式有点不同而已
{ //多与 直接插入排序 比较比较
int i, j, temp;
for(i = length; i < a.length ; i++)
{
temp = a.data[i];
for(j = i - length; j >= 0 && a.data[j] cmp temp; j -= length)
a.data[j + length] = a.data[j]; // 向后移动,步长为 length
a.data[j + length] = temp;
}
}
void ShellSort(sqlist &a)
{
int i, k[num]={0};
make(k, a.length/2); // 设计步长
cout << "希尔排序:" << endl;
for(i = 0; k[i] > 0; i++)
insertSort(a, k[i]); // k[i]是步长,直接插入排序
cout << "完成" << endl << endl;
}
int main()
{
sqlist a;
srand(time(NULL));
init(a);
print(a);
creat(a);
print(a);
ShellSort(a);
print(a);
system("pause");
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/a46468b2069a8c55c9591f63515c33b5.png)