018 直接插入排序
插入排序是把一个记录插入到已排序的有序序列中,使整个序列在插入该记录后仍然有序,插入排序中较简单的一种方法是直接插入排序,其插入位置的确定方法是将待插入的记录与有序区中的各记录自右向左依次比较其关键字值得大小,
要求: 使用直接插入排序法将数字由小到大排序。
——直接插入排序基本思想:每一步将一个待排序的记录,插入到前面已经排好序的有序序列中去,直到插完所有元素为止。
可以看出s[0]为监视参考的值,左边为排序好的值,右边为待排序的值,
#include<stdio.h>
#include<math.h>
void insort(int s[], int n)
{
int i, j;
for(i = 2; i <= n; i++) //数组下标从2开始,s[0]做监视哨,s[1]开始数据无可比性
{
s[0] = s[i]; //给监视哨赋值
j = i - 1; //确定要比较元素最右边位置
while(s[0] < s[j])
{
s[j + 1] = s[j]; //数据右移
j--; //移向左边一个未可比数
}
s[j + 1] = s[0]; //在确定得位置插入s[i]
}
}
main()
{
int a[11], i;
printf(" 请输入10个数据\n ");
// scanf(" %d\n", &n);
for(i = 1; i <= 10; i++)
{
scanf(" %d \n", &a[i]);
}
printf(" 原始顺序: \n ");
for(i = 1; i <= 10; i++)
{
printf(" %5d ", a[i]);
}
insort(a, 10);
printf("\n 插入数据排序后顺序: \n ");
for(i = 1; i < 11; i++)
{
printf(" %5d ", a[i]);
}
printf("\n ");
}
//_____ me ————————————————
#include<stdio.h>
#include<math.h>
main()
{
int a[100], n, i, j, temp;
scanf(" %d\n", &n); //确认输入的个数
for(i = 0; i < n; i++) //输入数组
{
scanf(" %d \n", &a[i]);
}
//进行比较。
for(i = 0; i < n; i++)
{
for(j = i + 1; j < n; j++)
{
if(a[i] > a[j])
{
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
//输出
for(i = 0; i < n; i++)
{
printf(" %02d ", a[i]);
}
}
019 希尔排序
用希尔排序法对一组数据由小到大进行排列,数据分别是:69、56、12、136、3、55、46、99、88、25
希尔排序:把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
例子说明:
#include<stdio.h>
#include<math.h>
void shsort(int s[], int n)
{
int i, j, d;
d = n / 2;
while(d >= 1)
{
for(i = d + 1; i <= n; i++) //数组下标从d + 1 开始进行直接插入排序
{
s[0] = s[i]; //设置监视哨
j = i - d; //确定要进行比较元素最右的位置
while((j > 0) && (s[0] < s[j]))
{
s[j + d] = s[j]; //数据右移
j = j - d; //向左移d个位置
}
s[j + d] = s[0]; //在确定位置插入s[i]
}
d = d / 2;
}
}
main()
{
int a[11], i;
printf(" 请输入10个数据\n ");
for(i = 1; i < 11; i++) //输入数组
{
scanf(" %d \n", &a[i]);
}
shsort(a, 10); //希尔比较
printf(" 排序后的顺序\n ");
//输出
for(i = 1; i < 11; i++)
{
printf(" %5d ", a[i]);
}
}
020 冒泡排序
冒泡法:如果要对n个数进行冒泡排序,那要进行n - 1 躺比较,在第一趟n-1次两两比较,在第j趟比较中要进行n - i次次两两比较。
用冒泡法对任意输入的10个数由小到大进行排序,
#include<stdio.h>
#include<math.h>
main()
{
int a[11], i, j, t;
printf(" 请输入10个数据\n ");
for(i = 0; i < 10; i++) //输入数组
{
scanf(" %d \n", &a[i]);
}
for(i = 1; i < 10; i++) //冒泡法
{
for(j = 0; j < 10 - i; j++ )
{
if(a[j] > a[ j + 1])
{
t = a[j];
a[j] = a[j +1];
a[j + 1] = t;
}
}
}
printf(" 排序后的顺序\n ");
//输出
for(i = 0; i < 10; i++)
{
printf(" %5d ", a[i]);
}
}
021 快速排序
快速排序:在待排序的n个数据中取第一个数据作为基准值,
- 第一趟分割:将所有记录分为3组,使第一组中各数据值均小于或等于基准值,第二组做基准值的数据,第三组中各数据值均大于或等于基准值,
- 然后再对第一组和第二组分别重复上诉方法。
步骤:
①、挑选基准值:从数列中挑出一个元素,称为“基准”(pivot),
②、分割:重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(与基准值相等的数可以到任何一边)。在这个分割结束之后,对基准值的排序就已经完成,
③、递归排序子序列:递归地将小于基准值元素的子序列和大于基准值元素的子序列排序。
用快速排序法对一组数据由小到大进行排序,数据分别为:99、45、12、36、69、22、62、796、4、696
#include<stdio.h>
#include<math.h>
void qusort(int s[], int start, int end)
{
int i, j;
i = start;
j = end;
s[0] = s[start]; //参考基准
while(i < j)
{
while(i < j && s[0] < s[j]) //位置左移
{
j--;
}
if(i < j)
{
s[i] = s[j]; //将s[j]放在a[i]位置
i++; //位置右移
}
while(i < j && s[i] <= s[0])
{
i++;
}
if(i < j)
{
s[j] = s[i]; //将大于基准的s[i]放在s[j]
j--; //左移
}
}
s[i] = s[0];
//对分割出的部分递归调用qusort
if(start < i)
{
qusort(s, start, j-1);
}
if(i < end)
{
qusort(s, j + 1, end);
}
}
main()
{
int a[11], i;
printf(" 请输入10个数据\n ");
for(i = 1; i <= 10; i++) //输入数组
{
scanf(" %d \n", &a[i]);
}
qusort(a, 1, 10);
printf(" 排序后的顺序\n ");
//输出
for(i = 1; i <= 10; i++)
{
printf(" %5d ", a[i]);
}
}
022 选择排序
选择算法:从待排序的区间中经过选择和交换后选出最小(最大)的数值存放在a[0]中,再从剩余的未排序区间中经过选择和交换后选出最小(最大)的数值存在a[1]中,依次类推。
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,
然后,再从剩余未排序元素中继续寻找最小(大)元素,
然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
——维基百科
用选择排序对一组数据由小到大进行排序,数据分别为:526、36、2、369、56、45、78、92、125、52
#include<stdio.h>
#include<math.h>
main()
{
int a[11], i, j, t;
printf(" 请输入10个数据\n ");
for(i = 1; i <= 10; i++) //输入数组
{
scanf(" %d \n", &a[i]);
}
for(i = 1; i < 10; i++)
{
for(j = i + 1; j < 11; j++)
{
if(a[i] > a[j]) //如果前一个比后一个大,互换
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}
printf(" 排序后的顺序\n ");
//输出
for(i = 1; i <= 10; i++)
{
printf(" %5d ", a[i]);
}
}
023 归并排序
归并是将两个或多个有序记录序列合并成一个有序序列。采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
-
归并方法:
-
一次对两个有序记录序列进行归并——二路归并排序。
-
三路归并排序以及多路归并排序
-
基本方法:
-
将n个记录堪称是n个长度为1的有序子表
-
将两两相邻的有序子表进行归并
-
重复执行步骤(2),直到归并成一个长度为n的有序表。
用归并排序对一组数据由小到大进行排序,数据:695、458、362、789、12、15、163、23、2、986
#include<stdio.h>
#include<math.h>
void merge(int r[], int s[], int x1, int x2, int x3)
{
int i, j, k;
i = x1;
j = x2 + 1;
k = x1;
while ((i <= x2) && (j <= x3))
{
if (r[i] <= r[j])
{
s[k] = r[i];
i++;
k++;
}
else
{
s[k] = r[j];
j++;
k++;
}
}
while (i <= x2)
{
s[k++] = r[i++];
}
while (j <= x3)
{
s[k++] = r[j++];
}
}
void merge_sort(int r[], int s[], int m, int n)
{
int p;
int t[20];
if (m == n)
{
s[m] = r[m];
}
else
{
p = (m + n) / 2;
merge_sort(r, t, m, p);
merge_sort(r, t, p + 1, n);
merge(t, s, m, p, n);
}
}
main()
{
int a[11], i, j, t;
printf(" 请输入10个数据\n ");
for (i = 1; i <= 10; i++) //输入数组
{
scanf_s(" %d \n", &a[i]);
}
merge_sort(a, a, 1, 10);
printf(" 排序后的顺序\n ");
//输出
for (i = 1; i <= 10; i++)
{
printf(" %5d ", a[i]);
}
}
参考文献: 希尔排序:https://www.cnblogs.com/chengxiao/p/6104371.html
快速排序:https://zh.wikipedia.org/wiki/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F
选择排序:https://zh.wikipedia.org/wiki/%E9%80%89%E6%8B%A9%E6%8E%92%E5%BA%8F
归并排序:https://zh.wikipedia.org/wiki/%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F
https://www.cnblogs.com/chengxiao/p/6194356.html