1. 7  动态规划算法

动态规划(Dynamic Programming)是求多阶段决策过程(Multistep Decision Process)最优化的一种数学方法,它将问题的整体按时间或空间的特征分成若干个前后衔接的时空阶段,把多阶段决策问题表示为前后有关的一系列单阶段决策问题,然后逐个求解,从而求出整个问题的最有决策序列。它强调了时间和空间的连续性。

动态规划算法的核心思想就是避免子问题的重复计算,通过用空间换取时间的方法来提高算法效率。动态规划算法与分治算法和贪心算法类似,都是将问题归纳为更小的、相似的子问题,然后通过求解子问题产生一个全局最优解。但是与分治算法和贪心算法不同的是,动态规划算法允许这些子问题不独立,也允许其通过自身子问题的解做出选择。动态规划算法的一个显著特征就是其问题树中的子问题呈现大量的重复,因此动态规划算法的实质就是分治思想和解决冗余。动态规划算法的关键,就在于针对重复出现的子问题,在其第一次出现时就加以求解并保存结果,以后再出现重复的子问题时就直接引用、不必重新求解。一般动态规划算法适用的场景满足:

1.最优子结构

如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有最优子结构性质(即满足最优化原理)。最优子结构性质为动态规划算法解决问题提供了重要线索。20世纪50年代初美国数学家R.E.Bellman等人在研究多阶段决策过程(multistep decision process)的优化问题时,提出了著名的最优化原理(principle of optimality)。

2.子问题重叠

子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题时,只是在表格中简单地查看一下结果,从而获得较高的效率。

3.无后效性

即子问题的解一旦确定,就不再改变,不受在这之后、包含它的更大的问题的求解决策影响。

下面以数字三角形和编辑距离问题来展示一下动态规划算法。

数字三角形问题:如图所示的数字三角形,从顶部出发,在每一结点可以选择向左走或得向右走,一直走到底层,要求找出一条路径,使路径上的值最大。以下是数字三角形问题动态规划算法的C语言程序。

/*

题目描述 Description

如图所示的数字三角形,从顶部出发,在每一结点可以选择向左走或得向右走,一直走到底层,要求找出一条路径,使路径上的值最大。

输入描述 Input Description

第一行是数塔层数N(1 <= N <= 100)。

第二行起,按数塔图形,有一个或多个的整数,表示该层节点的值,共有N行。

输出描述 Output Description

输出最大值。

样例输入 Sample Input

5

13

11 8

12 7 26

6 14 15 8

12 7 13 24 11

样例输出 Sample Output

86

*/

#include <stdio.h>

#define maxN 101

int N;                   //N表示数字三角形数塔层数。

int D[maxN][maxN];      //D[i][j]表示第i行第 j 个数字,其中i、j从1开始算。

int maxSum[maxN][maxN]; //maxSum[i][j]表示从D(i,j)到底边的各条路径中,最佳路径的数字之和。

//代码一:纯粹递归。当N达到100是绝对是超时的。因为复杂度是O(2^N)

int fun1(int i, int j)//返回从(i,j)到达最底层的最大路径之和

{

if (i == N) return D[i][j];

else

{

int x = fun1(i + 1, j);

int y = fun1(i + 1, j + 1);

return D[i][j] + (x > y ? x : y);

}

}

//代码二:记忆型递归,避免重复计算。时间复杂度O(n*n)

int fun2(int i, int j)//返回从(i,j)到达最底层的最大路径之和

{

if (maxSum[i][j] != -1) return maxSum[i][j];

if (i == N) maxSum[i][j] = D[i][j];

else

{

int x = fun2(i + 1, j);

int y = fun2(i + 1, j + 1);

maxSum[i][j] = D[i][j] + (x > y ? x : y);

}

return maxSum[i][j];

}

//代码三:递归变递推

int fun3()

{

int i, j,max;

for (j = 1; j <= N; j++) maxSum[N][j] = D[N][j];

for (i = N - 1; i >= 1; i--)

{

for (j = 1; j <= i; j++)

{

int max = (maxSum[i + 1][j] > maxSum[i + 1][j + 1] ? maxSum[i + 1][j] : maxSum[i + 1][j + 1]);

maxSum[i][j] = D[i][j] + max;

}

}

return maxSum[1][1];

}

