C ++中的简单链表

时间:2014-03-03 08:00:12

标签: c++ linked-list

我即将创建一个可以插入和显示的链接:

struct Node {
    int x;
    Node *next;
};

这是我的初始化函数,只会调用第一个Node

void initNode(struct Node *head, int n){
    head->x = n;
    head->next = NULL;
}

要添加Node,我认为我的链接列表无法正常工作的原因在于此函数:

void addNode(struct Node *head, int n){
    struct Node *NewNode = new Node;
    NewNode-> x = n;
    NewNode -> next = head;
    head = NewNode;
}

我的main功能:

int _tmain(int argc, _TCHAR* argv[])
{
    struct Node *head = new Node;

    initNode(head, 5);
    addNode(head, 10);
    addNode(head, 20);
    return 0;
}

让我按照我认为有效的方式运行程序。首先,我将头部Node初始化为Node,如下所示:

head = [ 5 |  NULL ]

然后我添加一个n = 10的新节点,并将head作为我的参数。

NewNode = [x |下一步指向下一个点。然后我改变了head指向NewNode的地方,因为NewNode现在是LinkedList中的第一个Node。

为什么这不起作用?我会很感激任何可以让我朝着正确的方向前进的提示。我认为LinkedList有点难以理解。

当我打印时,它只返回5:

12 个答案:

答案 0 :(得分:37)

这是我在这种情况下可以想到的最简单的例子,并没有经过测试。请考虑这使用了一些不好的做法,并且不像通常用C ++那样(初始化列表,声明和定义的分离等)。但这是我在这里无法涵盖的主题。

#include <iostream>
using namespace std;

class LinkedList{
    // Struct inside the class LinkedList
    // This is one node which is not needed by the caller. It is just
    // for internal work.
    struct Node {
        int x;
        Node *next;
    };

// public member
public:
    // constructor
    LinkedList(){
        head = NULL; // set head to NULL
    }

    // destructor
    ~LinkedList(){
        Node *next = head;

        while(next) {              // iterate over all elements
            Node *deleteMe = next;
            next = next->next;     // save pointer to the next element
            delete deleteMe;       // delete the current entry
        }
    }

    // This prepends a new value at the beginning of the list
    void addValue(int val){
        Node *n = new Node();   // create new Node
        n->x = val;             // set value
        n->next = head;         // make the node point to the next node.
                                //  If the list is empty, this is NULL, so the end of the list --> OK
        head = n;               // last but not least, make the head point at the new node.
    }

    // returns the first element in the list and deletes the Node.
    // caution, no error-checking here!
    int popValue(){
        Node *n = head;
        int ret = n->x;

        head = head->next;
        delete n;
        return ret;
    }

// private member
private:
    Node *head; // this is the private member variable. It is just a pointer to the first Node
};

int main() {
    LinkedList list;

    list.addValue(5);
    list.addValue(10);
    list.addValue(20);

    cout << list.popValue() << endl;
    cout << list.popValue() << endl;
    cout << list.popValue() << endl;
    // because there is no error checking in popValue(), the following
    // is undefined behavior. Probably the program will crash, because
    // there are no more values in the list.
    // cout << list.popValue() << endl;
    return 0;
}

我强烈建议您阅读一些关于C ++和面向对象编程的内容。一个很好的起点可能是:http://www.galileocomputing.de/1278?GPP=opoo

编辑:添加了弹出功能和一些输出。正如您所看到的,该程序将推送3个值5,10,20,然后弹出它们。之后订单相反,因为此列表在堆栈模式下工作(LIFO,后进先出)

答案 1 :(得分:5)

您应该参考头指针。否则,指针修改在函数外部不可见。

void addNode(struct Node *&head, int n){
    struct Node *NewNode = new Node;
 NewNode-> x = n;
 NewNode -> next = head;
 head = NewNode;
}

答案 2 :(得分:3)

这两个功能都是错误的。首先,函数initNode具有令人困惑的名称。它应该被命名为例如initList,并且不应该执行addNode的任务。也就是说,它不应该向列表中添加值。

实际上,函数initNode没有任何意义,因为在定义头部时可以完成列表的初始化:

Node *head = nullptr;

Node *head = NULL;

因此,您可以从列表设计中排除函数initNode

同样在您的代码中,无需为结构Node指定详细的类型名称,即在名称Node之前指定关键字struct。

函数addNode将改变head的原始值。在函数实现中,只更改作为参数传递给函数的头的副本。

该功能可能如下所示:

void addNode(Node **head, int n)
{
    Node *NewNode = new Node {n, *head};
    *head = NewNode;
}

或者如果您的编译器不支持初始化的新语法,那么您可以编写

void addNode(Node **head, int n)
{
    Node *NewNode = new Node;
    NewNode->x = n;
    NewNode->next = *head;
    *head = NewNode;
}

或者不使用指向指针的指针,而是可以使用对指向Node的指针。例如,

void addNode(Node * &head, int n)
{
    Node *NewNode = new Node {n, head};
    head = NewNode;
}

或者您可以从函数中返回更新的头部:

Node * addNode(Node *head, int n)
{
    Node *NewNode = new Node {n, head};
    head = NewNode;
    return head;
}

main写道:

head = addNode(head, 5);

答案 3 :(得分:2)

addNode功能需要能够更改head。正如现在所写,只需更改局部变量head(参数)。

将代码更改为

void addNode(struct Node *& head, int n){
    ...
}

会解决这个问题,因为现在head参数通过引用传递,被调用的函数可以改变它。

答案 4 :(得分:2)

head在主要内部定义如下。

struct Node *head = new Node;

但您只是在addNode()initNode()函数中更改头部。这些变化不会反映在主要上。

将头部的声明设为全局,不要将其传递给函数。

功能应如下所示。

void initNode(int n){
    head->x = n;
    head->next = NULL;
}

void addNode(int n){
    struct Node *NewNode = new Node;
    NewNode-> x = n;
    NewNode->next = head;
    head = NewNode;
}

答案 5 :(得分:2)

我会加入战斗。自从我写完C以来已经太久了。此外,这里没有完整的例子。 OP的代码基本上是C,所以我继续使用GCC。

之前已经涵盖了这些问题; next指针未被提升。这就是问题的症结所在。

我也借此机会进行了建议编辑;而不是将两个函数放到malloc,我将其放在initNode()中,然后将initNode()用于malloc两个(malloc是“C new”如果你将)。我更改了initNode()以返回指针。

#include <stdlib.h>
#include <stdio.h>

// required to be declared before self-referential definition
struct Node;

struct Node {
    int x;
    struct Node *next;
};

struct Node* initNode( int n){
    struct Node *head = malloc(sizeof(struct Node));
    head->x = n;
    head->next = NULL;
    return head;
}

void addNode(struct Node **head, int n){
 struct Node *NewNode = initNode( n );
 NewNode -> next = *head;
 *head = NewNode;
}

int main(int argc, char* argv[])
{
    struct Node* head = initNode(5);
    addNode(&head,10);
    addNode(&head,20);
    struct Node* cur  = head;
    do {
        printf("Node @ %p : %i\n",(void*)cur, cur->x );
    } while ( ( cur = cur->next ) != NULL );

}

汇编:gcc -o ll ll.c

输出:

Node @ 0x9e0050 : 20
Node @ 0x9e0030 : 10
Node @ 0x9e0010 : 5

答案 6 :(得分:2)

以下是示例链接列表

    #include <string>
    #include <iostream>

    using namespace std;


    template<class T>
    class Node
    {
    public:
        Node();
        Node(const T& item, Node<T>* ptrnext = NULL);
        T value;
        Node<T> * next;
    };

    template<class T>
    Node<T>::Node()
    {
        value = NULL;
        next = NULL;
    }
    template<class T>
    Node<T>::Node(const T& item, Node<T>* ptrnext = NULL)
    {
        this->value = item;
        this->next = ptrnext;
    }

    template<class T>
    class LinkedListClass
    {
    private:
        Node<T> * Front;
        Node<T> * Rear;
        int Count;
    public:
        LinkedListClass();
        ~LinkedListClass();
        void InsertFront(const T Item);
        void InsertRear(const T Item);
        void PrintList();
    };
    template<class T>
    LinkedListClass<T>::LinkedListClass()
    {
        Front = NULL;
        Rear = NULL;
    }

    template<class T>
    void LinkedListClass<T>::InsertFront(const T  Item)
    {
        if (Front == NULL)
        {
            Front = new Node<T>();
            Front->value = Item;
            Front->next = NULL;
            Rear = new Node<T>();
            Rear = Front;
        }
        else
        {
            Node<T> * newNode = new Node<T>();
            newNode->value = Item;
            newNode->next = Front;
            Front = newNode;
        }
    }

    template<class T>
    void LinkedListClass<T>::InsertRear(const T  Item)
    {
        if (Rear == NULL)
        {
            Rear = new Node<T>();
            Rear->value = Item;
            Rear->next = NULL;
            Front = new Node<T>();
            Front = Rear;
        }
        else
        {
            Node<T> * newNode = new Node<T>();
            newNode->value = Item;
            Rear->next = newNode;
            Rear = newNode;
        }
    }
    template<class T>
    void LinkedListClass<T>::PrintList()
    {
        Node<T> *  temp = Front;
        while (temp->next != NULL)
        {
            cout << " " << temp->value << "";
            if (temp != NULL)
            {
                temp = (temp->next);
            }
            else
            {
                break;
            }
        }
    }

    int main()
    {
        LinkedListClass<int> * LList = new LinkedListClass<int>();
        LList->InsertFront(40);
        LList->InsertFront(30);
        LList->InsertFront(20);
        LList->InsertFront(10);
        LList->InsertRear(50);
        LList->InsertRear(60);
        LList->InsertRear(70);
        LList->PrintList();
    }

答案 7 :(得分:1)

使用:

lookup

答案 8 :(得分:1)

我认为,为了确保列表中每个节点的紧密链接,addNode方法必须是这样的:

void addNode(struct node *head, int n) {
  if (head->Next == NULL) {
    struct node *NewNode = new node;
    NewNode->value = n;
    NewNode->Next = NULL;
    head->Next = NewNode;
  }
  else 
    addNode(head->Next, n);
}

答案 9 :(得分:1)

在代码中有一个错误:

void deleteNode ()
{
    for (Node * temp = head; temp! = NULL; temp = temp-> next)
        delete head;
}

有必要:

for (; head != NULL; )
{
    Node *temp = head;
    head = temp->next;

    delete temp;
}

答案 10 :(得分:0)

这是我的实现方式。

although true works here but you must write someBooleanAttribute={true} because someBooleanAttribute="false" will be recognized as true

enter image description here

答案 11 :(得分:0)

使用节点类和链接列表类的链接列表

这只是示例,并非链接列表的完整功能,代码中解释了添加功能和打印链接列表的

代码:

#include<iostream>
using namespace std;

节点类

class Node{
    public:
    int data;
    Node* next=NULL;
    Node(int data)
        {
            this->data=data;


        }   
    };

链接列表类命名为ll

class ll{
    public:
        Node* head;

ll(Node* node)
    {
        this->head=node;
    }

void append(int data)
    {
        Node* temp=this->head;
        while(temp->next!=NULL)
            {
                temp=temp->next;
            }
        Node* newnode= new Node(data);
        // newnode->data=data;
        temp->next=newnode;
    }
void print_list()
    {   cout<<endl<<"printing entire link list"<<endl;
        Node* temp= this->head;
        while(temp->next!=NULL)
            {
                cout<<temp->data<<endl;
                temp=temp->next;
            }
        cout<<temp->data<<endl;;

    }
};

主要功能

int main()
{
  cout<<"hello this is an example of link list in cpp using classes"<<endl;
  ll list1(new Node(1));
  list1.append(2);
  list1.append(3);
  list1.print_list();
  }

thanks ❤❤❤

屏幕截图https://i.stack.imgur.com/C2D9y.jpg