【问题标题】:python linklist pointer and sizepython链接列表指针和大小
【发布时间】:2017-01-19 08:55:14
【问题描述】:

我是一名 Python 新手程序员。我在下面看到了 leetcode 对链表的定义。我对这个概念有 2 个问题,任何帮助将不胜感激。提前致谢

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

Q1 只是想知道“self.next”的类型是什么,我知道在C++中,它应该是一个代表下一个节点地址的指针。但是python没有那个类型,所以我很困惑“next”是什么类型。

Q2 有人告诉我 next 只是一个名字。如果是这样,我运行下面的代码,

head =ListNode(1)
print sys.getsizeof(head)
head.next = ListNode(2)
print sys.getsizeof(head)

首先head.next是'None',然后分配给另一个ListNode类型, 但是在此更改之前和之后我得到了相同大小的头部,我认为头部的大小应该更大,因为它的成员之一(下一个)从 None 类型更改为 ListNode 类型。我只是对此感到困惑,非常感谢!

PS。据我了解,如果我不断向链表添加新节点,头部会越来越大,因为“嵌套”成员“下一个”越来越多,请指出我哪里出错了,谢谢。

【问题讨论】:

  • 它的 python 你可以为它分配几乎任何东西,但它需要是一个 Node 类型,它有一个 next 参数才能使列表工作。您最好为列表类创建一个add 方法,而不是显式添加到.next。你可以在那里进行类型检查,或者在 python 3.5+ 中有一个类型的概念。无论如何,大小都将保持不变,因为实际节点只是一个值和对下一个节点的引用。如果您想知道有多少节点,您需要遍历列表以计算节点数,或者在添加节点时保持计数。
  • 感谢您的澄清,还有一个关于引用的问题,如果引用的大小没有改变,为什么我们会有不同的大小来引用 int 和引用 list,因为在在这种情况下,它们都是引用,只是它们引用的对象不同。
  • 说实话,我不能 100% 确定。但我知道虽然python中的一切都是参考。一个 int 值是一个不可变的引用,因此在分配给它时被复制(类似于在 c++ 中按值传递),但 ListNode 像内置列表、dicts 等是一个可变引用,因此可以通过它传入的函数进行更改(类似于 c++ 中的非常量引用)。这种语义差异可以解释大小的差异。 This 问题可能很有趣。
  • 非常感谢,您的理解对您有帮助

标签: python c++ class pointers linked-list


【解决方案1】:

我对链表的解释。

class LinkedList(object):
    class Node(object):
        def __init__(self, val=None, next=None, previous=None):
            self.val = val
            self.next = next
            self.last = previous

    def __init__(self):
        self.length = 0
        self.start = None
        self.end = None

    def append(self, value):
        self.length += 1
        if not self.start:
            self.start = self.Node(value)
        else:
            if not self.end:
                self.end = self.Node(value)
                self.end.previous = self.start
                self.end.next = self.start
                self.start.next = self.end
            else:
                end = self.Node(value)
                self.end.next = end
                end.previous = self.end
                self.end = end
                self.end.next = self.start

    def prepend(self, value):
        self.length += 1
        if not self.start:
            self.start = self.Node(value)
        else:
            n = self.Node(value, self.start, self.end)
            self.start.previous = n
            self.start = n

    def __len__(self):
        return self.length

    def __iter__(self):
        self.position = 0
        return self

    def next(self):
        self.position += 1
        if self.position-1 >= len(self):
            raise StopIteration
        if self.position-1 == 0:
            return self.start
        cnt = 0
        n = self.start
        while cnt<self.position-1:
            n = n.next
            cnt += 1
        return n


    def __getitem__(self, index):
        if index == 0:
            return self.start

        if index == -1:
            return self.end

        cnt = 0
        n = self.start
        while cnt<index+1:
            n = n.next
            cnt += 1
        return n.val

    def __repr__(self):
        return repr(tuple(x.val for x in self))

l = LinkedList()
l.append(4)
l.append(5)
l.append(3)
l.prepend(0)
print l
print l[1]

【讨论】:

    【解决方案2】:

    问题一:

    Python 变量是动态类型的。 (即一个变量可以保存一个 int,然后保存一个列表,然后保存任何其他任意对象等)。

    在您的情况下,Head.next 首先引用 None NoneType 对象。

    在为它分配不同的值 (ListNode(2)) 后,Head.next 现在会引用新创建的 ListNode 对象。

    问题 2:

    为什么大小没有变化。 我不是 python 的 sys.getsizeof 如何工作的专家,但据我所知,List.next 在这两种情况下都是一个引用变量(即一个引用其他对象的变量)。大小不会改变,因为sys.getsizeof 会找到对象变量的大小。其中Head.next 在这两种情况下都只是对其他对象的引用。

    请参阅 How do I determine the size of an object in Python?,了解有关 sys.getsizeof 工作原理的更完整答案。

    【讨论】:

    • 非常感谢!那么当我们谈论引用变量时,您的意思是说,函数 sizeof(Var1) 获取的是它自身的引用变量的大小,而不是它指向的对象的大小?
    • @MuheXie 是的,这就是我从阅读中了解到的。
    猜你喜欢
    • 2020-04-17
    • 2013-08-26
    • 1970-01-01
    • 2017-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多