【问题标题】:Sorting of Arrays Alphabetically?数组按字母顺序排序?
【发布时间】:2011-09-21 15:48:10
【问题描述】:

假设我有两个字符串数组,名为“arrayone”和“arraytwo” 我将如何按字母顺序(从 A 到 Z)对“arrayone”进行排序,同时仍保持与我的第二个数组的关系。

如果您想知道“arrayone”和“arraytwo”中有什么,1 有姓氏,2 有每个人的年龄。我的最终结果是将其添加到 Richedit 中。

场景示例:

Smith           25 
Appleseed       32
Gibbs           45

必须变成:

Appleseed       32
Gibbs           45
Smith           25

请不要使用字符串列表,将其保存在简单的数组和过程中。

更新:我切换到录制。

试过这段代码没有用

for i := 0 to 26 do
for j := 0 to 26 do
  if recordname.surname[j] > recordname.surname[j+1] then begin
    line := recordname.surname[j];
    line[j] := recordname.surname[j+1];
    recordname.surname[j+1] := line;
  end;

上面写着不兼容的类型:'Char' 和 'String'

【问题讨论】:

  • 你的数据结构错误。你没有两个数组。您有一个数组,每个元素都是一个名称、值对。在继续之前,请考虑切换到正确的数据结构。
  • @David,我有两个数组。我将如何将其合并到一个多维数组中然后继续?
  • 你想要array of record。在现代 Delphi 中,您将使用 TList<TStringIntegerPair>
  • @BlackJack,我正在做 BubbleSort。到目前为止还没有太多
  • @David,好的,我如何将 2 个数组转换为记录数组?

标签: delphi delphi-7


【解决方案1】:

在为您提供了有关数据结构的建议并看到了随之而来的困难之后,我想直截了当并更清楚地解释我的意思。

您的原始代码有两个基本上没有连接的数组。您可以交换一个数组中的项目,而很容易忘记为另一个数组这样做。在我看来,姓名/年龄对真的不应该分开。这导致以下类型声明。

type
  TPerson = record
    Name: string;
    Age: Integer;
  end;

现在你需要保存TPerson的数组。

type
  TPersonArray = array of TPerson;

为了执行排序,您需要能够比较两个项目并交换它们。

function Compare(const Person1, Person2: TPerson): Integer;
begin
  Result := CompareText(Person1.Name, Person2.Name);
end;

procedure Swap(var Person1, Person2: TPerson);
var
  temp: TPerson;
begin
  temp := Person1;
  Person1 := Person2;
  Person2 := temp;
end;

现在我们可以用冒泡排序将所有这些放在一起。

procedure Sort(var People: TPersonArray);
var
  i, n: Integer;
  Swapped: Boolean;
begin
  n := Length(People);
  repeat
    Swapped := False;
    for i := 1 to n-1 do begin
      if Compare(People[i-1], People[i])>0 then begin
        Swap(People[i-1], People[i]);
        Swapped := True;
      end;
    end;
    dec(n);
  until not Swapped;
end;

现在,如果您想使用更复杂的比较运算符,则只需替换 Compare。例如,如果您想按年龄对任何同名的人进行排序,那么您可以使用字典比较函数。

function Compare(const Person1, Person2: TPerson): Integer;
begin
  Result := CompareText(Person1.Name, Person2.Name);
  if Result=0 then begin
    Result := Person2.Age-Person1.Age;
  end;
end;

我已经逐条写了这个答案,这就是你应该如何处理这样一个更大的问题。尝试将其分解成更小的部分,每个部分都易于管理。

【讨论】:

  • 冒泡排序只是性能的噩梦。但无论如何,我知道这是出于教学目的,您从一个困惑的问题中做出了明确的回答。
  • 在长循环中调用 CompareText 比直接转换记录字符串慢大约 3 倍(经过测试),最好只执行 "if person[a].name
  • @hikari:CompareText 不区分大小写。如果您要比较两种方法,请确保它们执行相同的操作;你必须把它改成CompareStr,或者写if LowerCase(person[a].name) < LowerCase(person[b].name)
【解决方案2】:

我们的TDynArray wrapper 只是明确处理此功能。

您可以使用自定义排序函数直接就地排序任何现有动态数组,或使用索引的整数数组。

function PersonCompare(const Person1, Person2: TPerson): Integer;
begin // sample function pasted from David's answer
  Result := CompareText(Person1.Name, Person2.Name);
  if Result=0 then 
    Result := Person2.Age-Person1.Age;
end;

type
  TPersonDynArray = array of TPerson;

function SortPersons(var Persons: TPersonDynArray);
var
  Person: TDynArray;
begin
  Person.Init(TypeInfo(TPersonDynArray),Persons);
  Person.Compare := PersonCompare;
  Person.Sort;
end;

顺便说一下,包装器的Sort方法会使用优化过的快速排序,比冒泡排序算法快很多。

这个包装器中还有更多功能,例如类似 TList 的方法,如 Add() 或 Delete(),使用外部 Count 变量(添加速度更快),序列化或使用散列快速查找。

它适用于 Delphi 5 到 XE2,并且是开源的。

【讨论】:

    【解决方案3】:

    无需创建包含两组数据点的新结构,您可以使用基于 arrayone 进行检查的比较函数对索引数组进行排序。

    更具体地说,最初使用indices[i] = i 创建一个数组indices

    然后,使用比较函数对indices进行排序

    i < j iff arrayone[indices[i]] < arrayone[indices[j]]
    

    那么,读取arrayone[indices[0]], arrayone[indices[1]] ...给你排序后的列表,对应的值为arraytwo[indices[0]], arraytwo[indices[1]], ...

    【讨论】:

    • 解决方案是正确的,但语法不正确(对于 Delphi)。不过,+1。
    • FWIW 正确语法:if arrayone[indices[i]] &lt; arrayone[indices[j]] then Result := 1 else if arrayone[indices[i]] &gt; arrayone[indices[j]] then Result := -1 else Result := 0;,但格式正确。无需检查 i
    • @Rudy:i &lt; j iff ...这行可能是用另一种语言写的,即数学语言(带有一些伪代码元素)。您可能知道,iff 代表“当且仅当”,即逻辑等价。
    • @RudyVelthuis 你没有说明你使用的是哪个版本的delphi,所以我只是给出了一个高级描述
    • 我没有问这个问题。 Delphi 的所有版本的语法实际上都是相同的,所以确切的版本无关紧要。
    【解决方案4】:

    使用您选择的排序算法对第一个数组进行正常排序。任何介绍算法的教科书都会有几个。每次交换第一个数组的两个条目时,对第二个数组的相应条目进行相同的更改。

    【讨论】:

    • 这行得通,但设计(使用单独的数组)有点不稳定,IMO。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-18
    • 2017-05-18
    • 1970-01-01
    • 1970-01-01
    • 2021-06-25
    • 1970-01-01
    相关资源
    最近更新 更多