要求#

将字符串按ASCLL码升序排序

冒泡排序法#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <string.h>
#define M 5
int main()
{
char *str[M] = {"China", "Japan", "Korea", "American", "England"};
for (int j = 0; j < M; j++) {
for (int i = 0; i < M - j - 1; i++) {
if (strcmp(str[i], str[i + 1]) > 0) {
char *temp;
temp = str[i];
str[i] = str[i + 1];
str[i + 1] = temp;
}
}
printf("%s ", str[j]);
}
return 0;
}

输出//China American England Japan Korea

结果错误

不能再内部循环中输出, 为啥???

因为 在j=0的时候,内循环完成排序为 C J A E K ,并未完全排序完成,就已经执行了打印语句,输出了str[0] ,即"China",余下相同原因.

应后面另外加输出语句,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <stdio.h>
#include <string.h>
#define M 5
int main()
{
char *str[M] = {"China", "Japan", "Korea", "American", "England"};
for (int j = 0; j < M; j++) {
for (int i = 0; i < M - j - 1; i++) {
if (strcmp(str[i], str[i + 1]) > 0) {
char *temp;
temp = str[i];
str[i] = str[i + 1];
str[i + 1] = temp;
}
}
printf("%s ", str[j]);
}
printf("\n");
for (int i = 0; i < M; i++) {
printf("%s ", str[i]);
}
return 0;
}
//输出
// China American England Japan Korea
// American China England Japan Korea
//排序过程
// C J K A E
// C J K A E
// C J A K E
// C J A E K

// C J A E K
// C A J E K
// C A E J K

// A C E J K
// A C E J K

// A C E J K

不知名 排序(我不知道哈哈)#

这个在内部输出正确的,是因为在完成第一次内部循环时,排序为A J K C E,输出了str[0],即"American"

第二次内部循环时,排序为A C J K E,输出了str[1],即"China",

…余下同样原理,

不具有普遍性,不建议使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#include <string.h>
#define M 5
int main()
{
char *str[M] = {"China", "Japan", "Korea", "American", "England"};
for (int i = 0; i < M; i++) {
for (int j = i + 1; j < M; j++) {
if (strcmp(str[i], str[j]) > 0) {
char *temp;
temp = str[i];
str[i] = str[j];
str[j] = temp;
}
}
printf("%s ", str[i]); //最好不在内部输出,另起一个循环输出
}
return 0;
}
//排序过程
// C J K A E
// C J K A E
// A J K C E
// A J K C E

// A J K C E
// A C K J E
// A C J K E

// A C J K E
// A C E K J

// A C E J K

简单选择排序#

效率最高,只用执行3次交换.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <string.h>
void main()
{
char *n[] = {"China", "Japan", "Korea", "American", "England"}, *temp;
int i, j, k;
for (i = 0; i < 5; i++) {
k = i;
for (j = i + 1; j < 5; j++)
if (strcmp(n[k], n[j]) > 0)
k = j; //找出最小值
if (k != i) {
temp = n[k];
n[k] = n[i];
n[i] = temp;
}
printf("%s ", n[i]);
}
}

怎么运行排序的呢?

思路:第一次外循环从5个字符串中,找出最小的一个,交换到第一个位置。

第二次外循环 从后4个字符串中,找出最小的一个,交换到第二个位置。

…余下原理相同,

即最多执行5次交换,最少0次,效率最高.

妙啊

以下为了方便,统一用字符串的首字母代表字符串.例: C 即代表 “China”

可以发现,只进行了三次交换

第一次交换 : A J K C E

第二次交换 : A C K J E

第三次交换: A C E J K

可以得出,第一次交换完成后,得到的排序应是 A J K C E 。在进行第二次外循环的时候,即i=1时,内循环中 j=i+1=2,循环条件为 j<5 ,循环变量增值为 j++,所以理论上会循环j=2,j=3,j=4 ,一共3次。

循环中的判断条件为 strcmp(n[k],n[j])>0 ,即当n[k]>n[j]时,条件成立,执行if内语句,否者将不执行。

前有赋值语句k=i,如果只讨论第二次外循环,在内循环中,k的值可以确定为与i相等,即k=1。而j的可能值前已经讨论过了,一共有三个值,分别是2,3,4。

现在我们分三种情况,讨论内循环中判断语句的执行情况。

1、当k=1,j=2时, n[k] = n[1]= J , n[j] = n[2] = K ,在ASCLL码中,J小于K,所以 n[k]>n[j] 不成立,不执行条件语句。

2、当k=1,j=3时, n[k] = n[1]= J , n[j] = n[3] = C , 在ASCLL码中,J大于C,所以 n[k]>n[j] 成立, 应当执行if内的赋值语句k=j,将当前j的值赋值给k。 注意:!!!!此时k值改变,下次循环将比较 n[3]与n[4] 。

3、当j=4时, n[j] = n[4] = E,注意,k不再等于1了, 上次循环已经改变k的值,k=3。所以 n[k] = n[3]= C, 在ASCLL码中,C小于E, 所以 n[k]>n[j] 不成立,不执行条件语句。

余下以此类推…