【问题标题】:Moving a node to the end of a chain of nodes将节点移动到节点链的末尾
【发布时间】:2017-02-02 21:18:13
【问题描述】:

我有一个函数,例如,我必须移动现有代码

def print_chain_and_ids(chain):
    current = chain
    while current != None:
        print(id(current), current.get_data())
        current = current.get_next()

a = Node('first')
b = Node('middle')
c = Node('last')
a.set_next(b)
b.set_next(c)

print_chain_and_ids(a)
move_node_to_end(a, 'middle')    

print_chain_and_ids(a)

所以现在链条开始了:

a ----> b ----> c

节点c位于链的末尾。

如果我想将节点 b 移动到链的末尾,那么它会:

a ----> c ----> b

这样它就不会改变最后一个节点的值,而只是移动它。我已经准备好一个节点类:

class Node:
    def __init__(self, init_data):
        self.data = init_data
        self.next = None

    def get_data(self):
        return self.data

    def get_next(self):
        return self.next

    def set_data(self, new_data):
        self.data = new_data

    def set_next(self, new_next):
        self.next = new_next

    def __str__(self):
        return str(self.data)

我想知道我将如何去做。

我想做一个函数,它接受两个输入,链的第一个节点,以及移动到链最后位置的值。所以:

def node_to_end(first_node, value_to_move):
    .....

这是我必须修改节点位置的地方。所以要移动的值会移到最后一个位置。

a = Node('blue')
b = Node('red')
c = Node('green')

a.set_next(b)
b.set_next(c)

这将导致blue red green

node_to_end(a, 'red') 

会创建一个链

blue green red

感谢您的帮助。

【问题讨论】:

  • 所以你想让c 指向ba 指向cb 指向什么?您已经编写了 set_next 方法,只需使用它来使它们指向您想要的内容....我不明白您的问题。对不起。
  • 我希望 b 指向 c 并且 c 指向 b。我不希望 b 和 c 的值只改变位置。
  • 目前b=a.nextc=a.next.next。现在做:a.next = c; c.next=b; b.next=None
  • 我认为你需要重新阅读你的链表笔记,不要粗鲁或任何事情。如果b->cc->b 那么这不是你举的例子:a ----> c ----> b。您仍然拥有“移动”节点的工具。我仍然无法理解您对您编写的程序的不理解。如果您没有编写程序,也许您应该向您的老师/导师/作者询问如何使用该程序。从您向我们展示的内容来看,您应该已经知道该怎么做了。
  • 您似乎无法仅使用“下一个”链接来做到这一点。您可能需要在 Node 类中添加一个“prev”链接。可以使用 b.prev 找到节点 a,b.next 找到节点 c,然后将三个节点上的链接全部更改。

标签: python python-3.x linked-list nodes


【解决方案1】:

您的节点链与所谓的单链表非常相似。有了这些,通常通过在遍历列表时跟踪 previous 节点来删除节点,这样当找到目标节点时,您就会知道哪个(如果有)在它之前。有了这些信息,就可以轻松修改列表。

以下是如何将其应用于您的代码。我还添加了一个小实用程序来打印链的内容,以明确其中的内容。

class Node:
    def __init__(self, init_data):
        self.data = init_data
        self.next = None

    def get_data(self):
        return self.data

    def get_next(self):
        return self.next

    def set_data(self, new_data):
        self.data = new_data

    def set_next(self, new_next):
        self.next = new_next

    def __str__(self):
        return str(self.data)

def move_to_end(start, target):
    """Move target node from the chain beginning with start to end."""
    previous = None
    current = start
    while current:
        if current.get_next() is target:
            previous = current
            break
        current = current.get_next()

    if previous:  # target found in chain?
        previous.set_next(target.get_next())  # remove it
        # and move it to the end
        current = target
        while current:
            if not current.get_next():  # last node in chain?
                target.set_next(None)
                current.set_next(target)
                break
            current = current.get_next()

def print_node_chain(start):
    """Utility to print out a node chain starting from given node."""
    values = []
    current = start
    while current:
        values.append(str(current))
        current = current.get_next()

    print(' ----> '.join(values) + ' ----> None')

a = Node('blue')
b = Node('red')
c = Node('green')

a.set_next(b)
b.set_next(c)

print_node_chain(a)
move_to_end(a, b)
print_node_chain(a)

输出:

blue ----> red ----> green ----> None
blue ----> green ----> red ----> None

【讨论】:

  • 我如何摆脱None 以便它只打印出blue ----> red ----> greenblue ----> green ----> red。感谢您的帮助。
  • 认真的吗?只需将其从显示它的代码中删除即可。
【解决方案2】:

这需要一些计算。让我们假设一般情况:

ei-1 -> ei -> ei+1 -> ... -> en

现在我们要将 ei 移动到最后一个位置:

ei-1 -> ei+1 -> ... -> en -> e我

所以问题是:应该改变什么?基于通用情况,有三个指针必须改变:

  • ei-1 现在指向 ei+1;
  • ei 现在不指向任何东西 (None);和
  • en 现在指向 ei

现在由于链表不是双向链接的:一个节点没有对前一个节点的引用,我们唯一能做的就是从根迭代获取前一个元素 直到我们找到元素:

def get_prev_element(root,node):
    while root.get_next() is not node:
        root = root.get_next()

一旦我们有了前一个元素,我们就可以让它链接到下一个元素:

previous.set_next(node.get_next())

但是现在我们仍然需要找出最后一个元素是什么。猜猜看,我们再次这样做,通过迭代,我们可以从我们自己的节点开始:

def get_last(node):
    while node.get_next() is not None:
        node = node.get_next()
    return node

现在我们将最后一个节点的next设置为我们自己的节点:

last.set_next(node)

最后我们在None旁边设置了自己的:

node.set_next(None)

现在将所有这些组合在一起,我们可以在节点上定义一个方法

class Node:

    # ...

    def get_previous(self,root):
        previous = root
        while previous.get_next() is not self:
            previous = previous.get_next()
        return previous

    def get_last(self):
        last = self
        while last.get_next() is not None:
            last = last.get_next()
        return last

    def move_last(self,root):
        previous = self.get_previous(root)
        previous.set_next(self.get_next())
        last = self.get_last()
        last.set_next(self)
        self.set_next(None)

请注意,由于链表不是双重链接的,因此您必须为其提供根元素。


Intermezzo:假设您引用了abc。当然没有理由计算前一个和最后一个:你知道a 是前一个,c 是最后一个。所以在这种情况下,代码很简单:

a.set_next(c)
c.set_next(b)
b.set_next(None)

如果根元素是节点本身,则此代码不起作用。我将其作为练习来修改代码以使其正常工作。难度不大。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-14
    • 2014-02-02
    • 2013-11-13
    相关资源
    最近更新 更多