2021年12月15日优化:
再优化:“C语言:(数据结构)较简明地实现随机生成MAXSIZE个整型数据,进行冒泡排序/快速排序。(较稳定)“_Xavier.S的博客-CSDN博客
2021年12月14日 14:25改良完成。
改良处:优化了原来快速排序的输出情况,即:避免了将每一次循环结果输出。
一、冒泡排序原理:
冒泡法是一种简单的排序方法,它的实现非常简单。首先对n个项目进行扫描,比较相领两个项目的大小,若发现违背大小次序则进行互换,由此可以使n个项目中的最大者换到最后。
然后对剩下的未排序好的项目再进行扫描,使它们的最大者换到表的最后。以此类推,直到将表全部排序好为止。这种排序方法,每遍扫描以后,都缩短了待排序表的长度,如果在某次扫描过程中,没有发现交换,则排序结束。
具体步骤:
1、从后往前依次比较相邻的元素。若是要按照升序排序,则后面的元素比前面的小,就交换这2个元素;降序则相反。
2、对每一对相邻元素作同样的工作,从第一对到最后一对。进行一轮比较交换下来,最后的元素就会是最小(或最大)的数了,这个数就不用参与后面的比较操作了。
3、针对所有的元素重复以上的步骤。
4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
为了尽量缩短待排序表的长度,避免下一次扫描中可能出现的不必要的比较,在每次扫描过程中,一方面要记录进行元素交换的次数,另一方面要记住在本次扫描中的最后一次进行交换的位置。在这个位置以后没有发生过交换,则说明在这个位置以后的元素实际上已经排好次序。
总的来说,冒泡法基本思想是重复的进行整个数组的排序,一次比较两个元素(两两排序),如果它们顺序不符合就交换,重复这样直到数列没有再需要交换的数为止(结束条件)。因为它就好像泡泡一样,轻的气泡会往上漂浮,在不断漂浮的过程中,发生了两两交换过程,所以叫冒泡排序。
(参考:冒泡排序算法原理-电子发烧友网)
二、快速排序原理:
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小。
然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
假设要排序的数组是A[1]……A[N],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一躺快速排序。一躺快速排序的算法是:
1、设置两个变量I、J,排序开始的时候I:=1,J:=N;
2、以第一个数组元素作为关键数据,赋值给X,即X:=A[1];
3、从J开始向前搜索,即由后开始向前搜索(J:=J-1),找到第一个小于X的值,两者交换;
4、从I开始向后搜索,即由前开始向后搜索(I:=I+1),找到第一个大于X的值,两者交换;
5、重复第3、4步,直到I=J。
例如:
设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。
值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
1、设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2、以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3、从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]的值赋给A[i];
4、从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]的值赋给A[j];
5、重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。
(参考:快速排序算法原理与实现_百度知道)
三、代码实现:
以下MAXSIZE以20为例。
随机数生成、创建数组:
int *CreatArray()
{
int *arr = (int*)malloc(sizeof(unsigned int)*MAXSIZE);
srand((unsigned int)time(NULL));
for (int i = 0; i < MAXSIZE; i++) {
int randNum = rand() % MAXSIZE;
arr[i] = randNum;
printf("%d ", arr[i]);
}
return arr;
}
冒泡排序函数:
void BubbleSort(int a[MAXSIZE])
{
int i,j,temp;
for(i=0;i<MAXSIZE-1;i++)
{
for(j=0;j<MAXSIZE-i-1;j++)
{
if(a[j]<a[j+1]) ///比较大小并交换
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
for(i=0;i<MAXSIZE;i++)
printf("%d ",a[i]);
printf("\n");
}
快速排序、打印排序后数组元素 函数 改进前:
快速排序函数:(初级版)
存在问题:将每一次循环的结果都输出。十分费时、费内存,糟糕极了。
///快速排序
void QuickSort(int arr[MAXSIZE],int start,int end) {
int i = start;
int j = end;
int temp = arr[start]; ///基准数
if (i < j) {
while(i < j){
///从右向左去找比基准数小的元素
while (i < j&&arr[j]>=temp)
{j--;}
///填坑
if (i < j) {
arr[i] = arr[j];
i++;
}
///从左向右 找比基准数大的数
while (i < j&&arr[i] <= temp)
{i++;}
///填坑
if (i < j) {
arr[j] = arr[i];
j--;
}
Display(arr,MAXSIZE);
}
///把基准数放到i=j的位置
arr[i] = temp;
///对左半部分(递归)进行快速排序
QuickSort(arr, start, i - 1);
///对右部分(递归)进行快速排序
QuickSort(arr, j + 1, end);
Display(arr,MAXSIZE);
}
}
打印排序后数组元素:
void Display(int a[],int n){
int i;
for(i=0; i<n ;i++)
printf("%d ",a[i]);
printf("\n");
}
主函数(测试函数):
void main()
{
int arr[MAXSIZE]; int choose;
printf("随机生成de数\n");
arr[MAXSIZE]=CreatArray();
printf("\n输入数字1、2依次选择冒泡、快速排序\n");
scanf("%d",&choose);
switch(choose)
{
case 1:
printf("冒泡排序(HIGN-->LOW)\n");
BubbleSort(arr[MAXSIZE]);
printf("\n");
break;
case 2:
printf("快速排序(LOW-->HIGN)\n");
QuickSort(arr[MAXSIZE],0,MAXSIZE);
printf("\n");
break;
}
}
完整代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
///定义最大数值(数组的最大长度)
#define MAXSIZE 20
///创建数组
int *CreatArray()
{
int *arr = (int*)malloc(sizeof(unsigned int)*MAXSIZE);
srand((unsigned int)time(NULL));
for (int i = 0; i < MAXSIZE; i++) {
int randNum = rand() % MAXSIZE;
arr[i] = randNum;
printf("%d ", arr[i]);
}
return arr;
}
///冒泡排序
void BubbleSort(int a[MAXSIZE])
{
int i,j,temp;
for(i=0;i<MAXSIZE-1;i++)
{
for(j=0;j<MAXSIZE-i-1;j++)
{
if(a[j]<a[j+1]) ///比较大小并交换
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
for(i=0;i<MAXSIZE;i++)
printf("%d ",a[i]);
printf("\n");
}
///快速排序
void QuickSort(int arr[MAXSIZE],int start,int end) {
int i = start;
int j = end;
int temp = arr[start]; ///基准数
if (i < j) {
while(i < j){
///从右向左去找比基准数小的元素
while (i < j&&arr[j]>=temp)
{j--;}
///填坑
if (i < j) {
arr[i] = arr[j];
i++;
}
///从左向右 找比基准数大的数
while (i < j&&arr[i] <= temp)
{i++;}
///填坑
if (i < j) {
arr[j] = arr[i];
j--;
}
Display(arr,MAXSIZE);
}
///把基准数放到i=j的位置
arr[i] = temp;
///对左半部分(递归)进行快速排序
QuickSort(arr, start, i - 1);
///对右部分(递归)进行快速排序
QuickSort(arr, j + 1, end);
Display(arr,MAXSIZE);
}
}
void Display(int a[],int n){
int i;
for(i=0; i<n ;i++)
printf("%d ",a[i]);
printf("\n");
}
void main()
{
int arr[MAXSIZE]; int choose;
printf("随机生成de数\n");
arr[MAXSIZE]=CreatArray();
printf("\n输入数字1、2依次选择冒泡、快速排序\n");
scanf("%d",&choose);
switch(choose)
{
case 1:
printf("冒泡排序(HIGN-->LOW)\n");
BubbleSort(arr[MAXSIZE]);
printf("\n");
break;
case 2:
printf("快速排序(LOW-->HIGN)\n");
QuickSort(arr[MAXSIZE],0,MAXSIZE);
printf("\n");
break;
}
}
运行结果:
冒泡排序:
快速排序(待改进):
由此可见,非常耗时,还待改进。
2021年12月14日 12:52:13
快速排序、打印排序后数组元素 函数 改进后:
快速排序函数:
int QuickSort(int arr[MAXSIZE],int start,int end) {
int i = start;
int j = end;
int temp = arr[start]; ///基准数
if (i < j) {
while(i < j){
///从右向左去找比基准数小的元素
while (i < j&&arr[j]>=temp)
{j--;}
///填坑
if (i < j) {
arr[i] = arr[j];
i++;
}
///从左向右 找比基准数大的数
while (i < j&&arr[i] <= temp)
{i++;}
///填坑
if (i < j) {
arr[j] = arr[i];
j--;
}
}
///把基准数放到i=j的位置
arr[i] = temp;
///对左半部分(递归)进行快速排序
QuickSort(arr, start, i - 1);
///对右部分(递归)进行快速排序
QuickSort(arr, j + 1, end);
}else
{return arr;} ///改进的地方
}
改进的地方:
增加return语句 为下面主函数中调用Display打印函数提供了条件。
打印排序后数组元素:(与改进前毫无变化)
void Display(int a[],int n){
int i;
for(i=0; i<n ;i++)
printf("%d ",a[i]);
printf("\n");
}
主函数(测试函数):
void main()
{
int arr[MAXSIZE]; int choose;
printf("随机生成de数\n");
arr[MAXSIZE]=CreatArray();
printf("\n输入数字1、2依次选择冒泡、快速排序\n");
scanf("%d",&choose);
switch(choose)
{
case 1:
printf("冒泡排序(HIGN-->LOW)\n");
BubbleSort(arr[MAXSIZE]);
break;
case 2:
printf("快速排序(LOW-->HIGN)\n");
Display(QuickSort(arr[MAXSIZE],0,MAXSIZE),MAXSIZE);///改进的地方
break;
}
}
改进的地方:
将Display打印函数放在主函数的switch中,这样就避免将每一次循环的结果输出打印了。
完整代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
///定义最大数值(数组的最大长度)
#define MAXSIZE 20
///创建数组
int *CreatArray()
{
int *arr = (int*)malloc(sizeof(unsigned int)*MAXSIZE);
srand((unsigned int)time(NULL));
for (int i = 0; i < MAXSIZE; i++) {
int randNum = rand() % MAXSIZE;
arr[i] = randNum;
printf("%d ", arr[i]);
}
return arr;
}
///冒泡排序
void BubbleSort(int a[MAXSIZE])
{
int i,j,temp;
for(i=0;i<MAXSIZE-1;i++)
{
for(j=0;j<MAXSIZE-i-1;j++)
{
if(a[j]<a[j+1]) ///比较大小并交换
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
for(i=0;i<MAXSIZE;i++)
printf("%d ",a[i]);
printf("\n");
}
///快速排序
int QuickSort(int arr[MAXSIZE],int start,int end) {
int i = start;
int j = end;
int temp = arr[start]; ///基准数
if (i < j) {
while(i < j){
///从右向左去找比基准数小的元素
while (i < j&&arr[j]>=temp)
{j--;}
///填坑
if (i < j) {
arr[i] = arr[j];
i++;
}
///从左向右 找比基准数大的数
while (i < j&&arr[i] <= temp)
{i++;}
///填坑
if (i < j) {
arr[j] = arr[i];
j--;
}
}
///把基准数放到i=j的位置
arr[i] = temp;
///对左半部分(递归)进行快速排序
QuickSort(arr, start, i - 1);
///对右部分(递归)进行快速排序
QuickSort(arr, j + 1, end);
}else
{return arr;}
}
void Display(int a[],int n){
int i;
for(i=0; i<n ;i++)
printf("%d ",a[i]);
printf("\n");
}
void main()
{
int arr[MAXSIZE]; int choose;
printf("随机生成de数\n");
arr[MAXSIZE]=CreatArray();
printf("\n输入数字1、2依次选择冒泡、快速排序\n");
scanf("%d",&choose);
switch(choose)
{
case 1:
printf("冒泡排序(HIGN-->LOW)\n");
BubbleSort(arr[MAXSIZE]);
break;
case 2:
printf("快速排序(LOW-->HIGN)\n");
Display(QuickSort(arr[MAXSIZE],0,MAXSIZE),MAXSIZE);
break;
}
}
运行结果:
冒泡排序:
快速排序:
四、总结:
回顾此次探究实验,明白了每一段代码都有其独特的重要作用,马虎大意不得,一丝丝的颠倒或者错误都会导致“牵一发而动全身”。在以后的学习生活中,要重视基础,打牢基础,多实践、动手,多探究并善于反思。否则一切都将是“豆腐渣工程”。
纸上得来终觉浅,绝知此事要躬行。
未尽事宜,敬请见谅。
欢迎联系我,提出您的宝贵意见。
谢谢观看!
By:Xavier.S
QQ:2543756155
E-mail:asztmicro@outlook.com
2021年12月14日 14:49:48