Реализация двойного связанного списка

У меня проблемы с синтаксисом в программе с двойным списком, которую я пишу для образовательных целей. Я создал структуру в своем заголовочном файле, и моя основная программа, кажется, в порядке, но реализация моих функций в файле .cpp доставляет мне огромные трудности. У меня проблемы с распознаванием трех случаев для вставки записи в список. В частности, меня смущает выделение памяти, инициализация начала и конца списка и порядок операторов, а также передача копии записи, которая будет добавлена ​​в мой список.

Мой заголовочный файл выглядит следующим образом:

struct rec
{
char * id;
char firstname[15];
char lastname[15];
struct rec* prev;
struct rec* next;
};int AddItem ( rec r );
int DeleteItem ( char* delid );
void PrintList ( int order );

Мой файл .cpp, в котором заключается трудность, выглядит следующим образом:

#include <iostream>
#include "list.h"#include <string.h>
using namespace std;

// These pointers refer to the head and tail of the list.
rec* first = NULL;
rec* last = NULL;

int AddItem( Rec r )
{

rec* newRecEntry;
rec* current = NULL;
rec* previous = NULL;

// Check for duplicate id
current = first;
while (current)
{
if( strcmp(current -> id, r.id) == 0)
{
return 0;
}
else
// Create a new node
{
newRecEntry = new Rec;
newRecEntry->id = new char[strlen(r.id)+1];
strcpy(newRecEntry->id, r.id);
strcpy(newRecEntry->firstname,r.firstname);
strcpy(newRecEntry->lastname,r.lastname);
newRecEntry->next = NULL;
newRecEntry->prev = NULL;
}
// Find the appropriate position for the node and insert accordingly
// Check to see if the list is empty
if (first == NULL)
{
first = newRecEntry;
last = newRecEntry;
}
else if ( r.lastname>last.lastname)
{else
{

return 0;
}

/*int DeleteItem(char* ID)

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

lists.cpp

#include <iostream>
#include "list.h"#include <string.h>
using namespace std;

// These pointers refer to the head and tail of the list.
rec* first = NULL;
rec* last = NULL;

int AddItem( Rec r )
{

rec* newRecEntry;
rec* current = NULL;
rec* previous = NULL;

// Check for duplicate id
current = first;
while (current)
{
if( strcmp(current -> id, r.id) == 0)
{
return 0;
}
else
// Create a new node
{
newRecEntry = new Rec;
newRecEntry->id = new char[strlen(r.id)+1];
strcpy(newRecEntry->id, r.id);
strcpy(newRecEntry->firstname,r.firstname);
strcpy(newRecEntry->lastname,r.lastname);
newRecEntry->next = NULL;
newRecEntry->prev = NULL;
}
// Find the appropriate position for the node and insert accordingly
// Check to see if the list is empty
if (first == NULL)
{
first = newRecEntry;
last = newRecEntry;
}
else if ( r.lastname>last.lastname)
{else
{

return 0;
}

/*int DeleteItem(char* ID)
{
rec
}
*//*void printList(int order)
{
loop
{
cout << ptr -> Id << " ";
cout << ptr -> firstname << " ";
cout << ptr -> lastname << " ";
cout << ptr -> prev << " ";  // address of previous
cout <<  ptr << " ";   // address of item
cout << ptr -> next << " ";  //  address of next item
}

}

Основное заключается в следующем:

#include <iostream>
#include "list.h"#include <string.h>  // <string>

using namespace std;

void main (void)
{
int choice, printorder;
char idbuffer[100];
rec r;do
{
cout << "Enter your choice 1 Add, 2 Delete, 3 Print, 0 quit "<<endl;
cin >> choice;

switch ( choice )
{
case 1:  //AddItem
cout << "\nEnter ID ";
cin >> idbuffer;

r.id = idbuffer;
cout << "\nFirst Name ";
cin >> r.firstname;
cout << "\nLast Name ";
cin >>  r.lastname;
if ( AddItem ( r ) )
{
cout << "\nSuccess!\n";
}
else
{
cout << "\nItem failed to be added\n";
}

break;
case 2:  //Delete
cout << "\nEnter id :";
cin >> idbuffer;
if ( DeleteItem ( idbuffer ) )
{
cout << "\nDelete OK\n";
}
else
{
cout << "\nDelete Failed for " << idbuffer;
}
break;
case 3: // Print
cout << "Enter order 0 - Ascending, 1 - Descending\n";
cin >> printorder;
PrintList (printorder);
break;
case 0:  // quit
break;default: // bad choice
break;
} // end switch

}
while ( choice != 0 );// end do while
}  // end main

0

Решение

Это может показаться не так, но даже эта функция

int AddItem(Record entry)
{
Record* newRecordPointer;
newRecordPointer=new Record;
strcpy(newRecordPointer->firstName,entry.firstName);
strcpy(newRecordPointer->lastName,entry.lastName);
newRecordPointer->ID=new char[strlen(entry.ID)+1];
strcpy(newRecordPointer->ID, entry.ID);
return 0;
}

пытается сделать слишком много вещей.

Давайте напишем псевдокодовое описание добавления элемента в список:

  1. Создайте новый узел
  2. населять новый узел с предоставленные значения
  3. прикреплять новый узел в список

Я отметил глаголы а также существительные участие, и вы уже можете увидеть один из существительные отсутствует в вашей функции. Ты спрашиваешь AddItem добавить элемент в список … но вы не даете ему список для работы.

Также полезно четко изложить ваши ожидания:

  1. до AddItem называется:
    • ему нужен список для работы
    • у нас нет класса контейнера списка, только записи, поэтому мы должны передать Record
    • скажем, мы хотим добавить наш новый элемент после Record прошло в
  2. после AddItem называется:
    • без разницы Record мы прошли, его Next должен указывать на новый узел
    • новый узел Previous должен указывать на узел, переданный в
    • и т. д. и т. д. (это стандартное поведение вставки списков с двойной связью)
  3. примечание к позже: мы не описали, как мы храним пустой список
    • если это круговой список, пустой список будет Record чья Next а также Previous Члены указывают на себя
    • если он линейный, они оба могут быть NULL вместо
    • это может быть просто указатель NULL, но для добавления первого узла в пустой список требуется больше усилий

Итак, скажем, минимальная функция, которая могла бы работать:

void AddItem(Record *insert_after, Record value)
{
Record *new_node = CreateRecord();
CopyRecordValues(new_node, &value);
AttachAfter(insert_after, new_node);
}

Обратите внимание, что если бы мы писали настоящий C ++, первые две строки могли бы просто использовать конструктор копирования Record *new_node = new Record(value), но потребуется больше изменений, чтобы достичь идиоматического кода C ++, с которого мы начали.


Теперь, учитывая это, вы можете:

  • реализовать эти три функции? (CreateRecord а также CopyRecordValues уже обработаны в вашем текущем коде)
  • написать эквивалентный псевдокод для других ваших операций и перевести его самостоятельно?
0

Другие решения

Попробуйте изменить это:

int AddItem(Record entry);

К этому:

Record* AddItem(Record entry, Record *insertion_point = NULL );

Если insertion_point является NULL, вы можете предположить, что Record это начало нового списка.

Теперь у вас достаточно информации для установки Next а также Previous указатели и вернуть вновь созданный узел.

0

Прежде всего вы должны определить первый и конечный элементы.

Возможность

  • Предмет с Previous назначен на NULL это первое.
  • Предмет с Next назначен на NULL Я отправляю.

Для простоты я удалил некоторые поля Record, это не самое лучшее, будьте осторожны, вы должны сделать много ошибок и позаботиться об исключениях:

struct Record
{
int id;
Record* Next;
Record* Previous;
};

Record *CreateList(int id)
{
Record *rec = new Record;
rec->id = id;
rec->Next = NULL;
rec->Previous = NULL;
return rec;
}

void AddItemAfter(Record *item, int id)
{
if (!item)
return;

Record* newRecordPointer = new Record;
newRecordPointer->id = id;
newRecordPointer->Next = NULL;
newRecordPointer->Previous = NULL;

newRecordPointer->Next = item->Next;
item->Next = newRecordPointer;
newRecordPointer->Previous = item;
}

void ShowList(Record *list)
{
Record *ptr = list;
while (ptr)
{
cout << ptr->id << endl;
ptr = ptr->Next;
}
}

int main()
{
Record *list = CreateList(1);

AddItemAfter(list, 2);
AddItemAfter(list, 3);

ShowList(list);
}
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector