Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Альтернатива TStringlist связный список строк

Delphi , Компоненты и Классы , Списки

Альтернатива TStringlist связный список строк

unit LinkList;
//******************************************************************************
// Данный модуль содержит объект для работы со связным списком (очередью)
// редакция 1.0.0.4
// дата последних исправлений 14/09/2006

// (c) KAN
//******************************************************************************

interface
uses KANsConverts;

//тип связный список
Type
  TLinkList = ^RLinkList; // ссылка на тип элемента очереди

  RLinkList = Record  //тип элемента очереди
    id  : integer;
    name: string;
    next: TLinkList;
  end;

  TQueue = Record   //указатель на начало и конец очереди
    Head  : TLinkList;
    Tail  : TLinkList;
  end;

//объект для работы с двухсвязным списком
Type CTLinkList = Class
  public
    Constructor Create;
    Destructor Destroyer;
    Procedure ClearAll;  //очищаем очередь
    Procedure AddItem (id : integer; name : string);        //добавлеяем элемент в конец очереди
    Function SearchItem (id : integer) : string;            //ищим элемент по id
    Function SearchItemByName (name : string) : integer;    //ищим элемент по имени
    Function GetAllItemID: TIntArray;                       //возвращает спискок ID`ов
  private
    Count     : integer;  //кол-во элементов в очереди
    Queue     : TQueue;   //начало и конец очереди
  published
    property ListLen: integer read Count; //кол-во элементов в очереди
    property GetQueue : TQueue read Queue; // сама очередь
  end;

implementation
//------------------------------------------------------------------------------
  Constructor CTLinkList.Create;
    //todo:добавить хэширование, при этом указывать кол-во элементов если (-1) то без хэширования...
    begin
      //создаём пустой связный списк - очередь
      Queue.Head:=nil;
      Queue.Tail:=nil;
      Count:=0;
    end;
//------------------------------------------------------------------------------
  Procedure CTLinkList.ClearAll; //очищаем очередь
    Var ListItems : TLinkList;
    begin
     if Queue.Head <> nil then
     begin
      ListItems:=Queue.Head;  // смотрим список с головы
      repeat
        if ListItems^.next <> nil then Queue.Head:=ListItems^.next; // узнаем следующий элемент
        Dispose(ListItems);       // удадяем голову
        ListItems:=Queue.Head;
        dec(Count);    // уменьшаем счетчик
      until Count <= 0; //Queue.Head = nil;   // повторяем пока ничего не останится
     end; //if

     Queue.Head:=nil;
     Queue.Tail:=nil;
     Count:=0;
    end;
//------------------------------------------------------------------------------
  Destructor CTLinkList.Destroyer;
    begin
      ClearAll;
    end;
//------------------------------------------------------------------------------
  Procedure CTLinkList.AddItem (id : integer; name : string);  //добавлеяем элемент в конец очереди
    Var ListItems : TLinkList;
    begin
      new(ListItems);         //отводим памяти кусочек
      ListItems^.id:=id;      //заполняем все поля
      ListItems^.name:=name;
      ListItems^.next:=nil;   //следующего элемента пока нет

      if Queue.Head = nil     //если очередь былла пустой,
        then Queue.Head := ListItems //то новый элемент будет головой
        else Queue.Tail^.next := ListItems;//иначе хвостом

      inc(Count);            //увеличивам счетчик кол-во элементов в очереди
      Queue.Tail:= ListItems; // приписываем элемент в хвост
    end;
//------------------------------------------------------------------------------
  Function CTLinkList.SearchItem (id : integer) : string;  //ищим элемент по id
    Var ListItems : TLinkList;
        Resultat  : String;
        NeedExit  : Boolean;
    begin
     Resultat:='';              //в случаи чего вернем пустую строку
     if Queue.Head <> nil then  // проверяем очередь на пустоту
     try
      ListItems:=Queue.Head;  // смотрим список с головы
      NeedExit:=False;        //снимаем признак выхода
      repeat
        begin
          if ListItems^.id=id then    //а если наши нужный id...
            begin
            Resultat:= ListItems^.name;  // запоминаем найденый результат
            NeedExit:=True;  //устанавливаем признак выхода
            end;
          ListItems:=ListItems^.next; // узнаем следующий элемент
        end;
      until ((ListItems = nil) or (NeedExit));   // повторяем пока ничего не останится или нет признака выхода
     finally
      SearchItem := Resultat;
     end; //finally
    end;//Function
//------------------------------------------------------------------------------
  Function CTLinkList.SearchItemByName (name : string) : integer;      //ищим элемент по имени
    Var ListItems : TLinkList;
        Resultat  : integer;
        NeedExit  : Boolean;
    begin
     Resultat:=-1;              //в случаи чего вернем пустую строку
     if Queue.Head <> nil then  // проверяем очередь на пустоту
     try
      ListItems:=Queue.Head;  // смотрим список с головы
      NeedExit:=False;        //снимаем признак выхода
      repeat
        begin
          if ListItems^.name=name then    //а если наши нужный name...
            begin
            Resultat:= ListItems^.id;  // запоминаем найденый результат
            NeedExit:=True;  //устанавливаем признак выхода
            end;
          ListItems:=ListItems^.next; // узнаем следующий элемент
        end;
      until ((ListItems = nil) or (NeedExit));   // повторяем пока ничего не останится или нет признака выхода
     finally
      SearchItemByName := Resultat;
     end; //finally
    end;//Function
