我有一个功能,我必须移动现有代码,例如
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
感谢您的帮助。
答案 0 :(得分:2)
您的节点链与所谓的单链表非常相似。有了这些节点,通常通过在遍历列表时跟踪上一个节点来删除节点,这样当找到目标节点时,您就会知道哪一个节点(如果有的话)在它之前。拥有这条信息可以轻松修改列表。
以下是如何将其应用于您的代码。我还添加了一个小工具来打印链的内容,以便清楚它们中的内容。
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
答案 1 :(得分:1)
这需要一些计算。让我们假设一般情况:
e i-1 - &gt; e i - &gt; e i + 1 - &gt; ... - &gt; Ë<子>名词子> 的
现在我们想将 e i 移到最后一个位置:
e i-1 - &gt; e i + 1 - &gt; ... - &gt; e n - &gt; Ë<子> I 子> 的
所以问题是:应该改变什么?根据一般情况,有三个指针必须改变:
None
);和现在由于链表是没有双重链接:一个节点没有引用前一个节点,我们唯一可以做的就是获取前一个元素,从根节点迭代直到我们找到元素:
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 :鉴于您引用了a
,b
和c
。当然没有理由计算前一个和后一个:你知道a
是前一个,c
是最后一个。所以在这种情况下,代码就是:
a.set_next(c)
c.set_next(b)
b.set_next(None)
如果根元素是节点本身,则此代码不起作用。我将它作为练习来修改代码以使其正常工作。这不是很难。