C语言逻辑挑战:将数组按字母顺序排序

4

我是一个初学者,目前正在学习C语言。我已经花了一周的时间来解决这个问题,但似乎无法理清逻辑。以下是我正在使用的书上的内容:

编写一个程序,使用一个字符串数组来存储以下名称:

  • "Florida"
  • "Oregon"
  • "Califoria"
  • "Georgia"

使用上述字符串数组,编写自己的sort()函数,并使用strcmp()函数按字母顺序显示每个州的名称。

所以,假设我有:

char *statesArray[4] = {"Florida", "Oregon", "California", "Georgia"}; 

我应该使用嵌套for循环,比如strcmp(string[x], string[y])...吗?我已经尝试了很多次,但是我对于解决这个问题所需的算法仍然感到困惑,即使是在效率上稍微好一点的情况下。非常感谢您的帮助!


2
你可能需要对排序算法做些研究。在对数字列表和按字母表顺序对单词列表进行排序之间唯一的区别是比较方法,这个非常容易实现。 - Dan F
2
先放松一下,去享受一杯美好的茶或其他什么。当你回来时,一步一步地进行。首先填充数组,然后再考虑排序问题。 - Dennis Meng
4
http://en.wikipedia.org/wiki/Bubble_sort - Oscar
3
1)对4个元素进行快速排序? 2)考虑到发帖者相对较新于编程,建议他使用冒泡/插入/选择排序,以便能够编写逻辑代码。 - Dennis Meng
2
@GeorgeMitchell 快速排序可能不是初学者最简单的解决方案。我建议从物理类比开始 - 如果我给你一堆棒球卡片或其他东西,并告诉你要对它们进行排序,你会怎么做?很少有人会想到快速排序。我怀疑大多数人基本上会从插入或选择排序开始。 - twalberg
显示剩余6条评论
6个回答

6
是的,你可以使用嵌套的for循环进行排序。在了解strcmp()函数的工作原理后,应该会比较容易:

strcmp(char *string1, char *string2)

  • 如果返回值是< 0,则表示string1小于string2

  • 如果返回值是> 0,则表示string2小于string1

  • 如果返回值是= 0,则表示string1等于string2

从这一点上,您可以选择任何排序方法。

这个网站有大量演示各种排序的优秀图形示例,并包括给定算法的伪代码。


6
假设你需要对数组进行排序,可以将每个状态写在卡片上,那么你会如何将它们按顺序排列?有很多种方法,每一种都被称为算法。
其中一种方法是查找第一个状态,通过查看每张卡片并在脑海中记录你所见过的最低状态来实现。查看完所有卡片后,你将得到最低状态。将其放入新堆中,然后重复操作,寻找剩下卡片中最低状态。
重复以上步骤,直到原始堆中没有卡片为止。这是一种众所周知的简单但缓慢的算法,这是我首先会使用的方法。
还有其他方法可供选择。

5

您需要“任何”排序算法还是“高效”的排序算法?

为了简单起见,我可以向您展示如何实现一种简单但不高效的排序算法。 它是通过使用“双重循环”的方法来实现的! 然后,使用相同的思路,您可以将其修改为任何其他高效算法(如希尔排序或快速排序)。

对于数字,您可以按以下顺序放置数组(正如您可能知道的那样):

int intcmp(int a, int b) {
    return (a < b)? -1: ((a > b)? +1: 0);
}

int main(void) {
   int a[5] = {3, 4, 22, -13, 9};

   for (int i = 0; i < 5; i++) {
      for (int j = i+1; j < 5; j++)
         if (intcmp(a[i], a[j]) > 0) {
            int temp = a[i]; 
            a[i] = a[j]; 
            a[j] = temp; 
         }
       printf("%d ", a[i]);
   }
}

现在唯一改变的是你有了字符串而不是整数。因此,你需要考虑一个字符串数组:
 char *a[] = {"Florida", "Oregon", "Califoria", "Georgia"};

然后,您需要将temp的类型更改为char*,最后将函数intcmp()替换为strcmp()

函数strcmp(s1, s2)(来自<string.h>)返回一个数字。如果s1是一个“小于”s2的字符串,则返回<0;如果s1与s2“相等”,则返回==0;否则返回>1。

程序看起来像这样:
#include <stdio.h>
#include <string.h>
int main(void) {
   char *a[] = {"Florida", "Oregon", "Califoria", "Georgia"};

   for (int i = 0; i < 4; i++) {
      for (int j = i+1; j < 4; j++)
         if (strcmp(a[i], a[j]) > 0) {
            char* temp = a[i]; 
            a[i] = a[j]; 
            a[j] = temp; 
         }
       printf("%s ", a[i]);
     }
   getchar();
   return 0;  
}

请注意,在printf()语句中,我们将"%d "更改为"%s ",以便正确显示字符串。
最后的评论:当您编写更好的算法(例如快速排序)时,只需更改比较函数即可,因为算法相同,无论您要比较的数据类型如何。
请注意,我使用了一个“巧妙”的方法。正如您所看到的,我已将变量a定义为一个指向字符串的指针。初始化器使用了一个常量字符串数组,然后用它初始化了变量a。现在,变量a可以安全地作为一个由4个指向字符串的指针组成的数组来处理和索引。
这就是为什么双重循环算法中的“交换”可以正常工作的原因:交换的是内存地址而不是整个字符串。

3

你可能需要采取以下步骤:

  1. 填充数组以包含州的名称
  2. 创建方法,以在数组中就地交换两个州
  3. 此时,您已拥有使用strcmp实现任何选择的排序算法所需的所有工具

大多数排序方法依赖于两件事:

  1. 能够重新排列列表(即交换)
  2. 能够比较列表中的项,以查看是否应将它们交换

我建议先确保这两件事正常工作,然后其他的只是学习特定的排序算法。


1
小心一个令人头痛的问题:字符串是按ASCII数字表示排序的,因此如果您按字母顺序排序,任何大写字母都会排在小写字母之前,例如"alpha","beta","gamma","Theta"将按以下方式排序: Theta,alpha,beta,gamma。

0

当涉及到您在此处列出的示例数组时,先前提到的简单算法实际上可能是最有效的。我所指的算法是从第一个元素开始,然后将其与其他元素进行比较并用找到的最小值替换,然后继续到下一个元素执行相同的操作,但不要将其与已排序的元素进行比较。

虽然这个算法的执行时间为O(n^2),其中n是数组中元素的数量。对于较小的数组,它通常比快速排序(执行时间为O(n*log(n)))更快。原因是快速排序有更多的开销。对于较大的数组,快速排序比其他方法更好,如果我没记错的话,这个方法被称为替换排序,尽管我在另一个答案中看到它被称为“双重循环”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接