//------------------------------------------------------------------------------
  Function CTLinkList.GetAllItemID: TIntArray;      //возвращает спискок ID`ов
    Var ListItems : TLinkList;
        Resultat  : integer;
        lResultArray: TIntArray;
    begin
     Resultat:=0;
     SetLength(lResultArray, Count);

     if Queue.Head <> nil then // проверяем очередь на пустоту
     try

      ListItems:=Queue.Head;  // смотрим список с головы
      repeat
        begin
          lResultArray[Resultat]:= ListItems^.id;  // запоминаем
          inc(Resultat);
          ListItems:=ListItems^.next; // узнаем следующий элемент
        end;
      until (ListItems = nil);   // повторяем пока ничего не останится или нет признака выхода

     finally
      GetAllItemID := lResultArray;
     end; //finally

    end;//Function
//------------------------------------------------------------------------------
end.

 

Привет! Я перевёл текст на русский язык:

В этом модуле Delphi реализуется связанный список данных, конкретно очередь. Модуль определяет два рекорда: RLinkList и TQueue. Тип RLinkList представляет собой отдельный элемент в очереди, который имеет три поля: id, name и next. Тип TQueue представляет собой очередь сама, с двумя полями: Head и Tail.

Модуль также определяет класс CTLinkList, который предоставляет методы для манипуляции очередью. Эти методы включают:

  • ClearAll: Очищает очередь, освобождая все элементы в ней.
  • AddItem: Добавляет элемент в конец очереди.
  • SearchItem: Ищет элемент с конкретным ID и возвращает его имя если найден.
  • SearchItemByName: Ищет элемент с конкретным именем и возвращает его ID если найден.
  • GetAllItemID: Возвращает массив IDs всех элементов в очереди.

Имплементация этих методов проста, используя рекурсию или циклы для прохождения связанного списка. Например, ClearAll проходит очередь от головы до хвоста, освобождая каждый элемент и обновляя счетчик элементов в очереди. AddItem выделяет новый элемент и добавляет его в конец очереди.

Некоторые предложения по улучшению:

  1. Обработка ошибок: Имплементация не обрабатывает ошибки должным образом. Например, если попытаться найти ID, который не существует в очереди, метод вернет пустую строку или -1. Лучше было бы выбросить исключение вместо этого.
  2. Управление памятью: Имплементация использует new и Dispose для управления памятью, что может привести к утечкам памяти если не использоваться правильно. Рекомендуется использовать умный указатель или сборщик мусора для упрощения управления памятью.
  3. Организация кода: Код организован в отдельные методы для каждой операции, что делает его легко понятным, но может сделать класс труднее использовать. Рекомендуется организовать методы в категории (например, "вставка", "поиск" и т.д.) для улучшения удобства использования.
  4. Безопасность типов: Имплементация использует кастинг типа (TLinkList to RLinkList), что может привести к ошибкам на время выполнения если не сделано правильно. Рекомендуется использовать интерфейсы или абстрактные классы для определения общего интерфейса для элементов связанного списка.

В этом альтернативном решении используется генерируемый тип TList<T> вместо реализации связанного списка вручную:

unit LinkList;
interface
uses System.Generics.Collections;
type TLinkList = class(TList<RLinkList>)
private
  function GetItem(id: integer): RLinkList;
public
  constructor Create;
  destructor Destroy; override;
  procedure ClearAll;
  procedure AddItem(id: integer; name: string);
  function SearchItem(id: integer): string;
  function SearchItemByName(name: string): integer;
  function GetAllItemID: TArray<Integer>;
end;
implementation
constructor TLinkList.Create;
begin
  inherited Create;
end;
destructor TLinkList.Destroy;
begin
  ClearAll;
  inherited Destroy;
end;
procedure TLinkList.ClearAll;
var i: integer;
begin
  for var item in Items do
    Dispose(item);
  SetLength(Items, 0);
  Count := 0;
end;
procedure TLinkList.AddItem(id: integer; name: string);
var item: RLinkList;
begin
  new(item);
  item.id := id;
  item.name := name;
  Add(item);
end;
function TLinkList.GetItem(id: integer): RLinkList;
var i: integer;
begin
  for i := 0 to Count - 1 do
    if Items[i].id = id then
      Result := Items[i]
      exit;
  Result := nil;
end;
function TLinkList.SearchItem(id: integer): string;
begin
  for var item in Items do
    if item.id = id then
      Result := item.name
      exit;
  Result := '';
end;
function TLinkList.SearchItemByName(name: string): integer;
var i: integer;
begin
  for i := 0 to Count - 1 do
    if Items[i].name = name then
      Result := Items[i].id
      exit;
  Result := -1;
end;
function TLinkList.GetAllItemID: TArray<Integer>;
var i: integer;
  resultArray: TArray<Integer>;
begin
  SetLength(resultArray, Count);
  for i := 0 to Count - 1 do
    resultArray[i] := Items[i].id;
  Result := resultArray;
end;
end.

В этом решении используется класс TList из модуля System.Generics.Collections и определяется custom class RLinkList, которая представляет собой отдельный элемент в связанном списке. Класс TLinkList предоставляет методы для манипуляции связанным списком, такими как добавление и удаление элементов, поиск конкретных элементов и получение всех IDs.

Обратите внимание, что это решение использует оператор new для выделения памяти для каждого элемента, что может привести к утечкам памяти если не использоваться правильно. Рекомендуется использовать умный указатель или сборщик мусора для упрощения управления памятью.

Альтернативой TStringlist является связный список строк, реализованный в виде объекта CTLinkList.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Списки ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-10-08 18:03:55/0.0073938369750977/0