动态内存和链表

Posted

技术标签:

【中文标题】动态内存和链表【英文标题】:Dyamic memory & Linked Lists 【发布时间】:2015-05-08 09:08:57 【问题描述】:

好的,假设我们在 C++ 中有一个链表实现。此外假设节点是一个类,列表本身是一个类,它看起来像这样:

#include <iostream>

using namespace std;

class List;

class Node

private:
    Node(char, Node*);
    char data;
    Node* next;
    friend class List;
    friend ostream& operator<<(ostream&, const List&);
;

class List

public:
    List(int = 0);
    List(const List&);
    ~List();
    bool gotoBeginning();
    bool gotoEnd();
    bool gotoNext();
    bool gotoPrior();
    bool insert(char);
    bool remove(char&);
    bool empty() const;
    bool full() const;
    bool clear();
    List& operator=(const List&);
    friend ostream& operator<<(ostream&, const List&);

private:
    Node* head;
    Node* cursor;
;

#endif

假设列表为空。 此外,假设我们刚刚在列表中插入了一个新元素“z”,这意味着列表当前有 1 个节点。

我们来看看插入函数:

bool List::insert(char item)

    if(empty())
    
        Node* newNode = new Node(item, NULL);
        head = cursor = newNode;
        return true;
    
    else
    
        // I dont need to show this part because the above code will suffice
    

好的,所以我们都知道,类型为指向节点的指针的变量 newNode 被分配了包含已存储在堆上的节点的内存位置。

现在记住我们刚刚创建了一个新节点,假设传递给插入函数的项目是'z'

内存分配 堆栈堆 | | | | \|/ \|/ 512 902 内存地址 | -----| |--->|-----|-----| | 902 | | | 'z'|空| |--------|----| |-----|-----| newNode (no name/newNode) 变量名

(无名称):因为在堆上分配的内存只能通过指针直接访问。

我遇到的问题是这个。 newNode 指针是否在堆栈上创建并分配了一些内存地址,如 512,如上所示? 还是该指针从未在堆栈上分配(因此只需删除上面的 512)并且仅指向在堆上创建的内存(902)?

我问的原因是因为插入函数内部 if 语句中的第二行代码将 newNode 分配给 head 和 cursor

这让我很困惑。头部和光标现在会包含地址 512 还是 902?

如果我们继续在插入函数中的 else 语句中编写代码,那么它看起来像这样:

bool List::insert(char item)

    if(empty())
    
        Node* newNode = new Node(item, NULL);
        head = cursor = newNode;
        return true;
    
    else
    
        Node* newNode = new Node(item, NULL);
        cursor = cursor->next = newNode; // what is this line doing
        return true;
    

    return false;

那么cursor-&gt;next如何获取新节点的值,cursor也获取新节点的值。

是的,上面的函数运行良好,我在项目中得到了 A,所以所有代码都是正确的,但我提到的概念让我很困扰

【问题讨论】:

【参考方案1】:

new 返回的指针需要存储在某个地方,它存储在堆栈变量newNode 中。 newNode的值,它的内容,就是new返回的地址。

当您将一个指针分配给另一个指针时,复制的是指针的值、内容、指针指向的地址。

所以当你这样做时,例如

head = newNode;

那么head 将获得与newNode 相同的值,并将指向new 表达式分配的内存。


举个小例子:假设你有两个指针:

int* a;
int* b;

你分配一些内存并分配给a

a = new int;

现在内存看起来像这样:

+---+ +------------------+ |一个 | --> |分配的内存 | +---+ +------------------+

然后你从a分配到b

b = a;

那么内存看起来是这样的:

+---+ |一个 | -。 +---+ | +------------------+ >>-> |分配的内存 | +---+ | +------------------+ |乙 | -' +---+

变量ab 的确切存储位置并不重要,它们指向的位置也不重要。

【讨论】:

好吧,这肯定有帮助,但我仍然对 cursor->next 如何接收 newNode 的地址感到困惑。然后它被分配 newNode, cursor = newNode @fsolano94 函数启动时,列表不为空,那么cursor指向一个节点(应该是最后一个节点),也就是说cursor-&gt;next = newNode会取最后一个节点,make它的next 指针指向newNode 指向的位置。然后,您将 cursor-&gt;next 指向的内容分配给 cursor,使 cursor 再次指向列表中的最后一个节点。但是,该表达式存在问题(请参阅下一条评论)。 @fsolano94 cursor = cursor-&gt;next = newNode 的问题在于它可以被评估为cursor = (cursor-&gt;next = newNode)(这是预期和希望的),但它也可能是(cursor = cursor-&gt;next) = newNode,即 不是你所期望的,最后会导致问题。您需要显式添加括号以确保完成正确的操作。 下一条评论?您是否发布更多详细信息 好的,感谢您提供的所有帮助 Joachim Pileborg 和好名字顺便说一句。 :)【参考方案2】:
cursor = cursor->next = newNode; // what is this line doing

请注意,分配不会同时发生。它从右向左传播。下面是一段更冗长的代码,与上面的代码行相同:

Node* oldNode = cursor;
cursor = newNode;
oldNode->next = newNode;

在某些情况下(重载的赋值运算符),按顺序写下来甚至可能是有益的。

【讨论】:

以上是关于动态内存和链表的主要内容,如果未能解决你的问题,请参考以下文章

数组和链表

数组和链表的区别

数据结构与算法 - 链表

数组和链表区别

面试提问-数组和链表的区别

php数组和链表有什么区别