//代码四:递归变递推并在空间上做优化

int fun4()

{

int i, j;

for (i = N - 1; i >= 1; i--)

{

for (j = 1; j <= i; j++)

{

int max = (D[i + 1][j] > D[i + 1][j + 1] ? D[i + 1][j] : D[i + 1][j + 1]);

D[i][j] = D[i][j] + max;

}

}

return D[1][1];

}

int main(int argc, char *argv[])

{

int i,j, sel,max;

printf("请输入数字三角形数塔层数:");

scanf_s("%d", &N);

printf("请输入数字三角形数塔数表:\n");

for (i = 1; i <= N; i++)

{

for (j = 1; j <= i; j++)

{

scanf_s("%d", &D[i][j]);

maxSum[i][j] = -1;

}

}

printf("fun1:纯粹递归\n\

fun2:记忆型递归\n\

fun3:递归变递推\n\

fun4:空间优化的递归变递推\n\

请选择计算方式:");

scanf_s("%d", &sel);

switch (sel) {

case 1:

max = fun1(1,1);

case 2:

max = fun2(1,1);

case 3:

max = fun3();

case 4:

max = fun4();

}

printf("数字三角形最佳路径的数字之和:%d\n", max);

return 0;

}

以上程序编译运行后结果如下:

请输入数字三角形数塔层数:3

请输入数字三角形数塔数表:

5

2 7

8 4 1

fun1:纯粹递归

fun2:记忆型递归

fun3:递归变递推

fun4:空间优化的递归变递推

请选择计算方式:3

数字三角形最佳路径的数字之和:16

编辑距离问题:设A和B是两个字符串,要用最少的字符操作将字符串A转换为字符串B,这里所说的字符操作包括(1):删除一个字符;(2):插入一个字符;(3):修改一个字符。将A转换为B所用的最少字符操作数称为A到B的编辑距离,记为d[A][B],d[][]中的A,B指的是A和B的长度,设计一个算法对任给的A,B,计算出d[A][B]。以下是编辑距离问题动态规划算法的C语言程序。

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#define ROWMAX 100

#define COLMAX 100

#define MIN3(a,b,c) ((a)<(b)?((a)<(c)?(a):(c)):((b)<(c)?(b):(c)))

//#define SWAP(a,b)   do{a^=b;b^=a;a^=b;}while(0)

//#define SWAP1(a,b)   do{a=a+b;b=a-b;a=a-b;}while(0)

//#define SWAP2(a,b)   do{a^=b;b^=a;a^=b;}while(0)

//#define SWAP3(a,b)   do{typeof(a) t=(a);(a)=typeof(a)(b);(b)=t;}while(0)

void SWAP(int *a, int *b)

{

int temp = *a;                    //需要关注的是改变指针所指变量的值,而不是交换指针值本身

*a = *b;                                   // 是用int temp 而不是int *temp

*b = temp;

}

int mintime_cmp_levenshtein(const char *s1, const char *s2);

int minspace_cmp_levenshtein(const char *s1, const char *s2);

int main(int argc, char *argv[])

{

char str1[] = "Today is Saturday.";

char str2[] = "Tomorrow is Sunday.";

int d,sel;

printf("Please input selection:");

scanf_s("%d", &sel);

if (1 == sel) {

d = mintime_cmp_levenshtein(str1, str2);

}

else if (2 == sel) {

d = minspace_cmp_levenshtein(str1, str2);

}

//int d = cmp_levenshtein(str1, str2);

printf("Edit distance: %d\n", d);

return 0;

}

int mintime_cmp_levenshtein(const char *s1, const char *s2)

{

int row = strlen(s1);               /* s1 的长度 */

int col = strlen(s2);               /* s2 的长度 */

//int mat[row][col];                  /* C99 - variable-length array */

int mat[ROWMAX][COLMAX];

for (int i = 0; i < row; ++i) {        /* 数组的行 */

for (int j = 0; j < col; ++j) {    /* 数组的列 */

if (i == 0) {

mat[i][j] = j;          /* 初始化第1行为 [ 0 1 2 ... ] */

}

else if (j == 0) {

mat[i][j] = i;          /* 初始化第1列为 [ 0 1 2 ... ] */

}

else {

int cost = (s1[i - 1] == s2[j - 1]) ? 0 : 1;     /* 记录s1[i-1]与s2[j-1]是否相等 */

mat[i][j] = MIN3(mat[i - 1][j] + 1,           /* 取三者的最小值 */

mat[i][j - 1] + 1,

mat[i - 1][j - 1] + cost);

}

}

}

return mat[row - 1][col - 1];

}

int minspace_cmp_levenshtein(const char *s1, const char *s2)

{

// create two work vectors of integer distances

int m = strlen(s1);

int n = strlen(s2);

int *v1 = (int*)malloc((n + 1) * sizeof(int));

if (v1 == NULL) {

return -1;

}

int *v2 = (int*)malloc((n + 1) * sizeof(int));

if (v2 == NULL) {

free(v1);

return -1;

}

// initialize v1 (the previous row of distances)

// this row is A[0][i]: edit distance for an empty s1

// the distance is just the number of characters to delete from s2

for (int i = 0; i <= n; ++i) {

v1[i] = i;

}

// calculate v2 (current row distances) from the previous row v1

for (int i = 0; i < m; ++i) {

// first element of v2 is A[i+1][0]

//   edit distance is delete (i+1) chars from s to match empty s2

v2[0] = i + 1;

// use formula to fill in the rest of the row

for (int j = 0; j < n; ++j) {

// calculating costs for A[i+1][j+1]

int deletionCost = v1[j + 1] + 1;

int insertionCost = v2[j] + 1;

int substitutionCost = v1[j];

if (s1[i] != s2[j]) {

++substitutionCost;

}

v2[j + 1] = MIN3(deletionCost, insertionCost, substitutionCost);

}

// copy v2 (current row) to v1 (previous row) for next iteration

SWAP(v1, v2);

//SWAP1(v1, v2);

//SWAP2(v1, v2);

//SWAP3(v1, v2);

}

// after the last swap, the results of v2 are now in v1

int retval = v1[n];

free(v1);

free(v2);

return retval;

}

以上程序编译运行后结果如下:

Please input selection:1

Edit distance: 9

  1. 8  模拟算法

很多算法都是有规律普通的、数值确定的、可以建立可解析的数学模型的;但是在人机交互中也会有一些算法规律特殊、数值不确定的、不能建立解析的数学模型,这时就要采用模拟算法来解决了。模拟算法就是对真实事物或者过程的虚拟。在编程时为了实现某个功能,可以用编程语言来模拟那个功能,模拟成功也就相应地表示编程成功。例如:计算机模拟抛硬币得到正反面的概率的情况。随机函数就是用来模拟自然界中发生的不可预测的情况的模拟算法,C语言中是用srand()和rand()函数来模拟生成随机数。

下面我们用掷骰子游戏和猜数游戏来说明一下模拟算法。

掷骰子游戏问题:要求根据用户输入骰子次数和参赛人数,然后由计算机随机生成每次投掷骰子的点数,再累加得到每一个选手的总点数。算法分析:(1)定义一个随机函数play,根据投掷骰子的次数随机生成每次投掷骰子的点数和总点数。(2)设置一个死循环,可以重复操作。(3)处理每个选手,调用函数play来模拟掷骰子游戏的。以下是掷骰子游戏问题模拟算法的C语言程序。

#include<stdio.h>

#include<stdlib.h>

#include<time.h>

void play(int m);

int main()

{

int n; //骰子次数

int c; //参赛人数

int i; //循环变量

do {

srand((unsigned int)time(NULL));

printf("\n请输入投掷骰子的次数:");

scanf_s("%d", &n);

if (0 == n) {

printf("输入投掷骰子的次数不能为0!");//至少需要投掷一次

break;

}

printf("输入本轮参赛选手人数:");

scanf_s("%d", &c);

if (0 == c) {

printf("输入的参赛选手人数不能为0!");//至少一个参赛选手

break;

}

for (i = 0; i < c; i++) {

printf("第%d位参赛选手投掷的骰子情况:\n", i + 1);

play(n);

}

}while(1);

return 0;

}

void play( int m) {

int i, n = 0, s = 0;

for (i = 1; i <= m; i++)

{

n = rand() % 6 + 1;//生成骰子的六位随机面

printf("第%d次投掷骰子的点数为:%d\n", i, n);

s = s + n;

}

printf("投掷骰子的总点数为:%d\n", s);

}

以上程序编译运行后结果如下:

请输入投掷骰子的次数:3

输入本轮参赛选手人数:3

第1位参赛选手投掷的骰子情况:

第1次投掷骰子的点数为:1

第2次投掷骰子的点数为:1

第3次投掷骰子的点数为:5

投掷骰子的总点数为:7

第2位参赛选手投掷的骰子情况:

第1次投掷骰子的点数为:2

第2次投掷骰子的点数为:6

第3次投掷骰子的点数为:2

投掷骰子的总点数为:10

第3位参赛选手投掷的骰子情况:

第1次投掷骰子的点数为:1

第2次投掷骰子的点数为:5

第3次投掷骰子的点数为:6

投掷骰子的总点数为:12

请输入投掷骰子的次数:

猜数游戏问题:用计算机实现一个随机1~100之间的数字,然后由用户来猜这个数,根据用户猜测的数的大小分别给出不同的提示。算法分析:(1)先通过rand()随机生成一个1~100的数字。(2)通过循环让用户逐个输入要猜测的整数,根据输入的数据和随机数字进行比较。(3)将比较的结果输出。以下是猜数游戏问题模拟算法的C语言程序。

//生成100以内的随机数

#include<stdio.h>//包含生成随机数的函数

#include<stdlib.h>

#include<time.h>

int main()

{

int m, n, i = 0;//i在此要先赋初值0

srand(time(NULL));

n = rand() % 100 + 1;//rand生成的随机数可达65000多,这里除以100

do {

printf("请输入所猜数字:");

scanf_s("%d", &m);

i++;

if (m > n)

printf("你猜的数太大了!\n");

else if (m < n)

printf("你猜的数太小了!\n");

} while (m != n);

printf("你一共猜了%d次,", i);

if (i <= 5)

printf("你很聪明!");

else

printf("你还要多努力!");

return 0;

}

以上程序编译运行后结果如下:

请输入所猜数字:50

你猜的数太小了!

请输入所猜数字:75

你猜的数太小了!

请输入所猜数字:88

你猜的数太大了!

请输入所猜数字:80

你一共猜了4次,你很聪明!

  1. 9  其他算法介绍

通用基础算法也有很多其他算法,比如数值转换算法、高精度求解算法、排序算法、排列组会算法等。按问题数值类型可分为数值算法(蒙特卡洛、龙格库塔、有限差分、有限元等)、非数值算法和半数值算法;按数学建模的类型可分为分类算法(支持向量机、聚类分析、主成分分析、判别分析、典型相关分析等)、优化算法(禁忌搜索、模拟退火、遗传算法、人工神经网络等)、评价算法(理想解法、模糊综合评判法、数据包络分析法、灰色关联分析法、主成分分析法、秩和比综合评价法)和预测算法(微分方程模型、灰色预测模型、马尔科夫预测、时间序列、插值与拟合、神经网络)。

通用基础算法有很多,这里就不一一展示了,下面仅以排序算法为例总结一下算法的复杂度和稳定性(时间复杂度、空间复杂度,以及稳定性如下表所示)。十大排序算法:冒泡排序算法、选择排序算法、插入排序算法、快速排序算法、堆排序算法、希尔排序算法、桶排序算法、计数排序算法、基数排序算法。

中文名称

英文名称

平均时间复杂度

最坏时间复杂度

最好时间复杂度

空间复杂度

稳定性

选择排序

Selection

n2

n2

n2

1

不稳定

冒泡排序

Bubble

n2

n2

n

1

稳定

插入排序

Insertion

n2

n2

n

1

稳定

堆排序

Heap

nlogn

nlogn

nlogn

1

不稳定

希尔排序

Shell

n1.3

n2

n

1

不稳定

归并排序

Merge

nlogn

nlogn

nlogn

1

稳定

快速排序

Quick

nlogn

n2

nlogn

nlogn

不稳定

桶排序

Bucket

n+k

n2

n

n+k

稳定

计数排序

Counting

n+k

n+k

n+k

n+k

稳定

基数排序

Radix

n*k

n*k

n*k

n+k

稳定

排序问题:给一个无序的数列进行重新排序(可升序或降序)。以下是十大排序算法的C++语言程序。

// sortalgo.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

//

#include <iostream>

#include<time.h>

//1——冒泡排序算法

template<typename T>

void bubblesort(T array[], int sz) {

//int sz = sizeof(array) / sizeof(array[0]);

int i = 0, j = 0;

T temp;

for (i = 0; i < sz - 1; i++) {

for (j = 0; j < sz - i - 1; j++) {

if (array[j] > array[j + 1]) {

temp = array[j];

array[j] = array[j + 1];

array[j + 1] = temp;

}

}

}

}

//2——选择排序算法

template<typename T>

void selectsort(T array[], int sz) {

int i = 0, j = 0, minindex = 0;

T temp;

for (i = 0; i < sz; i++) {

minindex = i;

for (j = i; j < sz; j++) {

if (array[j] < array[minindex]) {

minindex = j;

}

}

temp = array[i];

array[i] = array[minindex];

array[minindex] = temp;

}

}

//3——插入排序算法

template<typename T>

void insertsort(T array[], int sz) {

int i, j;

for (i = 1; i < sz; i++) {

T temp = array[i];//未排序的元素

for (j = i; j > 0 && temp < array[j - 1]; j--) {  //将未排序的元素与已排序的元素逐一比较

array[j] = array[j - 1];//移动已排序元素位置

}

array[j] = temp; //找到插入位置了

}

}

//4——快速排序算法

template<typename T>

T partition(T array[], int left, int right) {

int pivot = left;

T key = array[pivot];

while (left < right) {

while (left < right && array[right] >= key) {

right--;

}

array[left] = array[right];

while (left < right && array[left] <= key) {

left++;

}

array[right] = array[left];

}

array[left] = key;

return left;

}

template<typename T>

void qs_recursive(T array[], int left, int right) {

T middle;

if (left < right) {

middle = partition(array, left, right);

qs_recursive(array, left, middle - 1);

qs_recursive(array, middle + 1, right);

}

}

template<typename T>

void quicksort(T array[], int  sz) {

int left = 0;

int right = sz - 1;

qs_recursive(array, left, right);

}

//5——堆排序算法

template<typename T>

void swap(T *a, T *b) {

T temp;

temp = *a;

*a = *b;

*b = temp;

}

template<typename T>

void heapajust(T array[], int  index, int  sz) {

int max = index;

int left = 2 * index + 1;

int right = 2 * index + 2;

if (left < sz && array[left] > array[max]) {

max = left;

}

if (right < sz && array[right] > array[max]) {

max = right;

}

if (max != index) {

swap(&array[max], &array[index]);

heapajust(array, max, sz);

}

}

template<typename T>

void heapsort(T array[], int  sz) {

int i, j;

//堆初始化(将数组按照堆重排)

for (i = sz / 2 - 1; i >= 0; i--) {

heapajust(array, i, sz);

}

//堆排序

for (j = sz - 1; j >= 0; j--) {

swap(&array[0], &array[j]);

heapajust(array, 0, j);

}

}

//6——希尔排序算法

template<typename T>

void shellsort(T array[], int sz) {

int gap, i, j;

for (gap = sz; gap > 0; gap /= 2) {

for (i = gap; i < sz; i++) {

T temp = array[i];//未排序的元素

for (j = i; j > 0 && temp < array[j - 1]; j--) {  //将未排序的元素与已排序的元素逐一比较

array[j] = array[j - 1];//移动已排序元素位置

}

array[j] = temp; //找到插入位置了

}

}

}

7——归并排序算法

//template<typename T>

//void merge(T array[], T aux[], int left, int right, int middle) {

//  //int len = right - left + 1;

//  //T aux[right - left + 1];

//  int i, j, k;

//  for (k = left; k <= right; k++) {

//      aux[k - left] = array[k];

//  }

//  i = left;

//  j = middle + 1;

//  for (k = left; k <= right; k++) {

//      if (i > middle) {

//          array[k] = aux[j - left];

//          j++;

//      }

//      else if (middle > right) {

//          array[k] = aux[i - left];

//          i++;

//      }

//      else if (aux[j - left] > aux[i - left]) {

//          array[k] = aux[j - left];

//          j++;

//      }

//      else {

//          array[k] = aux[i - left];

//          i++;

//      }

//

//  }

//

//}

//

//template<typename T>

//void mergerecursive(T array[], T aux[], int left, int right) {

//  if (left >= right) {

//      return;

//  }

//  //aux = NULL;

//  int middle = (left + right) / 2;

//  mergerecursive(array, aux, left, middle);

//  mergerecursive(array, aux, middle + 1, right);

//  merge(array, aux, left, right, middle);

//}

//

//template<typename T>

//void mergesort(T array[], int sz) {

//  int left = 0, right = sz - 1;

//  T aux[sz];

//  //T *aux = (T *)malloc(sz);

//  //T aux[] = temp;

//  mergerecursive(array, aux, left, right);

//  //free(aux);

//}

//8——桶排序算法

//template<typename T>

//#define LMAX 100

//void bucketsort(T array[], int sz) {

//  int k = 0, i = 0, j = 0;

//  //根据原数组元素取值范围[min,max]确定桶的个数len

//  int min = array[0], max = array[0], len = 0;

//  for (k = 0; k < sz; k++) {

//      if (array[k] > max)

//          max = array[k];

//      if (array[k] < min)

//          min = array[k];

//  }

//  int b = 5; //计数排序 b=1,桶排序不一定

//  len = (max - min) / b + 1;

//  if (len > LMAX) {

//      std::cout << "len > LMAX" << std::endl;

//  }

//

//  //T bucket[LMAX] = { 0 };

//  T buckets[len][0];

//  //T *bucket=new T(len);

//  /*int *bucket = (int*)malloc(sizeof(int)*len);

//  memset(bucket, 0, sizeof(int)*len);*/

//

//  //桶计数

//  for (i = 0; i < sz; i++) {

//      int index = (array[i] - min) / b + 1;

//      buckets[index] = arrAppend(buckets[index], array[i]);

//  }

//

//  //原数组重新排序

//  /*for (j = min, i = 0; j < LMAX; j++) {

//      while ((bucket[j]--) > 0)

//          array[i++] = j;

//  }

//*/

//  int arrIndex = 0;

//  for (i = 0; i < len; i++) {

//      T bucket[] = buckets[i];

//      if (sizeof(bucket) <= 0) {

//          continue;

//      }

//      int sz = sizeof(bucket) / sizeof(bucket[0]);

//      // 对每个桶进行排序,这里使用了插入排序

//      insertsort(bucket, sz);

//      for (j = 0; j < sz; j++) {

//          array[arrIndex++] = bucket[j];

//      }

//  }

//}

//

//

///**

//  * 自动扩容,并保存数据

//  *

//  * @param arr

//  * @param value

//  */

//template<typename T>

//T* arrAppend(T* arr, int value) {

//  //arr = Arrays.copyOf(arr, arr.length + 1);

//  //arr[arr.length - 1] = value;

//  int length = sizeof(arr) / sizeof(arr[0]);

//  memcpy(arr, arr, (length + 1) * sizeof(T));

//  arr[length] = value;

//  return arr;

//}

//9——计数排序算法

template<typename T>

#define LMAX 100

void countsort(T array[], int sz) {

int k = 0, i = 0, j = 0;

//根据原数组元素取值范围[min,max]确定桶的个数len

int min = array[0], max = array[0], len = 0;

for (k = 0; k < sz; k++) {

if (array[k] > max)

max = array[k];

if (array[k] < min)

min = array[k];

}

len = max - min + 1;

if (len > LMAX) {

std::cout << "len > LMAX" << std::endl;

}

T count[LMAX] = { 0 };

//桶计数

for (i = 0; i < sz; i++) {

count[array[i]]++;

}

//原数组重新排序

for (j = min, i = 0; j < len; j++) {

while ((count[j]--) > 0)

array[i++] = j;

}

}

//10——基数排序算法

template<typename T>

#define MAX 100

#define BASE 10

void radixsort(T array[], int sz) {

int i, exp = 1;

T m = array[0], temp[MAX] = { 0 };

for (i = 0; i < sz; i++) {

if (m < array[i]) {

m = array[i];

}

}

while (m / exp > 0) {

//基数桶清零

int bucket[BASE] = { 0 };

//基数桶记录

for (i = 0; i < sz; i++) {

bucket[(array[i] / exp) % BASE]++;

}

//基数桶记录叠加

for (i = 1; i < sz; i++) {

bucket[i] += bucket[i - 1];

}

//排序到临时数组中

for (i = sz - 1; i >= 0; i--) {

temp[--bucket[(array[i] / exp) % BASE]] = array[i];

}

//临时数组赋值给原数组排序

for (i = 0; i < sz; i++) {

array[i] = temp[i];

}

exp *= BASE;

}

}

#define ANUM 15

int main()

{

//std::cout << "Hello World!\n";

/*int arr[] = { 65,58,95,10,57,62,13,106,78,23,85 };*/

int arr[ANUM];

int sz = sizeof(arr) / sizeof(arr[0]);

srand((unsigned int)time(NULL));

for (int i = 0; i < sz; i++) {

arr[i] = rand() % 100;

}

std::cout << "数组大小:" << sz << std::endl;

std::cout << "排序前:" << std::endl;

for (int i = 0; i < sz; i++) {

std::cout << arr[i] << " ";

}

std::cout << std::endl;

std::cout << "1——冒泡排序算法" << std::endl;

std::cout << "2——选择排序算法" << std::endl;

std::cout << "3——插入排序算法" << std::endl;

std::cout << "4——快速排序算法" << std::endl;

std::cout << "5——堆排序算法" << std::endl;

std::cout << "6——希尔排序算法" << std::endl;

std::cout << "7——归并排序算法" << std::endl;

std::cout << "8——桶排序算法" << std::endl;

std::cout << "9——计数排序算法" << std::endl;

std::cout << "10——基数排序算法" << std::endl;

std::cout << "请选择排序算法:";

int sel_num;

scanf_s("%d", &sel_num);

switch (sel_num) {

case 1:

bubblesort(arr, sz);

break;

case 2:

selectsort(arr, sz);

break;

case 3:

insertsort(arr, sz);

break;

case 4:

quicksort(arr, sz);

break;

case 5:

heapsort(arr, sz);

break;

case 6:

shellsort(arr, sz);

break;

case 7:

//mergesort(arr, sz);

break;

case 8:

//bucketsort(arr, sz);

break;

case 9:

countsort(arr, sz);

break;

case 10:

radixsort(arr, sz);

break;

default:

break;

}

std::cout << "排序后:" << std::endl;

for (int i = 0; i < sz; i++) {

std::cout << arr[i] << " ";

}

return 0;

}

以上程序编译运行后结果如下:

数组大小:15

排序前:

33 29 21 47 94 27 18 55 56 89 29 20 31 29 89

1——冒泡排序算法

2——选择排序算法

3——插入排序算法

4——快速排序算法

5——堆排序算法

6——希尔排序算法

7——归并排序算法

8——桶排序算法

9——计数排序算法

10——基数排序算法

请选择排序算法:4

排序后:

18 20 21 27 29 29 29 31 33 47 55 56 89 89 94

1. 通用基础算法(1.7动态规划算法/1.8模拟算法/1.9其他算法)相关推荐

  1. 2022劳务员-通用基础(劳务员)复训题库及在线模拟考试

    题库来源:安全生产模拟考试一点通公众号小程序 2022劳务员-通用基础(劳务员)判断题系劳务员-通用基础(劳务员)复习题高频考题覆盖!2022劳务员-通用基础(劳务员)复训题库及在线模拟考试依据劳务员 ...

  2. 【无标题】2022标准员-通用基础(标准员)复训题库及在线模拟考试

    题库来源:安全生产模拟考试一点通公众号小程序 2022标准员-通用基础(标准员)全部考试题库是标准员-通用基础(标准员)考试真题考前押题密卷!2022标准员-通用基础(标准员)复训题库及在线模拟考试根 ...

  3. 【无标题】2022劳务员-通用基础(劳务员)复训题库及在线模拟考试

    题库来源:安全生产模拟考试一点通公众号小程序 2022劳务员-通用基础(劳务员)考试题目是劳务员-通用基础(劳务员)全部考试题库历年真题!2022劳务员-通用基础(劳务员)复训题库及在线模拟考试根据劳 ...

  4. 2020年市政方向-通用基础(施工员)答案解析及市政方向-通用基础(施工员)考试总结

    题库来源:安全生产模拟考试一点通公众号小程序 2020年市政方向-通用基础(施工员)答案解析及市政方向-通用基础(施工员)考试总结,包含市政方向-通用基础(施工员)答案解析答案和解析及市政方向-通用基 ...

  5. 2022材料员-通用基础(材料员)考试题及模拟考试

    题库来源:安全生产模拟考试一点通公众号小程序 2022材料员-通用基础(材料员)复训题库是材料员-通用基础(材料员)试题仿真模拟预测!2022材料员-通用基础(材料员)考试题及模拟考试根据材料员-通用 ...

  6. 2021年施工员-市政方向-通用基础(施工员)考试及施工员-市政方向-通用基础(施工员)复审考试

    题库来源:安全生产模拟考试一点通公众号小程序 安全生产模拟考试一点通:施工员-市政方向-通用基础(施工员)考试考前必练!安全生产模拟考试一点通每个月更新施工员-市政方向-通用基础(施工员)复审考试题目 ...

  7. 2021年质量员-市政方向-通用基础(质量员)最新解析及质量员-市政方向-通用基础(质量员)证考试

    题库来源:安全生产模拟考试一点通公众号小程序 质量员-市政方向-通用基础(质量员)最新解析根据新质量员-市政方向-通用基础(质量员)考试大纲要求,安全生产模拟考试一点通将质量员-市政方向-通用基础(质 ...

  8. 2020资料员-通用基础(资料员)模拟考试题库及资料员-通用基础(资料员)考试试题

    题库来源:安全生产模拟考试一点通公众号小程序 2020资料员-通用基础(资料员)模拟考试题库及资料员-通用基础(资料员)考试试题,包含资料员-通用基础(资料员)模拟考试题库答案解析及资料员-通用基础( ...

  9. 2020土建方向-通用基础(施工员)考试题及土建方向-通用基础(施工员)考试题库

    题库来源:安全生产模拟考试一点通公众号小程序 2020土建方向-通用基础(施工员)考试题及土建方向-通用基础(施工员)考试题库,包含土建方向-通用基础(施工员)考试题答案解析及土建方向-通用基础(施工 ...

  10. 2020年市政方向-通用基础(施工员)考试题及市政方向-通用基础(施工员)考试平台

    题库来源:安全生产模拟考试一点通公众号小程序 2020年市政方向-通用基础(施工员)考试题及市政方向-通用基础(施工员)考试平台,包含市政方向-通用基础(施工员)考试题答案和解析及市政方向-通用基础( ...

最新文章

  1. 这套“人造肌腱”装备,可保护你的老腰|Science子刊
  2. linux清屏命令clear和reset
  3. 地市级地铁数据管理信息系统解决方式
  4. PHP-代码审计-ini配置文件
  5. python爬取基金历史净值_Python爬取天天基金网历史净值数据
  6. php 显示当前年月日时分秒,php 获取当前前后年、月、星期、日、时分秒的时间...
  7. 一文带你了解MultiBERT
  8. linux运行asm文件,linux – 尝试在Ubuntu上的NASM上运行.asm文件时出错
  9. 技术分享PPT整理(一):Bootstrap基础与应用
  10. 记12306货运系统“抢订空车”插件的编写--订车流程梳理
  11. coreldraw怎样定数等分_coreldraw 里怎么将线段等分?
  12. 泰坦尼克号幸存者的预测
  13. β阶段第一周版本控制报告
  14. 5 打印选课学生名单 (25分)
  15. vue element 重新上传图片(将已经上传过的图片链接重新上传)
  16. 支招:苹果电脑Mac版如何快速解压缩软件
  17. 手摸手教会你三次握手和四次挥手
  18. 收集的几个自定义的404页面的模板
  19. WineQQ 转自 清风的网络空间
  20. C4D致富经典入门到精通(七)

热门文章

  1. linux php配置
  2. Java入门基础知识点一
  3. violate在c语言中的作用,Violate的应用和作用
  4. webpack配置完全指南
  5. You need Perl 5 安装openssl时报错,提示需要安装perl 5
  6. 物资管理系统的设计与实现
  7. 微信小程序实现一个表格table
  8. 苹果手机用什么无线耳机比较好?苹果耳机平替品牌推荐
  9. 基于面向对象 来写一个简单的贪吃蛇小游戏(代码可直接用)
  10. Java互联网架构-企业级实战秒杀系统优化方案与应用思路