You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

266 lines
8.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Initialcommit
//一、希尔排序 和插入排序的过程相似,相对于插入排序而言,比较较远距离的数据,使得数据移动跨过多个元素,进行一次比较可能会消除多个元素的交换
//最好情况是步长序列只有1且序列几乎有序时间复杂度为O(n)。
//希尔本人给出的步长序列,最坏情况时间复杂度是 O(n^2)
//希尔排序的时间复杂度与步长序列有关
#include <stdio.h>
int main() {
int arr[] = {1,5, 2, 7, 6, 4, 9, 8};
int i;
for (i = 0; i < 8; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
int step; //步长;
int key; //保护每一组数据排序时的第二个数据;
int j;
//该排序过程是多组数据同时进行,并不是一组一组的进行;
for (step = 8 / 2; step > 0; step /= 2) {
for (i = step; i < 8; i++) {
key = arr[i]; //保护数据
for (j = i - step; j >= 0 && arr[j] > key; j -= step) {
arr[j + step] = arr[j];
}
arr[j + step] = key; //将保护的数据放到合适的位置;
}
}
for (i = 0; i < 8; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
//结果:1 5 2 7 6 4 9 8
// 1 2 4 5 6 7 8 9
//二、插入排序:最简单常用的方法
//类似于我们打扑克牌的时对手里的牌进行排序的过程,选出一个值,将其插入在合适的排序位置。
//适用于数据量不大,对算法的稳定性有要求,且数据局部或者整体有序的情况。
//时间复杂度为O(n*n).
//空间复杂度为O(1); 最好的情况下即当数据有序时可以达到O(n)的时间复杂度
#include<stdio.h>
int main()
{
int a[] = {45,32,56,71,12};
int i,j,temp;
printf("未排序前:\n");
for(i=0;i<5;i++)
{
printf("%d ", a[i]);
}
printf("\n经过直接插入排序后:\n");
for(i=1;i<5;i++)
{
temp = a[i];
//当前数小于前一位数时
if(a[i] < a[i-1])
{
//将子序列重新排列为有序序列
for(j=i-1;temp<a[j];j--)
{
a[j+1] = a[j];
}
a[j+1] = temp;
}
}
for(i=0;i<5;i++)
{
printf("%d ", a[i]);
}
}
//结果:未排序前:
// 45 32 56 71 12
// 经过直接插入排序后:
//12 32 45 56 71
//三、归并排序 时间复杂度为O(nlog),空间复杂度为O(n),其需要借助额外的存储空间,是高级排序算法中,唯一一个稳定的排序算法,当数据量较大时,要注意考虑内存空间的开销。
//原理:如果有两个已经排序好的数组{1,4,6,8}{2,7,9,12}
//我们要把这两个数组合并再排序;目标数组应该是{1,2,4,6,7,8,9,12}
//四、选择排序法(以从小到大排序为例)
//算法思想:
//A.在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
//B.从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾
//C.以此类推,直到所有元素均排序完毕
#include<stdio.h>
int main()
{
void sort(int a[],int n);
int i,a[10];//定义数组营首地址和数组长度
printf("please input the original array:");
for(i=0;i<10;i++)
scanf("%d",&a[i]);//输入十个数
sort(a,10);//调用函数sort对这十个数进行排序
for(i=0;i<10;i++)
printf("%5d",a[i]);//输出排序后的十个数
printf("\n");
return 0;
}
void sort(int a[],int n)//n是指数组长度
{
int min,i,j,t;
for(i=0;i<n-1;i++)//数组中的前n-1个数除最后一个数外都要进行一趟循环
{
min=i;//假设此趟循环中的最小值就是当前值i
for(j=i+1;j<n;j++)//第i个数要和后面的每个值比较与i比较的值记作j
if(a[min]>a[j])//若后面的数j更小
min=j;//记住此时j的下标
t=a[i];a[i]=a[min];a[min]=t;//将a[i]和a[j]交换位置
}
}
//五、冒泡排序法(从小到大排序为例)
//算法思想:
//1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
//2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后//的元素会是最大的数,然后将该数固定
//3.针对所有的元素重复以上的步骤,除了最后一个。
//4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
#include<stdio.h>
int main()
{
void sort(int a[],int n);
int i,a[10];//定义数组营首地址和数组长度
printf("please input the original array:");
for(i=0;i<10;i++)
scanf("%d",&a[i]);//输入十个数
sort(a,10);//调用函数sort对这十个数进行排序
for(i=0;i<10;i++)
printf("%5d",a[i]);//输出排序后的十个数
printf("\n");
return 0;
}
//六、堆排序
//(一)最大堆调整(Heapify):将堆的末端子节点作调整,//使得子节点永远小于父节点
//(二)创建最大堆(CreateHeap):将堆中的所有数据重新//排序
//(三)堆排序(HeapSort):移除位在第一个数据的根节点,//并做最大堆调整的递归运算
时间复杂度及总结
1、堆排序最大的优点就是,在最坏的情况下,时间复杂度仍为 O(n*logn)
2、堆排序只需要存放一个记录的辅助空间,所以堆排序也称原地排序;
3、堆排序是不稳定的;
//七、快速排序
//先从数列中取出一个数作轴值(基准数)pivot
//根据基准数将数列进行分区,小于基准数的放左边,大于基准数的//放右边;
//重复分区操作,直到各区间只有一个数为止。
#include<stdio.h>
int fast(int* y,int begin,int end)
{
int temp=y[begin];
//将结尾位置保存一下,因为之后的运算会改变end值,end会逐渐向前移动
//,而最后递归的时候end还得是数组的尾元素,不能发生变化
int endTemp=end;
//设定递归条件,左右不可相等(重合)如果相等那就return
if(end>begin)
{
//循环条件,左右不可相等(重合),如果相等,那就一次排序分组完毕,开始将分好的两组数组再递归进行排序
while(begin<end)
{
//向左移动
while((begin<end)&&(temp<=y[end]))
end--;
y[begin]=y[end];
//向右移动
while((begin<end)&&(temp>y[begin]))
begin++;
y[end]=y[begin];
}
//基准元素放到中间左右重合的位置上
y[begin]=temp;
//分组递归,前一组数组为首元素到
fast(y,0,begin-1);
fast(y,begin+1,endTemp);
}
return 0;
}
int main()
{
int y[]={22,12,1,33,17,5,10,89,88,30,21,11,11};
fast(y,0,(sizeof(y)/sizeof(int))-1);
for(int i=0;i<sizeof(y)/sizeof(int);i++)
printf("%d ",y[i]);
return 0;
}
1 5 10 11 11 12 17 21 22 30 33 88 89
在最好情况下,快速排序算法的时间复杂度为O(nlogn)
在最坏情况下,待排序的序列为正序或者逆序,每次划分只得到一个臂上次划分少一个记录的子序列,而且另一个序列还为空。如果递归树画出来,它就是一棵斜树。此时需要执行(n-1)次递归调用,且第i次划分需要经过i-1次关键字的比较才能找到第i个记录,即中轴元素的位置,因此比较次数为:n-1+n-2+n-3+…+1 = n*(n-1)/2 时间复杂度为O(n^2)
//八、基数排序(以整形为例),将整形10进制按每位拆分,然后从低位到高位依次比较各个位。每次比较完进行排序,直到整个数组有序主要分为两个过程:
//(1)分配,先从个位开始,根据位值(0-9)分别放到0~9号桶中(比如53,个位为3,则放入3号桶中)
//(2)收集,再将放置在0~9号桶中的数据按顺序放到数组中重复(1)(2)过程,从个位到最高位,直到排好序为止(比如32位无符号整形最大数4294967296,最高位10位)
#include <stdio.h>
#define NUM 10 //数组元素个数
void counting_sort(int a[],int b[],int c[],int atemp[]);
int main()
{
int i;
int j;
int a[10] = {326,54,512,13,9,71,92,61,53,19}; //input array
int atemp[10];
int b[10]; //output array
int c[10]; //temp all element are not biger than 10
// 个位排序
for (i = 0;i < NUM;i++)
atemp[i] = a[i] % 10;
counting_sort(atemp,b,c,a);
for (i = 0;i < NUM;i++)
a[i] = b[i];
// 十位排序
for (i = 0;i < NUM;i++)
atemp[i] = a[i] / 10 % 10;
counting_sort(atemp,b,c,a);
for (i = 0;i < NUM;i++)
a[i] = b[i];
//百位排序
for (i = 0;i < NUM;i++)
atemp[i] = a[i] / 100 % 10;
counting_sort(atemp,b,c,a);
for (i = 0;i < NUM;i++)
printf(" %d ",b[i]);
printf("\n");
}
//基数排序算法,a为待排序数组(一位数,要和atemp区分开)b为排序好的数组,c为中间数组,atemp为原始数组(包括三位数)
void counting_sort(int a[],int b[],int c[],int atemp[])
{
int i,j;
for (i = 0;i < NUM;i++)
c[i] = 0;
for (j = 0;j < NUM;j++)
c[a[j]] += 1;
for (i = 1;i < NUM;i++)
c[i] = c[i] + c[i-1];
for (j = 9;j >= 0;j--) {
b[c[a[j]] - 1] = atemp[j];
c[a[j]] -= 1;
}
}
9 13 19 53 54 61 71 92 326 512