二叉查找树递归遍历与非递归遍历

本文只是为了对二叉查找树的递归和非递归方式进行总结,便于以后查看,也希望得到其他朋友的批评指正。

代码实现用了c++,需要指出的是,由于本文重点在于而叉树遍历,所以没有自己实现队列和栈的结构,在算法中的队列和栈结构是引用其他博文的内容,说明如下:

队列MyQueue引自:http://blog.csdn.net/yushuai007008/article/details/7096726

代码如下:

template<class T>
struct NODE {
	NODE<T>* next;
	T data;
};

template<class T>
class MyQueue {
public:
	MyQueue() {
		NODE<T>* p = new NODE<T>;
		if (NULL == p) {
			cout << "Failed to malloc the node." << endl;
		}
		p->data = NULL;
		p->next = NULL;
		front = p;
		rear = p;
	}

//在队尾入队
	void push(T e) {
		NODE<T>* p = new NODE<T>;
		if (NULL == p) {
			cout << "Failed to malloc the node." << endl;
		}
		p->data = e;
		p->next = NULL;
		rear->next = p;
		rear = p;
	}

//在队头出队
	T pop() {
		T e;

		if (front == rear) {
			cout << "The queue is empty." << endl;
			return NULL;
		} else {
			NODE<T>* p = front->next;
			front->next = p->next;
			e = p->data;
			//注意判断当只有一个元素,且删除它之后,rear指向的node被删除
			//应将其指向头结点
			if (rear == p) {
				rear = front;
			}
			delete p;
			p = NULL;
			return e;
		}
	}

	//取得队头元素
	T front_element() {
		if (front == rear) {
			cout << "The queue is empty." << endl;
			return NULL;
		} else {
			NODE<T>* p = front->next;
			return p->data;
		}
	}

	T back_element() {
		if (front == rear) {
			cout << "The queue is empty." << endl;
			return NULL;
		} else {
			return rear->data;
		}
	}

	//取得队列元素个数
	int size() {
		int count(0);

		NODE<T>* p = front;

		while (p != rear) {
			p = p->next;
			count++;
		}
		return count;
	}

	//判断队列是否为空
	bool empty() {
		if (front == rear) {
			return true;
		} else {
			return false;
		}
	}

private:
	NODE<T>* front; //指向头结点的指针。 front->next->data是队头第一个元素。
	NODE<T>* rear; //指向队尾(最后添加的一个元素)的指针
};

栈结构Stack引自:http://hi.baidu.com/keflying/item/b29269156c3fdd48e65e06e6

代码如下:

template<class T>
class Stack;
template<class T>
class Node {
	T data;
	Node *next;
public:
	Node() {
	}
	Node(T d) {
		data = d;
		next = NULL;
	}
	friend class Stack<T> ;
};
template<class T>
class Stack {
	Node<T> *top;
public:
	Stack() {
		top = NULL;
	}
	~Stack() {
		if (top != NULL) {
			Node<T> *p = top, *q;
			while (p != NULL) {
				q = p->next;
				delete p;
				p = q;
			}
			delete q;
		}
	}
	bool StackEmpty() {
		return top == NULL;
	}
	void Push(T e) {
		Node<T> *p = new Node<T>(e);
		if (top != NULL)
			p->next = top;
		top = p;
	}
	bool Pop(T &e) {
		Node<T> *p;
		if (top == NULL)
			return false;
		p = top;
		e = p->data;
		if (p != NULL)
			top = p->next;
		delete p;
		return true;
	}
	bool GetTop(T &e) {
		if (top == NULL)
			return false;
		e = top->data;
		return true;
	}
};

二叉查找树的遍历实现代码如下:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <cmath>
using namespace std;

/*
 * 二叉查找树
 */

class BSTNode {
public:
	int val;
	BSTNode *lchild;
	BSTNode *rchild;

	BSTNode(int v) {
		val = v;
		lchild = NULL;
		rchild = NULL;
	}
};

class BST {
private:
	BSTNode *root;

public:
	BST() {
		root = NULL;
	}

	BSTNode *get() {
		return root;
	}

	/*
	 * 创建二叉查找树
	 */
	void CreateBST() {
		int input;
		BSTNode *p;
		cout << "entry the node value: " << endl;
		cin >> input;
		while (input >= 0) {
			if (root == NULL) {
				BSTNode *tmp = new BSTNode(input);
				root = tmp;
			} else {
				p = root;
				if (input == p->val) {
					cout << "repeated node value is not allowed! Please entry:"
							<< endl;
					cin >> input;
					continue;
				}
				while (p != NULL) {
					if (input < p->val) {
						if (p->lchild == NULL) {
							BSTNode *tmp = new BSTNode(input);
							p->lchild = tmp;
							break;
						} else
							p = p->lchild;
					} else {
						if (p->rchild == NULL) {
							BSTNode *tmp = new BSTNode(input);
							p->rchild = tmp;
							break;
						} else
							p = p->rchild;
					}
				}
			}

			cin >> input;
		}
		cout << "creating bst finished!" << endl;
	}

