我已经在这上面困了半天了。我可以得到一些提示或指针,如何交换一个链表的头部和尾部(而不是反转整个列表),而不复制他们的数据吗?
class myNode:
def __init__(data, next):
self.data = data
self.next = next
class MyLinkedList:
def __init__(self):
self.head = None
self.tail = None
如果我能看到代码并对它有一个解释,那就太棒了!
编辑:
通过列表查找列表的第二个最后节点,并将其链接到头部。
将原来的头部链接到null,就像现在一样,头部应该被交换到尾部。
有一些边缘情况最好单独处理,以保持代码简单。它们是大小为零、一和二的列表。
对于其中的前两个,列表根本不会改变。对于大小2,只有头部和尾部会改变,内部节点不会改变(因为没有内部节点)。
在这种情况下,左边的列表变成右边的列表(表示空指针,
h/t
表示头部和尾部指针):
h t h t
A -> B -> | B -> A -> |
使用(这是伪代码而不是Python,.n
指定next
指针):
h=A t=B A.n=B B.n=|
tail.next = head h=A t=B A.n=B B.n=A
head.next = null h=A t=B A.n=| B.n=A
swap head, tail h=B t=A A.n=| B.n=A
对于所有其他情况(三个或更多节点),倒数第二个节点的指针必须更改为指向新的尾部。上面的两个节点的情况可能更容易,因为它知道头部是倒数第二个。下图显示了大小为4的情况(我已经用P
标记了倒数第二个节点):
h p t h p t
A -> B -> C -> D -> | D -> B -> C -> A -> |
这可以通过以下操作实现:
h=A t=D p=C A.n=B B.n=C C.n=D D.n=|
tail.next = head.next h=A t=D p=C A.n=B B.n=C C.n=D D.n=B
head.next = None h=A t=D p=C A.n=| B.n=C C.n=D D.n=B
penu.next = head h=A t=D p=C A.n=| B.n=C C.n=A D.n=B
swap head, tail h=D t=A p=C A.n=| B.n=C C.n=A D.n=B
class MyNode:
def __init__(self, data, next = None):
self.data = data
self.next = next
class MyList:
def __init__(self):
self.head = None
self.tail = None
def push_back(self, data):
if self.tail is None:
self.head = MyNode(data)
self.tail = self.head
else:
self.tail.next = MyNode(data)
self.tail = self.tail.next
def dump(self, desc):
print(desc, end=' ')
node = self.head
while node is not None:
print(node.data, end=' -> ')
node = node.next
print('|')
def swap(self):
# For empty and size 1, no change.
if self.head is None: return
if self.head.next is None: return
# For size 2, easy swap.
if self.head.next.next is None:
self.tail.next = self.head
self.head.next = None
self.head, self.tail = self.tail, self.head
return
# For size 3+, little more complex, need the
# penultimate node as well as head and tail.
penu = self.head
while penu.next != self.tail:
penu = penu.next
self.tail.next = self.head.next
self.head.next = None
penu.next = self.head
self.head, self.tail = self.tail, self.head
当然,如果没有某种测试代码,什么自尊类会存在。下面将测试不同大小的列表,以便您可以看到swap
操作按预期工作:
x = MyList()
# Do various sizes.
for i in range(6):
# Add an element except for first time (so we check empty list).
if i > 0:
x.push_back(i)
# Show before and after figures, making sure we restore
# list to original state.
x.dump('Size = %d, before:'%(i))
x.swap()
x.dump('Size = %d, after :'%(i))
x.swap()
print()
运行此代码将导致:
Size = 0, before: |
Size = 0, after : |
Size = 1, before: 1 -> |
Size = 1, after : 1 -> |
Size = 2, before: 1 -> 2 -> |
Size = 2, after : 2 -> 1 -> |
Size = 3, before: 1 -> 2 -> 3 -> |
Size = 3, after : 3 -> 2 -> 1 -> |
Size = 4, before: 1 -> 2 -> 3 -> 4 -> |
Size = 4, after : 4 -> 2 -> 3 -> 1 -> |
Size = 5, before: 1 -> 2 -> 3 -> 4 -> 5 -> |
Size = 5, after : 5 -> 2 -> 3 -> 4 -> 1 -> |
一旦您对此工作感到满意,您可能需要考虑将penu
(倒数第二个节点指针)变成一个成员,就像head
和tail
一样,如果大小是两个或更小,则将其设置为none
。这样,您就不必在每次交换节点时都进行搜索。每当调用push_back
(或任何其他更改列表大小的方法)时,更新它应该比较容易。
如果你想创建一个像这样的单链表: 这个列表有方法“追加”、“删除”、“printList”和“findElement”。有必要有尾巴吗?因为使用“最后”你可以地址最后一个节点。 那么,什么时候有必要拥有所有三个节点“头”、“尾”和“最后”?例如,当您想将排序的节点插入列表时?
我正在尝试为我的链表类创建一个添加和删除方法。我写了两封信,名字是Head和Tail。 头- 当我试图删除特定节点时,我一直遇到问题,因为Java说我越界了。我想是因为我的头没有指向第一个节点?你们觉得怎么样?还是我完全走错路了...
[采访问题] 编写一个函数,该函数将在一次传递中从单个链表整数的尾部(或尾部)返回第5个元素,然后提供一组针对该函数的测试用例。 这类似于问题:如何从单链表的末尾找到第n个元素?,但是我还有一个额外的要求,我们应该只遍历链接列表一次。 这是我的解决方案: 我只遍历链表一次,并使用隐式递归堆栈。另一种方法是有两个指针:快指针和慢指针,快指针是比慢指针快的k个指针。哪一个看起来更好?我认为有两个指针的
似乎人们总是说,如果一个单链接列表的头是空的,那么这个列表是空的,但是检查尾部也会起作用吗?假设我确实知道一个列表有一个尾部,我可以检查尾部是否为空以确定它是否为空吗?
我正在尝试交换双链接列表中的两个节点。下面是具有交换功能的程序部分。 当我运行这个程序时,在第一个和第二个节点的情况下,它崩溃了。而在任何其他节点的情况下,它提供无限循环输出。(例如:-2- 我知道还有一些关于节点交换的问题,但是我没有找到任何与我的问题相似的问题。请帮帮我...!! 提前谢谢。