c++动态数组、选择排序、冒泡排序
概要
本文主要讲述如何用c++创建一个动态大小的数组,以及对于排序的问题,主要包括选择排序和冒泡排序,并进行算法实现与性能比较。
在日常用到的排序算法中,选择排序和冒泡排序的算法比较简单,是用得最多的两种,对于数据量不大的情况,两者的排序速度差不多,数据量较大的情况下,通常选择排序的效率更高些。
#include <iostream>
#include <chrono>
using namespace std;
//生成double类型的随机数
double rand_double(int a,int b) {
double data = double((rand() % (b - a + 1)) + a)*double(rand())*0.01;
return data;
}
//输出数组
void show(double* parr, int len) {
for (int i = 0; i < len; ++i) {
cout << parr[i] << endl;
}
}
void main()
{
int len = 5;
//生成动态数组,数组大小定为5,实际上也相当于 arr[5];
double *arr=(double *)malloc(sizeof(double)*len);
//对动态数组赋值
for (int i = 0; i < len; ++i) {
arr[i] = rand_double(-10, 10);
}
//计算运行开始时间
auto beforeTime = std::chrono::steady_clock::now();
auto arr1 = arr;
cout << "选择排序:" << endl;
xuanze(arr1,len);
show(arr1,len);
//计算运行结束时间
auto afterTime = std::chrono::steady_clock::now();
//得到运行时间
double duration_second = std::chrono::duration<double>(afterTime - beforeTime).count();
std::cout << duration_second << "秒" << std::endl;
auto beforeTime2 = std::chrono::steady_clock::now();
auto arr2 = arr;
cout << "冒泡排序:" << endl;
maopao(arr2, len);
show(arr2, len);
auto afterTime2 = std::chrono::steady_clock::now();
double duration_second2 = std::chrono::duration<double>(afterTime2 - beforeTime2).count();
std::cout << duration_second2 << "秒" << std::endl;
free(arr);//释放内存
//静态数组使用
double arr_p[5] = { 0.2,0.5,0.4,0.1,0.6 };
xuanze(arr_p, size(arr_p));
//maopao(arr_p, size(arr_p));
show(arr_p, size(arr_p));
}
选择排序
选择排序算法流程:
按照从小到大排的情况
- 首先用 i 从左到右遍历整个数组,设置第二个循环 j,即从 i 的位置往后遍历,对比 i 和 j 所在位置的值大小,若 a[j] 比 a[i] 的小,就交换两者的位置,当 j 遍历完毕,最小值的位置已经换到了 i 的位置。比如,当 i 等于0时,j 遍历往后的整个数组,得到整个数组的最小值放到 a[0]。
- j 是从 i+1开始,每次求出 位置 i 到 len-1的最小值,放到 i 的位置,这样一直遍历,就可以将整个数组从小到大排序。
- 反之,若 j 从0开始的话,就是每次将最小值放到最后,这样就是从大到小排序了。
当然,除了通过 j 范围的设置来设定排序顺序,还可以通过改变判断 a[i] 和 a[j]的大小关系来变换排序顺序,即取 a[i] > a[j] 或者 a[i] < a[j] 也是可以变换升序和降序的。
算法实现:
//parr 即数组,len表示数组长度
void xuanze(double * parr,int len) {
//double *arr = *parr;
for (int i = 0; i < len; ++i) {
//for (int j = 0; j < i; ++j) { //从大往小排
for (int j = i + 1; j < len; ++j) { //从小往大排
if (parr[j] < parr[i]) {
auto it = parr[i];
parr[i] = parr[j];
parr[j] = it;
}
}
}
}
选择排序:
587.16
795
1100.68
1846.7
2201.76
冒泡排序
冒泡排序与选择排序不同之处在于,冒泡算法是前后两个对比大小,而选择算法相当于直接求出最小值放在前面。
冒泡排序算法流程:
从小到大排的情况
- 设定循环次数,只需要循环 len-1 次就可以对数组进行排序。
- 首先,当第一次循环时,j 的范围为 0 到 len-1,此时依次对比前后两个数的大小,若前一个大于后一个,就交换两者的位置,此时,遍历整个数组后,数组的最大值就被交换到最后了。
- 每次循环都把遍历部分的最大值放到最后,所有循环结束后,数组就是从小到大排序了。
- 若改成前一个小于后一个交换位置的话,最小值就会放在后面,此时就是从大到小排序。
同样,也可以通过变换 j 的范围来控制升降序。
算法实现:
void maopao(double* parr, int len) {
for (int i = 0; i < len-1; ++i) {
for (int j = 0; j < len-i-1; ++j) {
if (parr[j+1] < parr[j]) { //从小往大排
//if (parr[j+1] > parr[j]) { //从大往小排
auto it = (parr)[j];
parr[j] = parr[j+1];
parr[j+1] = it;
}
}
}
}
冒泡排序:
587.16
795
1100.68
1846.7
2201.76
选择排序算法通常效率更高一些
设置排序数组大小为50000,两种方法使用时间对比:
选择排序:5.2-5.5秒
冒泡排序:5.6-5.8秒