More on Linked Lists – flattening and unflattening

More from the Programming Interviews Exposed book (see last post). In this problem you take a double linked list (where each node knows its previous and next nodes) with child elements, and flatten it. Then unflatten it back to its original structure. It took me a few minutes to understand using recursion for unflattening.

  1. class Node:
  2. def __init__(self,data,prev=None,next=None,child=None):
  3. self.data=data
  4. self.prev=prev
  5. self.next=next
  6. self.child=child
  7. class ListFlattener:
  8. """
  9. >>> node1=Node(1)
  10. >>> node5=Node(5)
  11. >>> node1.child=node5
  12. >>> node2=Node(2)
  13. >>> node3=Node(3,node1,None,node2)
  14. >>> node1.next=node3
  15. >>> node4=Node(4,node2)
  16. >>> node2.next=node4
  17. >>> ListFlattener.listAsArray(node1)
  18. [1, 3]
  19. >>> ListFlattener.flattenList(node1)
  20. >>> ListFlattener.listAsArray(node1)
  21. [1, 3, 5, 2, 4]
  22. >>> ListFlattener.unflattenList(node1)
  23. >>> ListFlattener.listAsArray(node1)
  24. [1, 3]
  25. >>> ListFlattener.flattenList(node1)
  26. >>> ListFlattener.listAsArray(node1)
  27. [1, 3, 5, 2, 4]
  28. >>> ListFlattener.listAsArray(ListFlattener.findTail(node1),False)
  29. [4, 2, 5, 3, 1]
  30. """
  31. @staticmethod
  32. def flattenList(head):
  33. curr=head
  34. tail=ListFlattener.findTail(head)
  35. while curr!=None:
  36. if curr.child!=None:
  37. tail=ListFlattener.appendChildToEnd(curr,curr.child,tail)
  38. curr=curr.next
  39. @staticmethod
  40. def unflattenList(head):
  41. curr=head
  42. while curr!=None:
  43. if curr.child!=None:
  44. curr.child.prev.next=None
  45. curr.child.prev=None
  46. ListFlattener.unflattenList(curr.child)
  47. curr=curr.next
  48. @staticmethod
  49. def appendChildToEnd(node,child,tail):
  50. tail.next=child
  51. child.prev=tail
  52. return ListFlattener.findTail(child)
  53. @staticmethod
  54. def findTail(node):
  55. while node.next!=None:
  56. node=node.next
  57. return node
  58. @staticmethod
  59. def listAsArray(node,forward=True):
  60. list=[]
  61. while node!=None:
  62. list.append(node.data)
  63. if forward:
  64. node=node.next
  65. else:
  66. node=node.prev
  67. return list
  68. if __name__ == "__main__":
  69. import doctest
  70. doctest.testmod()
class Node:
    def __init__(self,data,prev=None,next=None,child=None):
        self.data=data
        self.prev=prev
        self.next=next
        self.child=child

class ListFlattener:
    """
    >>> node1=Node(1)
    >>> node5=Node(5)
    >>> node1.child=node5
    >>> node2=Node(2)
    >>> node3=Node(3,node1,None,node2)
    >>> node1.next=node3
    >>> node4=Node(4,node2)
    >>> node2.next=node4
    >>> ListFlattener.listAsArray(node1)
    [1, 3]
    >>> ListFlattener.flattenList(node1)
    >>> ListFlattener.listAsArray(node1)
    [1, 3, 5, 2, 4]
    >>> ListFlattener.unflattenList(node1)
    >>> ListFlattener.listAsArray(node1)
    [1, 3]
    >>> ListFlattener.flattenList(node1)
    >>> ListFlattener.listAsArray(node1)
    [1, 3, 5, 2, 4]
    >>> ListFlattener.listAsArray(ListFlattener.findTail(node1),False)
    [4, 2, 5, 3, 1]
    """
    @staticmethod
    def flattenList(head):
        curr=head
        tail=ListFlattener.findTail(head)
        while curr!=None:
            if curr.child!=None:
                tail=ListFlattener.appendChildToEnd(curr,curr.child,tail)
            curr=curr.next

    @staticmethod
    def unflattenList(head):
        curr=head
        while curr!=None:
            if curr.child!=None:
                curr.child.prev.next=None
                curr.child.prev=None
                ListFlattener.unflattenList(curr.child)
            curr=curr.next

    @staticmethod
    def appendChildToEnd(node,child,tail):
        tail.next=child
        child.prev=tail
        return ListFlattener.findTail(child)

    @staticmethod
    def findTail(node):
        while node.next!=None:
            node=node.next
        return node

    @staticmethod
    def listAsArray(node,forward=True):
        list=[]
        while node!=None:
            list.append(node.data)
            if forward:
                node=node.next
            else:
                node=node.prev
        return list

if __name__ == "__main__":
    import doctest
    doctest.testmod()
This entry was posted in programming and tagged , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *