本文只是为了对二叉查找树的递归和非递归方式进行总结,便于以后查看,也希望得到其他朋友的批评指正。
代码实现用了c++,需要指出的是,由于本文重点在于而叉树遍历,所以没有自己实现队列和栈的结构,在算法中的队列和栈结构是引用其他博文的内容,说明如下:
队列MyQueue引自:http://blog.csdn.net/yushuai007008/article/details/7096726
代码如下:
template
struct NODE {
NODE* next;
T data;
};
template
class MyQueue {
public:
MyQueue() {
NODE* p = new NODE;
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* p = new NODE;
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* 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* 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* p = front;
while (p != rear) {
p = p->next;
count++;
}
return count;
}
//判断队列是否为空
bool empty() {
if (front == rear) {
return true;
} else {
return false;
}
}
private:
NODE* front; //指向头结点的指针。 front->next->data是队头第一个元素。
NODE* rear; //指向队尾(最后添加的一个元素)的指针
};
代码如下:
template
class Stack;
template
class Node {
T data;
Node *next;
public:
Node() {
}
Node(T d) {
data = d;
next = NULL;
}
friend class Stack ;
};
template
class Stack {
Node *top;
public:
Stack() {
top = NULL;
}
~Stack() {
if (top != NULL) {
Node *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 *p = new Node(e);
if (top != NULL)
p->next = top;
top = p;
}
bool Pop(T &e) {
Node *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
#include
#include
#include
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 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 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 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 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;
}