We are apologize for the inconvenience but you need to download
more modern browser in order to be able to browse our page

Download Safari
Download Safari
Download Chrome
Download Chrome
Download Firefox
Download Firefox
Download IE 10+
Download IE 10+

How to traverse through a binary tree with parent node pointer (without stack, without recursion)

Recently I have some research coding works, and I’ve met a big problem.

I’m patching a compiler, and to make the change as little as possible, I decided to write the whole patch in a function.

I thought it would be easy for me to achieve this, but I found it’s FAR MORE harder than I ever thought.

I’ve got to create a custom AST, so I can’t use the original implementation of tree, but to write a custom one.

So I have to write a tree implementation.

 

First of all, the definition of struct, quite easy:

struct Node {
	Node* lchild;
	Node* rchild;
	Node* parent;
	union {
		size_t pos;
		uint8_t ins;
	};
};

(As we needed to do the iteration without function, we cannot use the recursive way, and I doesn’t wanted the tree to be changed, so I choose to include a parent node pointer.)

Second, how to create a empty node elegantly:

struct Node emptyNode = { 0 };
struct Node* nodehead = new Node(emptyNode);

Use the copy construction ;)

Third, create a full binary tree with specified degree:(in a iterative way)

int curLevel = 1;
int c = 1;

while (true) {
	if (curLevel < TREE_DEGREE && !curnode->lchild) {
		curLevel++;
		curnode->lchild = new Node(emptyNode);
		curnode->lchild->parent = curnode;
		curnode = curnode->lchild;
		curnode->pos = c++;
	}
	else {
		if (!curnode->parent->rchild) {
			curnode->parent->rchild = new Node(emptyNode);
			curnode->parent->rchild->parent = curnode->parent;
			curnode = curnode->parent->rchild;
			curnode->pos = c++;
		}
		else {
			curLevel--;
			curnode = curnode->parent;
		}
	}
	if (curLevel == 1) {
		break;
	}
}

(A little long, but still easy enough)

 

Fourth, delete selected a leaf node:

int selected = rand() % (remainingLeafNode - 1);
int curLayer = 1;
Node* curnode = nodehead;
bool deleteFail = 0;
while (true) {
	if (curLayer < TREE_DEGREE - 1) {
		if (selected >= pow(2, TREE_DEGREE - curLayer - 1)) {
			curnode = curnode->rchild;
			selected -= pow(2, TREE_DEGREE - curLayer - 1);
		}
		else {
			curnode = curnode->lchild;
		}
	}
	else {
		if (selected == 0) {
			if (!curnode->lchild)
				deleteFail = true;
			else
				curnode->lchild = NULL;
		}
		else {
			if (!curnode->rchild)
				deleteFail = true;
			else
				curnode->rchild = NULL;
		}
		break;
	}
	curLayer++;
}

(Every node is virtually mapped into a full binary tree which its leaf nodes are numbered from left to right)

 

Finally, we have to traverse through the tree: (Here I’ll only show you the last-root order traversing method)

You may thought I’ll show you with this one:

while (true) {
	while (curnode->lchild) {
		curnode = curnode->lchild;
	}

	if (!curnode->rchild) // leaf node here 
		visit(curnode);
	else { // no left child, but have a right child
		curnode = curnode->rchild;
		continue;
	}
	
	// a leaf node
	if (curnode->parent->lchild == curnode) { // a leaf left node finished, go to its sibiling
		if (curnode->parent->rchild) { // has a right sibiling, redoing the process above
			curnode = curnode->parent->rchild;
			continue;
		}
	}
	else {
		// a leaf right node
		while (curnode->parent && curnode == curnode->parent->rchild) {// way up until it's a left node or root node
			curnode = curnode->parent;
			visit(curnode);
		}
		if (curnode == nodehead) {
			break;
		}
		if (curnode->parent->rchild)
			curnode = curnode->parent->rchild;
	}
}

 

But that one has a fatal shortage, the visit code is called in two location, that means I would have to use a function, or to copy the code twice times.

OFC, neither of them satisfied me. Using a function is against my prerequsition, and copy code twice is ugly and not robust

So Instead, I changed the code structure and moved the while loop, introducing two flags, and finally we can have only one visit function here :)

while (true) {
	while (curnode->lchild) {
		curnode = curnode->lchild;
	}
	if (curnode->rchild) { // no left child, but have a right child
		curnode = curnode->rchild;
		continue;
	}

	bool doingRightNodeBacktrack = false;
	bool hasRightNodeBacktrack = false;
	while (true){
		if (hasRightNodeBacktrack && !doingRightNodeBacktrack) {
			break;
		}
		if (doingRightNodeBacktrack || !curnode->rchild) { // short-circuit if doingRightNodeBacktrack is true
			// leaf node here 
			visit(curnode);
		}

		// a leaf node
		if (curnode->parent && curnode->parent->lchild == curnode) { // a leaf left node finished, go to its sibiling
			if (curnode->parent->rchild) { // has a right sibiling, redoing the process above
				curnode = curnode->parent->rchild;
				break;// break into the outer while loop
			}
		}
		else {
			// a leaf right node
			if (curnode->parent && curnode == curnode->parent->rchild) {// way up until it's a left node or root node
				curnode = curnode->parent;
				doingRightNodeBacktrack = true;
				hasRightNodeBacktrack = true;
			}
			else {
				doingRightNodeBacktrack = false;
			}
		}
	}
	if (curnode == nodehead) {
		break;
	}
	if (hasRightNodeBacktrack) {
		if (curnode->parent->rchild)
			curnode = curnode->parent->rchild;
	}
}

That’s all~ Have a nice day~ :)