从中间删除节点的算法

时间:2017-02-04 22:17:53

标签: python algorithm linked-list nodes

我正在阅读Cracking the Coding Interview并且正在练习练习问题而且我仍然坚持这个:

“实现一种算法来删除中间的节点(即除了第一个和最后一个节点之外的任何节点,不一定是确切的中间节点)或单个链接列表,只能访问该节点。

实施例 输入:来自链表的节点a-> b-> c-> d-> e-> f 结果:未返回任何内容,但新链接列表看起来像a-> b-> d-> e-> f“

这是我的代码:

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

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


class LinkedList():
    def __init__(self, head = None):
        self.head = head

    def insert(self, data):
        new_node = Node(data)
        new_node.nextnode = self.head
        self.head = new_node

    def remove(self, data):
        current = self.head
        absent = True
        if current == None: print('List is empty')
        if current.data == data:
            self.head = current.nextnode
            absent = False
        while current.nextnode:
            if current.nextnode.data == data:
                absent = False
                if current.nextnode.nextnode:
                    current.nextnode = current.nextnode.nextnode
                else: current.nextnode = None
            else: current = current.nextnode
        if absent: print('Element not in list')

    def size(self):
        current = self.head
        size = 0
        while current:
            current = current.nextnode
            size += 1
        return size

    def find(self, data):
        current = self.head
        if current == None: print('List is empty')
        search = True
        while current and search:
            if current.data == data:
                print(current)
                search = False
            current = current.nextnode
        if search: print('Not found')

def print_list(self):
    current = self.head
    while current:
        print(current, end = ' ')
        current = current.nextnode
    print('')    


node1 = Node(1)
node2 = Node(2)
node3 = Node(3)
node4 = Node(4)
node1.nextnode = node2
node2.nextnode = node3
node3.nextnode = node4
list1 = LinkedList(node1)
list1.insert(2 ****EDITED node2 to 2 here****)
print_list(list1)

def delmid(ll, n):
    current = ll.head
    if current == n:
        print('Can\'t delete first node')
        return
    while current.nextnode:
        if current.nextnode == n:
            if current.nextnode.nextnode:
                current.nextnode = current.nextnode.nextnode
                return
            else:
                print('Can\'t delete last node')
                return

delmid(list1, node2)
print_list(list1)

我无法弄清楚为什么它似乎没有认为ll.head和node2是相同的......如果我摆脱了行list1.insert(node2) ...

我不明白......

编辑:在读完书中解决方案的第一句后,显然我做错了......“只允许访问该节点”意味着你不知道列表的头部...返回到绘图板......

2 个答案:

答案 0 :(得分:1)

因为你的插入方法错了:

def insert(self, data):
    new_node = Node(data)
    new_node.nextnode = self.head
    self.head = new_node

您的方法不会插入node2本身作为节点:它会创建一个新节点,其中node2作为有效负载(数据)。这是不同的。

您可以定义方法:

def insert_node(self, node):
    node.nextnode = self.head
    self.head = new_node

然而,这将创建一个循环,因为现在node1将指向node2和node2 to node1`。因此,生成的链表将是一个带有两个元素的圆形列表,如:

node1  -->  node2
  ^---------/

编辑:因为你解决了那个问题。您的delmid方法也存在问题。

主要问题是你的while循环中的需要遍历链表,而你不这样做:当前总是保持不变,所以:

def delmid(ll, n):
    current = ll.head
    if current == n:
        print('Can\'t delete first node')
        return
    while current.nextnode:
        if current.nextnode == n:
            if current.nextnode.nextnode:
                current.nextnode = current.nextnode.nextnode
                return
            else:
                print('Can\'t delete last node')
                return
        current = current.nextnode

应该解决这个问题。

答案 1 :(得分:0)

插入操作

您误解了自己的insert - 实施。 list1.insert(node2)node2的新节点作为内容

插入
def insert(self, data):
    new_node = Node(data)    #  <== wrap node2 into another node instance
    new_node.nextnode = self.head
    self.head = new_node

节点比较

== - 运算符通过调用方法__eq__(self, other)在内部工作。在您的情况下,您没有为此方法提供和实现,因此默认值用于比较所有变量,其中包括nextnode。因此,如果它们完全相同,则两个节点只能相等。要更正此问题,请使用Node中的自定义比较方法:

    def __eq__(self, other):
        return type(other) is Node && other.data == self.data

__eq__ - 方法首先检查other肯定属于Node类型,然后按每个实例中存储的data进行比较。

Delmid

比实际问题更进一步:

while current.nextnode:
    if current.nextnode == n:
        if current.nextnode.nextnode:
            current.nextnode = current.nextnode.nextnode
            return
        else:
            print('Can\'t delete last node')
            return

此循环将无限运行,除非列表的最大大小为1.要在current = current.nextnode列表中修复此步骤。

改善德尔米德

此任务的实际目的是让您习惯于另一种操纵链接列表的方式:交换

您可以检查n既不是第一个节点也不是最后一个节点,而是将值替换为连续节点的值,而不是在整个列表中搜索n的前任。删除连续节点:

def delmid(ll, n):
    if ll.head == n:
        print('Can\'t delete first node')
        return
    if n.nextnode is None:
        print('Can\'t delete last node')
        return

    # swap values
    tmp = n.data
    n.data = n.nextnode.data
    n.nextnode.data = tmp

    # remove node
    n.nextnode = n.nextnode.nextnode