概述
目录
冒泡和快速的改进???
综合应用题
冒泡和快速的改进???
综合应用题
1、题目:编写双向冒泡算法,在正反两个方向交替进行扫描,即第一趟把关键字最大的元素放在序列的最后面,第二趟把关键字最小的元素放在序列的最前面,如此反复进行。
解析:
这种排序叫做双向起泡。奇数趟时,从前往后比较相邻元素的关键字,遇到逆序即交换,直到把序列中关键字最大的元素移动到序列尾部。偶数趟时,从后往前比较相邻元素的关键字,遇到逆序即交换,直到把序列中关键字最小的元素移动到序列尾部。
#include <stdio.h>
#include <stdbool.h>
typedef int ElemType;
ElemType a[50];//a[]待排序序列
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void BubbleSort(ElemType a[], int n)
{
int low = 0, high = n-1,i;
bool flag = true;
while (low < high && flag)
{
flag = false;//每一趟开始之前都需要将标志归0.
//奇数趟,正向走,将最大的移动到最后。
for ( i = low; i < high; i++)
{
if (a[i] > a[i+1])
{
swap(&a[i],&a[i+1]);
flag = true;//发生交换
}
}
high --;
//偶数趟,倒向走,将最小的移动到最前面。
for ( i = high; i > low; i--)
{
if (a[i] < a[i-1])
{
swap(&a[i],&a[i-1]);
flag = true;
}
}
low ++;
}
}
int main()
{
int n;
printf("请输入序列个数:n");
scanf("%d",&n);
printf("请输入序列中的元素: n");
for (int i = 0; i < n; i++)
{
scanf("%d",&a[i]);
}
BubbleSort(a,n);
printf("排序好的序列是:n");
for (int i = 0; i < n; i++)
{
printf("%d,",a[i]);
}
printf("n");
return 0;
}
结果:
请输入序列个数:
10
请输入序列中的元素:
12 13 39 43 10 33 23 90 82 19
排序好的序列是:
10,12,13,19,23,33,39,43,82,90
自己敲的过程中出现的不足之处:
1、没有想过双向冒泡以后,每趟排序的起始点和结尾点都会变,要添加low和high。还在那啥傻傻的想。。。废物。。。
2、你是憨熊吗?为什么不考虑一下是否要判断越界等情况,只知道写排序过程,就没有想过结束条件是什么吗?
我希望你可以记住!!!判断结束条件!!!
3、那么怎么才是排序结束呢?当然是用flag来标志每一次是否排序,若排序则对flag进行改变。
在定义bool flag = true时,我一开始初始定义成了flag = flase,然后,
因为只有true时while才执行,那么我只能把对flag的判断放在了while循环里面。
因为每趟排序后,flag=true,所以在while循环的开头增加判断:若flag = false则说明没有进行交换对叭?然后跳出循环。
造成了一个后果:是不是傻,是不是傻,一开始你自己规定的就是flag = false呀!!!。所以一遍也不执行,直接跳出。。。
我说怎么排序后没有发生变化。。。害… …
2、已知线性表按顺序存储,且每个元素都是不相同的整形元素,设计把所有奇数移动到所有偶数前边的算法(要求时间最少,辅助空间最少)。
解析:我的看法:没什么新颖的。重点是要求时间最少,辅助空间最少,。那也就是说,循环嵌套层数要少,尽量在原序列上进行移动。 王道:本题可基于快速排序的划分思想来设计算法:只需要遍历一次即可。时间复杂度为O(n),空间复杂度O(1),基本思想:先从前向后找到一个偶数元素L(i),再从后向前找到一个奇数元素L(i),将二者交换;重复上述过程,直到low>high。(不完全使用快速排序)。
#include <stdio.h>
typedef int ElemType;
ElemType a[50];
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void move(ElemType a[],int n)
{
int low = 0, high = n-1;
while (low < high)
{
while (low < high && a[low] % 2 != 0)
{
//只要是奇数就跳过,直到找到一个偶数,跳出while循环。
low ++;
}
while (low < high && a[high] % 2 != 1)
{
//只要是偶数就跳过,直到找到一个奇数,跳出while循环。
high --;
}
if (low < high)
{
swap(&a[low], &a[high]);//交换。
}
low ++; high --;//我居然把这一条件给忘了,不加这一句,i和j的值就一直不变,就会死循环。
}
}
int main()
{
int n;
printf("请输入序列个数:n");
scanf("%d",&n);
printf("请输入序列中的元素: n");
for (int i = 0; i < n; i++)
{
scanf("%d",&a[i]);
}
move(a,n);
printf("排序好的序列是:n");
for (int i = 0; i < n; i++)
{
printf("%d,",a[i]);
}
printf("n");
return 0;
}
总结一下:1、main函数里好像都差不多,那以后就不写了。2、在考试里遇到要求时间最少、算法最优等等,或者没有暗示又不是超级适合其他排序算法的,那就从快速排序开始试试。
3、试重新编写考点精析中的快速排序的划分算法,使之每次选取的枢轴值都是随机地从当前子表中选择的。
pass吧? 使用随机数来选出pivot.但是,选出的随机数要和第一个元素进行交换,pivot还是=a[low]。
4、试编写一个算法,使之能够在数组L[1…n]中找出第k小的元素(即从小到大排序后处于第k个位置的元素)。
解析:
我的想法是直接对数组进行排序,然后提取L(k),便得到了第k小。但是,这样其平均时间复杂度将达到O(nlog2n)以上。
王道:可以采用小根堆的思想,时间复杂度为O(n+klog2n).
最精彩的还是基于快速排序的划分操作。
主要思想:
5、荷兰国旗问题:设有一个仅有红、白、蓝三种颜色的条块组成的条块序列,请编写一个时间复杂度为 Q ( n ) Q(n) Q(n)的算法,使得这些条块按红、白、蓝的顺序排好,即排成荷兰国旗图案。
6、【2016年统考真题】已知由n(n≥2)个正整数构成的集合 A = {ak ∣ 0 ≤ k < n} ,将其划分为两个不相交的子集A1和 A2,元素个数分别是n1和n2,A1和A2中的元素之和分别为S1和S2。设计一个尽可能高效的划分算法,满足 |n1 − n2|最小且 |S1 − S2|最大。
要求:
1、给出算法的基本设计思想。
2、根据设计思想,采用C语言描述算法,关键之处给出注释。
3、说明你所设计算法的平均时间复杂度和空间复杂度。
最后
以上就是虚心保温杯为你收集整理的排序算法的代码--选择排序综合训练题的全部内容,希望文章能够帮你解决排序算法的代码--选择排序综合训练题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复