package me.ramswaroop.misc;
/**
* Created by IntelliJ IDEA.
*
* @date: 5/4/15
* @time: 8:17 PM
*/
// TreeList.java
/*
Demonstrates the greatest recursive pointer problem ever --
recursively changing an ordered binary tree into a circular
doubly linked list.
See http://cslibrary.stanford.edu/109/
This code is not especially OOP.
This code is free for any purpose.
Feb 22, 2000
Nick Parlante nick.parlante@cs.stanford.edu
*/
/*
This is the simple Node class from which the tree and list
are built. This does not have any methods -- it's just used
as dumb storage by TreeList.
The code below tries to be clear where it treats a Node pointer
as a tree vs. where it is treated as a list.
*/
class Node {
int data;
Node small;
Node large;
public Node(int data) {
this.data = data;
small = null;
large = null;
}
}
/*
TreeList main methods:
-join() -- utility to connect two list nodes
-append() -- utility to append two lists
-treeToList() -- the core recursive function
-treeInsert() -- used to build the tree
*/
class TreeList {
/*
helper function -- given two list nodes, join them
together so the second immediately follow the first.
Sets the .next of the first and the .previous of the second.
*/
public static void join(Node a, Node b) {
a.large = b;
b.small = a;
}
/*
helper function -- given two circular doubly linked
lists, append them and return the new list.
*/
public static Node append(Node a, Node b) {
// if either is null, return the other
if (a == null) return (b);
if (b == null) return (a);
// find the last node in each using the .previous pointer
Node aLast = a.small;
Node bLast = b.small;
// join the two together to make it connected and circular
join(aLast, b);
join(bLast, a);
return (a);
}
/*
--Recursion--
Given an ordered binary tree, recursively change it into
a circular doubly linked list which is returned.
*/
public static Node treeToList(Node root) {
// base case: empty tree -> empty list
if (root == null) return (null);
// Recursively do the subtrees (leap of faith!)
Node aList = treeToList(root.small);
Node bList = treeToList(root.large);
// Make the single root node into a list length-1
// in preparation for the appending
root.small = root;
root.large = root;
// At this point we have three lists, and it's
// just a matter of appending them together
// in the right order (aList, root, bList)
aList = append(aList, root);
aList = append(aList, bList);
return (aList);
}
/*
Given a non-empty tree, insert a new node in the proper
place. The tree must be non-empty because Java's lack
of reference variables makes that case and this
method messier than they should be.
*/
public static void treeInsert(Node root, int newData) {
if (newData <= root.data) {
if (root.small != null) treeInsert(root.small, newData);
else root.small = new Node(newData);
} else {
if (root.large != null) treeInsert(root.large, newData);
else root.large = new Node(newData);
}
}
// Do an inorder traversal to print a tree
// Does not print the ending "\n"
public static void printTree(Node root) {
if (root == null) return;
printTree(root.small);
System.out.print(Integer.toString(root.data) + " ");
printTree(root.large);
}
// Do a traversal of the list and print it out
public static void printList(Node head) {
Node current = head;
while (current != null) {
System.out.print(Integer.toString(current.data) + " ");
current = current.large;
if (current == head) break;
}
System.out.println();
}
// Demonstrate tree->list with the list 1..5
public static void main(String[] args) {
// first build the tree shown in the problem document
// http://cslibrary.stanford.edu/109/
Node root = new Node(6);
treeInsert(root, 3);
treeInsert(root, 5);
treeInsert(root, 7);
treeInsert(root, 8);
treeInsert(root, 9);
System.out.println("tree:");
printTree(root); // 1 2 3 4 5
System.out.println();
System.out.println("list:");
Node head = treeToList(root);
printList(head); // 1 2 3 4 5 yay!
}
}