	/*
	 * 借助队列广度优先遍历二叉树
	 */
	void PrintBST() {
		MyQueue<BSTNode *> queue;
		queue.push(root);
		while (!queue.empty()) {
			BSTNode *tmp = queue.pop();
			cout << tmp->val << endl;
			if (tmp->lchild != NULL)
				queue.push(tmp->lchild);
			if (tmp->rchild != NULL)
				queue.push(tmp->rchild);
		}
	}

	/*
	 * 前序递归遍历
	 */
	void PreOrderRecursion(void *node) {
		BSTNode *p = (BSTNode *) node;
		if (node == NULL)
			return;
		cout << p->val << endl;
		if (p->lchild != NULL)
			PreOrderRecursion(p->lchild);
		if (p->rchild != NULL)
			PreOrderRecursion(p->rchild);
	}

	/*
	 * 前序非递归遍历
	 */
	void PreOrderNonRecursion() {
		Stack<BSTNode *> stack;
		if (root == NULL)
			return;
		stack.Push(root);
		BSTNode *tmp;
		while (!stack.StackEmpty()) {
			stack.Pop(tmp);
			cout << tmp->val << endl;
			if (tmp->rchild != NULL)
				stack.Push(tmp->rchild);
			if (tmp->lchild != NULL)
				stack.Push(tmp->lchild);
		}
	}

	/*
	 * 中序递归遍历
	 */
	void InOrderRecursion(void *node) {
		if (node == NULL)
			return;
		BSTNode *p = (BSTNode *) node;
		if (p->lchild != NULL)
			InOrderRecursion(p->lchild);
		cout << p->val << endl;
		if (p->rchild != NULL)
			InOrderRecursion(p->rchild);
	}

	/*
	 * 中序非递归遍历
	 */
	void InOrderNonRecursion() {
		Stack<BSTNode *> stack;
		BSTNode *tmp;
		tmp = root;
		while (tmp != NULL || !stack.StackEmpty()) {
			if (tmp != NULL) {
				stack.Push(tmp);
				tmp = tmp->lchild;
				continue;
			}
			//reach the leftmost node, then pop the stack
			if (!stack.StackEmpty()) {
				stack.Pop(tmp);
				cout << tmp->val << endl;
				tmp = tmp->rchild;
			}
		}
	}

	/*
	 * 后续递归遍历
	 */
	void PostOrderRecursion(void *node) {
		if (node == NULL)
			return;
		BSTNode *tmp = (BSTNode *) node;
		if (tmp->lchild != NULL)
			PostOrderRecursion(tmp->lchild);
		if (tmp->rchild != NULL)
			PostOrderRecursion(tmp->rchild);
		cout << tmp->val << endl;
	}

	/*
	 * 非递归后续遍历:难度比前序和中序大,因为每个节点在第一次访问是得用GetTop,而不能用Pop出栈;在第二次访问的时候才能用Pop
	 *         思路一:在node中增加是否为第一次访问的标记,缺点是得改变node结构;
	 *         思路二:增加一个pre指针,判断上次访问的是否为自己的左孩子或者右孩子。
	 */
	void PostOrderNonRecursion() {
		if (root == NULL)
			return;
		Stack<BSTNode *> stack;
		stack.Push(root);
		BSTNode *tmp, *pre = NULL;
		while (!stack.StackEmpty()) {
			stack.GetTop(tmp);     //get the top element, but not pop
			if ((tmp->rchild == NULL && tmp->lchild == NULL)
					|| (pre != NULL
							&& (pre == tmp->lchild || pre == tmp->rchild))) {
				cout << tmp->val << endl;
				stack.Pop(tmp);           //pop the top element
				pre = tmp;
				continue;
			}
			if (tmp->rchild != NULL)
				stack.Push(tmp->rchild);
			if (tmp->lchild != NULL)
				stack.Push(tmp->lchild);
		}
	}

};

int main() {
	BST bst;
	bst.CreateBST();
	bst.PrintBST();

	cout << "preorder scan the bst:" << endl;
	bst.PreOrderRecursion(bst.get());

	cout << "nonrecursion preorder scan the bst:" << endl;
	bst.PreOrderNonRecursion();

	cout << "inorder scan the bst:" << endl;
	bst.InOrderRecursion(bst.get());

	cout << "nonrecursion inorder scan the bst:" << endl;
	bst.InOrderNonRecursion();

	cout << "postorder scan the bst:" << endl;
	bst.PostOrderRecursion(bst.get());

	cout << "nonrecursion postorder scan the bst:" << endl;
	bst.PostOrderNonRecursion();

	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值