2013-10-21 88 views
1

双向链表实现我现在自学C++和我试图实现在C++中使用指针是部分完成一个双向链表。我知道,代码当前无法处理悬挂节点或输出错误,我将在下面实现这两个错误。但是,代码至少应该能够构造一个列表对象并向其添加元素。目前,我在尝试调用列表的构造函数时遇到错误,该错误表示我正在请求从LinkedList *转换为非标量类型LinkedList。为什么我的列表被声明为一个指针?任何帮助将不胜感激,谢谢!与指针C++

LinkedList.h 
#ifndef LINKEDLIST_H 
#define LINKEDLIST_H 

struct dataElement { 
    int key; 
    int id; 
}; 

struct Node 
{ 
    dataElement data; 
    Node* next; 
    Node* prev; 
}; 


class LinkedList 
{ 
public: 
    /** Default constructor */ 
    LinkedList(); 
    /** Default destructor */ 
    virtual ~LinkedList(); 
    void addAtFront(int newElement); 
    void addAtBack(int newElement); 
    int removeTop(); 
    int removeBottom(); 
    int getTop(); 
    int getBottom(); 
    int findKey(int keyToFind); 
protected: 
private: 
    Node* head; 
    Node* tail; 
    int size; 
}; 

#endif // LINKEDLIST_H 


LinkedList.cpp 
#include "LinkedList.h" 
#include <iostream> 
#include <stdlib.h> 


LinkedList::LinkedList() 
{ 
size = 0; 
} 

LinkedList::~LinkedList() 
{ 
//dtor 
} 

void LinkedList::addAtFront(int newElement) 
{ 
if (size == 0) 
{ 
    Node temp; 
    temp.data.id = newElement; 
    temp.data.key = 0; 
    head = &temp; 
    tail = &temp; 
    ++size; 
} 
else 
{ 
    Node temp; 
    temp.data.id = newElement; 
    temp.data.key = size; 
    temp.next = head; 
    head->prev = &temp; 
    head = &temp; 
    ++size; 
} 
} 

void LinkedList::addAtBack(int newElement) 
{ 
if (size == 0) 
{ 
    Node temp; 
    temp.data.id = newElement; 
    temp.data.key = 0; 
    head = &temp; 
    tail = &temp; 
    ++size; 
} 
else 
{ 
    Node temp; 
    temp.data.id = newElement; 
    temp.data.key = 0; 
    tail->next = &temp; 
    temp.prev = tail; 
    tail = &temp; 
    ++size; 
} 
} 

LinkedListTest.cpp 
#include "LinkedListTest.h" 
#include "LinkedList.h" 

int main() 
{ 
LinkedList list = new LinkedList(); 
list.addAtFront(0); 
} 
+0

,你需要使用' - 的>'',而不是向.'到成员函数。使主'list-> addAtFront(0)的最后一行;'看看会发生什么。 – Charlie

回答

4

的错误意味着什么地方你已经在LinkedList列表中声明不为指针,以这您分配new LinkedList(),其类型为LinkedList*(而不是LinkedList)。它应该是:

LinkedList* list = new LinkedList(); // I declare a pointer to a list 
list->addAtFront(0); // I call a method on a pointer to an object 

LinkedList list; 
list.addAtFront(0); 

它们是在两个不同的存储分配,这是非常重要的,请继续阅读两种不同类型。

我看更重要的是什么,当你使用动态分配的内存,你应该采取案件的居然就应该坚持声明它们的范围堆对象分配。

更具体地说,本:

{ 
    Node temp; 
    .. 
    head = &temp; 
    .. 
} 

因为temp被声明为堆栈自动存储,这意味着一旦你得到它的地址,并将其分配给headtail或什么的,该地址这将导致问题一旦范围退出,将不再有效。您应该分配它堆:

Node temp = new Node(value, id); 
head = temp; 
tail = temp; 
++size; 

记住,这需要你自己从堆中清理内存时不再需要的Node

+0

这意味着我需要声明addElement方法之外的节点是否正确?如果是这样,我是否需要像数组一样对待它,并声明10个初始节点,并在必要时扩展列表?我想我可以使用add元素方法相应地移动前端和尾端指针。这似乎有点低效。 –

+0

不,不正确。你在'addElement'内声明它们,但是通过'new'运算符声明它们。这将为堆中的列表元素分配内存,而不是在堆栈中本地分配内存。在这里读一读:http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap – Jack

1

new返回一个指向LinkedList对象的指针,该对象正试图分配给LinkedList对象而不是指针。

LinkedList list = new LinkedList(); 

应该读

LinkedList list; 
0

要么

LinkedList list; 
list.addAtFront(0); 

LinkedList* list = new LinkedList(); 
list->addAtFront(0); 
delete list; 
1

试试这个完全实现双向链表:

#include <stdio.h> 

struct node{ 
int data; 
struct node *next,*prev; 
}; 

struct node *head=NULL; 

