Problem z sortowaniem TStringList za pomoca Insertion-Sort

0

Hej , mam problem z posortowaniem TStringListy w InsertionSort . Stworzylem TStriingListe, wczytalem plik txt do ListBoxa , jednak moja procedura nie dziala jak powinna i pojawia sie blad 'unit1.pas(54,27) Fatal: Syntax error, "THEN" expected but "identifier DONE" found'. Bylbym wdzieczny za pomoc , pozdrawiam

procedure InsertionSort(Items: TStrings);
var
  i, Position, n: integer;
  Value: string;
  Done        : boolean;
begin
  n := Items.Count;

  for i := 1 to n - 1 do
  begin
    Value := Items[i];
    Position := i;
    Done := false;

    while not done do
    begin
      if Position         Done := true
      else
        if Value = Items[Position - 1] then
          Done := true
        else
        begin
          Items[Position] := Items[Position - 1];
          Position := Position - 1;
        end;
    end;

    Items[Position] := Value;
  end;
end;             
´´´
2

czy to trudno zobaczyć, gdzie if nie spotyka się z then ? Wymaga doktoratu? Dla ułatwienia, jest tam Done ....

BTW nie "program nie działa", a "się nie kompiluje" i o działaniu to jeszcze jaskółki nie ćwierkają

Po pięciu latach wypadało elementarny elementarz przyswoić

3

If position

Tu masz błąd position to int wiec musisz go z czymś porównać i dać then

A co do sortowania to tstringlist ma property sort i nie musisz ręcznie sortowac

0

dzieki ! z Delphi dopiero zaczynam . funkcja .sort sortuje w QuickSort , a w projekcie chodzi o zestawienie 5 metod sortowania i zmierzenia przy tym czasu .

0

Po wielu probach udalo mi sie posortowac liste , jednak z malym ale , nie sortuje wszystkich elementow poprawnie , konczy na 4 znaku integera:

list.png

procedure InsertionSort(Items: TStrings);
var
  i, Position, n: integer;
  Value: string;
begin
  n := Items.Count;
  for i := 1 to n - 1 do
  begin
    Value := Items[i];
    Position := i-1;
     while (Position >0) and (Items[Position]>Value) do
      begin
        Items[Position+1]:= Items[Position]  ;
        Position := Position -1 ;
        end;
        Items[Position+1] := Value;
  end;
end;

2

Nie ma nic lepszego od tego dla delphi.

{--------------------------------------------------------------------------
A very fast stringlist Quicksorting routine - many many times faster than
Delhpi's built in TStringlist.sort - even in spite of the double casts.
The whole routine sorts 100.000 words in about 1 sec (on a 650MHz machine (sic!)).

It is also much faster than using the TStringlist.Sorted := true property
while filling the stringlist. Set the sorted property to false and sort it using
this routine afterwards.

Copyright Hans J. Klarskov Mortensen 2004 - ([email protected]) Sorting routine
based on M. C. Kerman's book "Programming and Problem Solving
with Delphi", Pearsons Education, 2002.

If anyone can use this unit they're welcome. But I ask you to let
this copyright notice stay and that you don't pretend that you wrote it.

No warranty imaginable accepted. Use at your own risk.

(Language note: My native language is Danish. In this language "ord" means
"word" not ordinal.)

Usage : FastSortStList(YourStringlist);
-------------------------------------------------------------------------}
unit Quicksorting;

interface

uses
  ComCtrls, Classes, Windows, Sysutils;

type
  {This explains part of the speed! I wish I (really) knew why!
  If this declaration is placed in connection with the
  procedure the whole procedure is more than ten times slower.
  The reason may be that placing it here means that the array is
  created when the program loads - if it is declared "locally"
  it is not created until the procedure requests it.}
  OrdArray = array of string;

procedure FastSortStList(Stlist: TStringlist);

implementation

{------------ Standard hand coded quicksort ------------------------------}
{ The sorting is - as you can see - based on ANSI-values, thus it is case sensitive.
If case insensitivity is needed use ANSIUPPERCASE.

If the string variables indicated are replaced by integer variables it'll
happily sort integers as well, but of course a StrToInt cast is needed.
--------------------------------------------------------------------------}

procedure Swap(var Value1, Value2: string);
var
  temp: string; //Integer;
begin
  temp := Value1;
  Value1 := Value2;
  Value2 := temp;
end;

function GetPIndex(lo, hi: Integer): Integer;
var
i : integer;
begin
  i := (lo+hi) div 2;
  GetPIndex := i;
end;
  
procedure Quicksort(low, high: Integer; var Ordliste: OrdArray);
var
  pivotIndex: Integer;
  pivotValue: string;
  left, right: Integer;
begin

  pivotIndex := GetPIndex(low, high);
  pivotValue := Ordliste[pivotIndex];

  left := low;
  right := high;
  repeat

    while ((left <= high) and (Ordliste[left] < pivotValue)) do
    begin
      Inc(left);
    end;

    while ((right >= low) and (pivotValue < Ordliste[right])) do
    begin
      Dec(right);
    end;
    if (left <= right) then
    begin
      Swap(Ordliste[left], Ordliste[right]);
      Inc(left);
      Dec(right);
    end;

  until (left > right);

  if (low < right) then
  begin
    Quicksort(low, right, Ordliste);
  end;

  if (left < high) then
  begin
    Quicksort(left, high, Ordliste);
  end;
end;
{-----------   End of Quicksort routines   -----------------------------}

{-----------   The Stringlist sorting routine with casts   -------------}

procedure FastSortStList(Stlist: TStringlist);
var
  SortArray: OrdArray;
  i, j: Integer;
begin
  //Cast Stringlist to an array
  setlength(sortArray, Stlist.count);
  for i := 0 to Stlist.count - 1 do
    SortArray[i] := Trim(Stlist.strings[i]);

  //Now sort
  QuickSort(Low(SortArray), High(SortArray), SortArray);

  //Recast
  for j := low(SortArray) to High(SortArray) do
    begin //Sometimes empty entries abound, get rid of them
    if StList.strings[j] <> '' then
    Stlist.Strings[j] := Sortarray[j];
    end;

  //Free the array
  SetLength(SortArray,0);
end;

end.

Wywołanie

var
ZaladujListe : TStringList;
begin
  ZaladujListe := TStringList.Create;

  if Opendialog1.Execute then
  ZaladujListe.LoadFromFile(Opendialog1.FileName);

  FastSortStList(ZaladujListe);

  if SaveDialog1.Execute then
  ZaladujListe.SaveToFile(SaveDialog1.FileName);

  ZaladujListe.Free;

  Showmessage('GOTOWE !!!');
end;
1

Moja metoda na najszybsze zliczanie danych w delphi nie ma szybszej :-) W prostocie jest wszystko. Jeśli ktoś chce wyliczyć dane swoją metodą niech sprawdzi wpierw moją. Jest prosta. Co jedynie ma wadę musi wstawić items na początku, aby go pózniej usunąć. To wszystko.

procedure ...(Sender: TObject);
var
i, a : integer;
s1, s2 : string;
sl, sl1, ZaladujListe : TStringList;
begin
ZaladujListe := TStringList.Create;

if Opendialog1.Execute then
ZaladujListe.LoadFromFile(Opendialog1.FileName);

sl := TStringList.Create;
sl1 := TStringList.Create;

ZaladujListe.Insert(0,'');

for i := ZaladujListe.Count -1 downto 1 do
begin
 s1 := ZaladujListe[i];
 s2 := ZaladujListe[i-1];

 if s1 = s2 then inc(a);
 if s1 = s2  then sl.Text := inttostr(a+1)+' razy wystąpiło powtórzenie wartości statystycznej '+ZaladujListe[i];
 if s1 <> s2 then sl.Text := inttostr(a+1)+' razy wystąpiło powtórzenie wartości statystycznej '+ZaladujListe[i];

 if s1 <> s2 then a := 0;
 if s1 <> s2 then sl1.Add(sl[sl.Count-1]);

 if i = 1 then break;

 application.ProcessMessages;
end;

  ZaladujListe.Free;
  //ZaladujListe.Delete(0);

  Wartość posortowana := sl1.Text;

  sl.free;
  sl1.free;
end;
4

@Daniel M: źle się za ten temat zabierasz. Po pierwsze dlatego, że TStringList jest skomplikowanym kontenerem, który ma już wbudowaną metodę sortującą i masę innych rzeczy, które wykoślawią wyniki pomiarowe. A w szczególności, że nawet nigdzie nie wołasz BeginUpdate i EndUpdate, więc czas sortowania zależy nie tylko od algorytmu, ale też od szybkości renderowania danych na ekranie. Bo bez wywołania tych metod, każdorazowa zamiana itemów miejscami spowoduje przemalowanie kontrolki.

Jeśli użycie TStringList jest wymagane, to przed sortowaniem wywołaj BeginUpdate, a po nim EndUpdate, a do zamiany elementów miejscami skorzystaj z metody Exchange. Jeśli nie jest wymagane, to dane trzymaj w zwykłej macierzy, tę sobie sortuj jak chesz, a po wszystkim przepisz dane do kontrolki, aby były widoczne w oknie.


Daniel M napisał(a):

Po wielu probach udalo mi sie posortowac liste , jednak z malym ale , nie sortuje wszystkich elementow poprawnie , konczy na 4 znaku integera:

Sortuje poprawnie, według kodu który napisałeś. Jak wspomniał w komentarzu @Paweł Dmitruk, dane sortujesz alfabetycznie, za co odpowiada wykorzystanie operatora > — w Pascalu zachowanie tego operatora dla ciągów znaków jest zdefiniowane w standardzie i przeprowadza alfabetyczne ich porównanie. To co otrzymujesz jest zupełnie poprawne, choć na takie nie wygląda (krótsze ciągi mają wyższy priorytet).

Jeśli chcesz sortować liczby, a nie ciągi znaków je reprezentujące, to przed porównaniem musisz dokonać konwersji ciągów znaków na liczbę, np. za pomocą funkcji StrToInt lub metody ToInteger, jeśli taka jest dostępna. Czyli tak:

while (Position > 0) and (StrToInt(Items[Position]) > StrToInt(Value)) do

albo tak:

while (Position > 0) and (Items[Position].ToInteger() > Value.ToInteger()) do

1 użytkowników online, w tym zalogowanych: 0, gości: 1