Консультация № 185661
25.03.2012, 14:11
62.88 руб.
0 14 1
Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:
Нужно написать программу, реализующую комбинированный способ организации таблицы идентификаторов. Идентификаторы берутся из файла.
Для организации таблицы используется простейшая хэш-функция "Сумма кодов первой и второй букв",
а при возникновении коллизий используется бинарное дерево.


Вот программа https://rfpro.ru/upload/7776
Большая часть задания в ней сделана,но в ней нужно еще создать второй stringgrid для поиска коллизий и выводить все коллизии в stringgrid, а также
сообщать среднее число коллизий и среднее количество сравнений, выполненных для поиска идентификатора.
Помогите пожалуйста мне это реализовать, т.к. мне совсем непонятно как это сделать.

Немного теории:
Ситуация, когда двум или более идентификаторам соответствует одно и то же значение функции, называется коллизией.

Обсуждение

Неизвестный
27.03.2012, 23:27
общий
Я постараюсь посмотреть в ближайшее время, если никто другой не обратит внимания.
давно
Профессор
230118
3054
29.03.2012, 11:43
общий
А реализовано там двоичное дерево?
давно
Профессор
230118
3054
29.03.2012, 20:38
общий
А что значит вывести коллизию?
Неизвестный
01.04.2012, 17:51
общий
01.04.2012, 18:10
Да, двоичное дерево там реализовано.
Вывести кллизию можно так:
По функции ord мы получили код идентификатора, это уже реализоавно. Так вот если например у идентификаторов двух это значение одинаково, то выводим в таблицу stringgrid название этого идентификатора.
Неизвестный
01.04.2012, 18:11
общий
В двоичном дереве считается только количество коллизий и сравнений.
давно
Профессионал
304622
583
02.04.2012, 14:13
общий
это ответ
Здравствуйте, novij2011!

Можно добавить вот такую рекурсивную процедуру
Код:

procedure TForm1.Output(IDIndex:integer);
begin

if IDTable[IDIndex].Left <> 0 then Output(IDTable[IDIndex].Left);
sg2.Cols[0].Add(IDTable[IDIndex].Name);
if IDTable[IDIndex].Right <> 0 then Output(IDTable[IDIndex].Right);
end;


Плюс соответствующие исправления в Button1Click и определении TForm1
Итого, вот как выглядит Unit1.pas

[code h=200]
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, StdCtrls, ID, ExtCtrls;

type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
ESearch: TEdit;
sg: TStringGrid;
Edit1: TEdit;
Label1: TLabel;
sg2: TStringGrid;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Output(IDIndex:integer);


private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
IDTable: array of TID;
HashTable: array of integer;
CollisionQuantity: integer;
CompareQuantity: integer;

implementation

{$R *.dfm}

procedure MakeTreeNode(HashIndex:integer; IDIndex:integer);
begin
if IDTable[HashIndex].Name<IDTable[IDIndex].Name then
begin
if IDTable[HashIndex].Right = 0 then
IDTable[HashIndex].Right := IDIndex
else
MakeTreeNode(IDTable[HashIndex].Right,IDIndex);
end;
if IDTable[HashIndex].Name>IDTable[IDIndex].Name then
begin
if IDTable[HashIndex].Left = 0 then
IDTable[HashIndex].Left := IDIndex
else
MakeTreeNode(IDTable[HashIndex].Left,IDIndex);
end;
end;
procedure HashTreeBuild(N:integer);
var
i:integer;
begin
for i:=1 to N do
begin
if HashTable[IDTable[i].Hash]=0 then
HashTable[IDTable[i].Hash] := i
else
begin
Inc(CollisionQuantity);
MakeTreeNode(HashTable[IDTable[i].Hash],i);
end;
end;
end;
function GetIDIndex(SearchID:TID;HashIndex:integer):integer;
begin
if IDTable[HashIndex].Name=SearchID.Name then
begin
Inc(CompareQuantity);
Result:=HashIndex;
exit;
end;
if IDTable[HashIndex].Name<SearchID.Name then
begin
Inc(CompareQuantity);
if IDTable[HashIndex].Right<>0 then
begin
result:= GetIDIndex(SearchID,IDTable[HashIndex].Right);
exit;
end
else
begin
result := 0;
exit;
end;
end
else
begin
inc(CompareQuantity);
if IDTable[HashIndex].Left=1 then
begin
result := GetIDIndex(SearchID,IDTable[HashIndex].Left);

exit;
end
else
begin
result := 0;
exit;
end;
end
end;

procedure TForm1.Output(IDIndex:integer);
begin

if IDTable[IDIndex].Left <> 0 then Output(IDTable[IDIndex].Left);
sg2.Cols[0].Add(IDTable[IDIndex].Name);
if IDTable[IDIndex].Right <> 0 then Output(IDTable[IDIndex].Right);
end;

procedure TForm1.Button1Click(Sender: TObject);

var
d1,d3:TDateTime;
Hash:integer;
SearchID:TID;
SearchString : string;
HashIndex:integer;
IDIndex:integer;
begin
d1:=Now();
SearchString := eSearch.Text;
SearchID := TID.Create;
SearchID.Name := SearchString;
Hash := SearchID.Hash;
HashIndex := HashTable[Hash];
CompareQuantity := 0;

IDIndex := GetIDIndex(SearchID,HashIndex);

memo1.Clear;

if IDIndex<>0 then
begin





memo1.Lines.Add('Идентификатор найден, его индекс = :'+IntToStr(IDIndex));
memo1.Lines.Add('Сравнений:'+IntToStr(CompareQuantity));
memo1.Lines.Add('Коллизий:'+IntToStr(CollisionQuantity));

end

else
begin
memo1.Lines.Add('Идентификатор не найден');
memo1.Lines.Add('Сравнений:'+IntToStr(CompareQuantity));
memo1.Lines.Add('Коллизий:'+IntToStr(CollisionQuantity));

end ;
d3:=Now();

edit1.Text:=formatdatetime('hh:mm:ss:ms',(d1-d3));
if CollisionQuantity >=1 then begin
sg2.cells[0,0]:='№ ID. c коллизией';
sg2.cells[1,0]:=(IntToStr(IDIndex));
Output(IDIndex);
end;
end;


procedure TForm1.FormCreate(Sender: TObject);
var
N:integer;
i:integer;
begin
memo1.Lines.LoadFromFile('Input.txt');
N := memo1.Lines.Count;

SetLength(IDTable,N+1);
for i:=0 to N do
begin
IDTable[i] := TID.Create;
IDTable[i].Name := memo1.Lines.Strings[i-1];
end;

SetLength(HashTable,256);
for i:=0 to 255 do HashTable[i] := 0;

HashTreeBuild(N);

sg.Rows[0].Add('индекс');
sg.Rows[0].Add('имя идент.');
sg.Rows[0].Add('хэш-функция');
sg.Rows[0].Add('поле Left');
sg.Rows[0].Add('поле Right');

for i := 1 to N do
begin
sg.Rows[i].Add(IntToStr(i));
sg.Rows[i].Add(IDTable[i].Name);
sg.Rows[i].Add(IntToStr(IDTable[i].Hash));
sg.Rows[i].Add(IntToStr(IDTable[i].Left));
sg.Rows[i].Add(IntToStr(IDTable[i].Right));
sg.RowCount := sg.RowCount+1;
end;
memo1.Clear;
memo1.Lines.Add('Введите имя идентификатора');
memo1.Lines.Add('Коллизий:'+IntToStr(CollisionQuantity));

end;

end.
[/code]
давно
Профессионал
304622
583
02.04.2012, 14:14
общий
Насчёт "среднее число коллизий и среднее количество сравнений" -- я не понял, что имеется в виду.
Неизвестный
02.04.2012, 16:28
общий
Цитата: Сергей Бендер
Насчёт "среднее число коллизий и среднее количество сравнений" -- я не понял, что имеется в виду.

Да, что то это как то странно. Если сумму чисел коллизий например сложить и в последующем поделить полученную сумму на количество просуммированных чисел, то все равно будет один и тот же результат
Неизвестный
02.04.2012, 16:42
общий
02.04.2012, 18:15
Адресаты:
А что за такая странная строчка?
Код:
qwe(IDIndex);

на нее компилятор ругается, да и в delphi я не видел ни разу такой функции. Вроде и без этой строчки работает.

Спасибо огромное за помощь.

p.s.
кнопочка "спасибо" куда то делась.
давно
Профессионал
304622
583
02.04.2012, 19:35
общий
Ёлки-палки! Извините, пожалуйста -- я второпях доделывал. У меня функция сначала называлась "qwe". Потом переименовал в Output, а вызов функции поменятьзабыл. У вас не должно работать без этой строчки. Кроме того, кодировка русского текста сбилась.

Я сейчас исправлю.

кнопочка "спасибо" куда то делась


Это потому что срок действия кончился -- я в последние минуты выкладывал ответ.
давно
Профессионал
304622
583
02.04.2012, 19:43
общий
Готово.

А "qwe" -- это три подряд клавиши вверху слева. Имя для тех случаев, когда ещё нет времени или нужды придумывать имена.
Неизвестный
02.04.2012, 20:24
общий
02.04.2012, 22:25
Адресаты:
А, вооооот как она должна работать. А я сам ее чуть чуть доработал.
В кнопке 1 написал
Код:
if CollisionQuantity >=1 then
begin
sg2.cells[0,0]:='ID. c коллизией';
sg2.cells[1,0]:=(IntToStr(IDIndex));
sg2.cells[2,0]:=(IDTable[IDIndex].Name);
i:=2;


и в прцедуре output,
Код:
sg2.Cols[2].Add(Inttostr(IDTable[IDIndex].Name));


так как без этой строчки
Код:
output(IDIndex); 
имя(название) идентификатора не выводилось

p.s. а на счет кракозябр, так я догадался, что такм должно быть написано.

Что за такое, всегда иду какими то сложными путями, а вот переимновать qwe в output как то в голову не пришло.

еще раз спасибо!!!
давно
Профессионал
304622
583
03.04.2012, 11:38
общий
Кстати, обратите внимание, что по сравнению с вашим исходным текстом сделано два исправления:
1) Было "CollisionQuantity >=2". Из-за этого в вашем исходном варианте даже при вводе "repeat" ничего не срабатывало.
2) Было "sg2.cells[0,1]:=..." и "sg2.cells[1,1]:=...". Из-за после заголовки выводились во вторую строку.
Неизвестный
03.04.2012, 21:12
общий
Адресаты:
Да, действительно, спасибо.
Форма ответа