void insert(int data, int position) 
{ 
    struct node *newNode=malloc(sizeof(struct node)); 
    newNode->data=data; 

    if(position<1) 
    { 
     printf("Invalid Insertion Position \n"); 
     return; 
    } 
    if(head==NULL && position==1) 
    { 
     newNode->next=NULL; 
     newNode->prev=NULL; 
     head=newNode; 
    } 
    else if(head==NULL && position!=1) 
    { 
     printf("Invalid Insertion Position \n"); 
    } 
    else if(position==1) 
    { 
     newNode->next=head; 
     newNode->prev=NULL; 
     if(head->next!=NULL) 
     { 
      head->next->prev=newNode; 
     } 
     head=newNode; 
    } 
    else 
    { 
     int i=0; 
     struct node *temp=head; 
     while(temp->next!=NULL && i<position-2) 
     { 
      i++; 
      temp=temp->next; 
     } 
     if(i<position-2) 
     { 
      printf("Invalid Insertion Position \n"); 
     } 
     else 
     { 
     newNode->next=temp->next; 
     temp->next=newNode; 
     newNode->prev=temp; 
     if(temp->next!=NULL) 
     { 
      temp->next->prev=newNode; 
     } 
     } 

    } 
} 

void delete(int position) 
{ 
    int i=0; 
    if(position<1) 
    { 
     printf("Invalid Position of Deletion \n"); 
     return; 
    } 
    if(head==NULL) 
    { 
     return; 
    } 
    if(position==1) 
    { 
     head=head->next; 
     if(head!=NULL) 
     { 
     head->prev=NULL; 
     } 
    } 
    else 
    { 
     struct node *temp=head; 
     while(temp->next->next!=NULL && i<position-2) 
     { 
      i++; 
      temp=temp->next; 
     } 
     if(i<position-2) 
      { 
       printf("Invalid Position of Deletion \n"); 
       return; 
      } 
     else 
      { 
       temp->next=temp->next->next; 
       if(temp->next!=NULL) 
       temp->next->prev=temp; 
      } 
    } 
} 



void printlist() 
{ 
    if(head==NULL) 
    { 
     printf("Empty List!! \n"); 
     return; 
    } 
    struct node *temp=head; 

    while(temp!=NULL) 
    { 
     printf("%d",temp->data); 
     printf("\t"); 
     temp=temp->next; 
    } 
    printf("\n"); 
} 

int main() 
{ 
    int t; 
    printf("Enter number of Test Cases: \t"); 
    scanf("%d", &t); 
    printf("\nEnter Queries in this format: \n"); 
    printf("For Insertion: \t I data position \n"); 
    printf("\tEx:\t I 25 5 \n"); 
    printf("For Deletion: \t D position \n"); 
    printf("\tEx:\t D 2 \n\n"); 

    while(t--) 
    { 
     char c; 
     int a,b; 
     printf("Enter query: \t"); 
     scanf("%c", &c); 
     scanf("%c", &c); 

     if(c=='I') 
     { 
      scanf("%d %d", &a,&b); 
      insert(a,b); 
     } 
     else if(c=='D') 
     { 
      scanf("%d", &a); 
      delete(a); 
     } 
     printlist(); 
    } 

} 
-1

我想你应该实现两个类:

  1. 双向链表与哨兵:Double_sentinel_list,并
  2. 双连接节点: Double_node

成员变量。 Constuctors,析构函数:

int size() const; 
    //Returns the number of items in the list. 
bool empty() const; 
    // Returns true if the list is empty, false otherwise. 
Type front() const; 
    // Retrieves the object stored in the node pointed to by the next pointer of the head sentinel. This function throws a underflow if the list is empty. 
Type back() const; 
    // Retrieves the object stored in the node pointed to by the previous pointer of the tail sentinel. This function throws a underflow if the list is empty. 
Double_node<Type> *head() const; 
    // Returns the head pointer. 
Double_node<Type> *tail() const; 
    // Returns the tail pointer. 
int count(Type const &) const; 
    // Returns the number of nodes in the linked list storing a value equal to the argument. Mutators 

这个类有七个存取器:

与指针打交道时
void swap(Double_sentinel_list &); 
    // The swap function swaps all the member variables of this linked list with those of the argument. 
Double_sentinel_list &operator=(Double_sentinel_list &); 
    // The assignment operator makes a copy of the argument and then swaps the member variables of this node doubly linked sentinel list those of the copy. 
void push_front(Type const &); 
    // Creates a new Double_node<Type> storing the argument, the next pointer of which is set to the next pointer of the sentinel and the previous pointer is set to point to the sentinel. Theprevious pointer of what was the first node is set to the new node. 
void push_back(Type const &); 
    // Similar to push_front, this places a new node at the back of the list. 
Type pop_front(); 
    // Delete the first non-sentinel node at the front of the linked list and the previous and next pointers of any other node (including the sentinels) within the list. Return the object stored in the node being popped. Throw an underflow exception if the list is empty. 
Type pop_back(); 
    // Similar to pop_front, delete the last non-sentinel node in the list. This function throws a underflow if the list is empty. 
int erase(Type const &); 
    // Delete the first node (from the front and other than the sentinals) in the linked list that contains the object equal to the argument (use == to to test for equality with the retrieved element). Update the previous and next pointers of any other node (including possibly the sentinels) within the list. Return the number of nodes that were deleted.