双链表实现

时间:2013-03-07 17:51:04

标签: c++ doubly-linked-list

我正在编写一个双链表项目的语法问题,我是出于教育目的而编写的。我在头文件中创建了一个结构体,我的主程序似乎没问题,但在.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)

我应该能够在列表的开头,中间和结尾插入。根据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

3 个答案:

答案 0 :(得分:0)

尝试更改此内容:

int AddItem(Record entry);

对此:

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

如果insertion_pointNULL,您可以假设Record是新列表的开头。

现在您有足够的信息来设置NextPrevious指针,并返回新创建的节点。

答案 1 :(得分: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);
}

答案 2 :(得分: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. 新节点附加 列表
  4. 我已经标记了动词名词,你已经可以看到你的函数中缺少一个名词。您要求AddItem将项目添加到列表中......但是您没有给它一个列表来处理。

    明确写出你的期望也很有用:

      在调用AddItem之前
      • 需要一个列表才能使用
      • 我们没有列表容器类,只有记录,所以我们必须传递Record
      • 假设我们想在传递的Record之后添加我们的新项目
    1. 调用AddItem
      • 无论我们传入的是哪个Record,其Next都应指向新节点
      • 新节点的Previous应指向传入的节点
      • 等。等(这些是标准的双向链表插入行为)
    2. 稍后请注意:我们尚未描述如何存储空列表
      • 如果它是循环列表,则空列表将是Record,其NextPrevious成员指向自己
      • 如果它是线性的,它们可能都是NULL而不是
      • 它可能只是一个NULL指针,但是将第一个节点添加到空列表需要更多的努力
    3. 所以,让我们说可能有效的最小函数是:

      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 ++代码需要更多的更改。


      现在,鉴于此,你可以:

      • 实现这三个功能? (CreateRecordCopyRecordValues已在您当前的代码中处理)
      • 为您的其他操作编写等效的伪代码,并自行翻译?