Home > CLR, Кодинг, Проги, С++ > CLR. Работа с двусвязными списками + listBox

CLR. Работа с двусвязными списками + listBox

Программа должна уметь записывать элементы в конец списка, удалять по значению и вставлять “до” и “после”. Изначальный список – выводится в listBox1, а измененный, после нажатия на кнопку “Обновить” – в listBox2.

Форма проекта

Так выглядит форма проекта. Если вам чем-то не нравятся “точки” с выбором метода вставки, то можете вместо них вделать кнопки с отдельными обработчиками.

Итак, приступим к воплощению. Перед программированием кнопок, необходимо задать структуру элемента. Посколько список двусвязный, то структура будет такой:

struct list {int inf; list *prev; list *next;};

Где inf – переменная с данными, *prev – указатель на предыдущий элемент списка, *next – на следующий. Самое важное то, что описание структуры необходимо поместить вне класса формы, т.е. перед ним.

Далее, уже в классе, опишем переменые

list *_prev, *_now, *_next, *_first;

Первые три переменные используются только при записи элемента в конец списка. А _first – как следует из названия, переменная, в которой хранится адрес первого элемента списка. Далее, чтобы облегчить код кнопки добавления в конец, первый элемент будем создавать в конструкторе. Там же запишем его адрес в _first.

_prev = NULL;
_now = (list*)calloc(1, sizeof(list));
_first = _now;

Вот так. Теперь, когда все приготовления сделаны, приступим к написаню обработчиков. Первая кнопка будет добавлять в конец списка элемент.

if (textBox1->Text != "")
{
_now->inf = Convert::ToInt32(textBox1->Text);
_now->prev = _prev;
_next = (list*)calloc(1, sizeof(list));
_now->next = _next;
_prev = _now;
_now = _next;
listBox1->Items->Add(textBox1->Text);
}
textBox1->Text = "";

Код бредовый. Если напишете лучше, приылайте – с радостью обновлю здесь :-).

Поскольку в ListBox2 должен выводиться измененный список, создадим кнопку “Обновить”. Что будет происходить в обработчике? В нем будет в цикле проходиться список и значение поля inf будет записываться в listBox.

list *temp;
temp = _first;
listBox2->Items->Clear();
while(temp->next != NULL)
{
listBox2->Items->Add(temp->inf);
temp = temp->next;
}

Здесь temp – переменная, из которой будет читаться поле inf.

Следующая кнопка – удаление по значению. В ней будет происходить проход цикла и значение поля inf каждого поля будет сравниваться со значением в текстовом поле под кнопкой. Теперь о том, как будут изменяться адреса. Пусть A[i]    – элемент, который необходимо удалить. На него ссылается элемент A[i-1] как next и элемент A[i+1] как prev. Чтобы исключить элемент из списка, необходимо в элементе A[i-1] изменить поле next так, чтобы он указывал на A[i+1], а в A[i+1] изменить поле prev так, чтобы в нем хранился адрес элемента A[i-1].

list *temp1, *temp2;
temp1 = _first;
do
{
if (temp1->inf == Convert::ToInt32(textBox2->Text))
{
temp2=temp1->prev;
if (temp1->prev == NULL) _first = temp1->next; else
{
temp2->next = temp1->next;
temp1->next->prev = temp2;
}
}
temp1 = temp1->next;
}
while (temp1->next != NULL);

Внутренняя проверка служит для того, чтобы предотвратить потерю адреса  начала списка, в случае его удаления. Кстати, если Вы захотите удалить элемент из списка, в котором не будет элементов или textBox3 окажется пустым, то будет ошибка исполнения. Возможность избавиться от этих исключений, я предоставляю Вам.

Последняя кнопка – “Добавить”. Поскольку есть два вида вставки – “до” и “после”, для этого есть 2 RadioButton’а (before и after соответсвенно).

list *temp, *temp2;
temp = _first; int flag = 0;
while((temp->next != NULL))
{
if ((before->Checked == true) && (temp->inf == Convert::ToInt32(textBox3->Text)))
{
temp2 = (list*)calloc(1,sizeof(list));
temp2->inf = Convert::ToInt32(textBox4->Text);
temp->prev->next = temp2;
temp2->prev = temp->prev;
temp2->next = temp;
temp->prev = temp2;
}
if ((after->Checked == true) && (temp->inf == Convert::ToInt32(textBox3->Text)))
{
temp2 = (list*)calloc(1,sizeof(list));
temp2->inf = Convert::ToInt32(textBox4->Text);
temp2->next = temp->next;
temp->next->prev = temp2;
temp2->prev = temp;
temp->next = temp2;
}
temp = temp->next;
}

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

Удачи 😉

Advertisements
Categories: CLR, Кодинг, Проги, С++
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: