您的位置:首页 > 编程语言 > C语言/C++

C++实现二叉树 前序遍历, 后序遍历, 中序遍历, 层序遍历(不用递归)

2011-03-20 21:41 861 查看
/*
完成MyTree

非递归的PreOrder,MidOrder,AftOrder,LayerOrder
*/

#include <iostream.h>
#include <assert.h>

#define OUT

//////////////////////////////////////////////////////////////////////////
//       栈     //////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
template <class T> class Stack;
template <class T>
class StackNode
{
T data;
StackNode * pNext;

friend class Stack<T>;
};

template <class T>
class Stack
{
private:
StackNode<T> * m_lpTmp;
StackNode<T> * m_lpTop;

int m_nCount;

public:
Stack()
{
m_nCount = 0;
m_lpTop = m_lpTmp = NULL;
}

private:
Stack(const Stack<T> &);

Stack & operator = (const Stack<T> &);

public:
// 清空栈
bool ClearStack();

// 栈中元素个数(0 代表空)
int GetLength() const;

// 入栈
bool Push(const T &);

// 出栈
bool Pop(OUT T &);

// 获得栈顶元素
bool GetTop(OUT T &);
};
//////////////////////////////////////
// 栈成员函数 实现
// 清空栈
template <class T>
bool Stack<T>::ClearStack()
{
assert(m_nCount >= 0);

if (m_nCount == 0)
{
return true;
}

while (m_nCount > 0)
{
m_lpTmp = m_lpTop->pNext;
delete m_lpTop;
m_lpTop = m_lpTmp->pNext;
}

// 如果在栈空间的释放中, 检查到栈结构没有问题, 就返回true
if (0 == m_nCount && m_lpTop == NULL)
{
return true;
}

// 如果链表结构异常 返货 false
m_lpTop = m_lpTmp = NULL;
m_nCount = 0;
return false;
}

// 返回栈中元素个数(0 代表空)
template <class T>
int Stack<T>::GetLength() const
{
return m_nCount;
}

// 入栈
template <class T>
bool Stack<T>::Push(const T & data)
{
m_lpTmp = new StackNode<T>;
if (m_lpTmp == NULL)
{
return false;
}

m_lpTmp->data = data;
m_lpTmp->pNext = m_lpTop;
m_lpTop = m_lpTmp;
m_nCount++;

return true;
}

// 出栈
template <class T>
bool Stack<T>::Pop(OUT T & data)
{
if (m_nCount == 0)
{
return false;
}

m_lpTmp = m_lpTop->pNext;
data = m_lpTop->data;
delete m_lpTop;
m_lpTop = m_lpTmp;
m_nCount--;

return true;
}

// 获得栈顶元素
template <class T>
bool Stack<T>::GetTop(OUT T & data)
{
if (m_nCount == 0)
{
return false;
}

data = m_lpTop->data;
return false;
}

////////////////////////////////////////////////////////////////////////
//   队列     /////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

template <class T> class Queue;
template <class T>
class QueNode
{
T data;
QueNode * pNext;

friend class Queue<T>;
};

template <class T>
class Queue
{
private:
QueNode<T> * m_lpFront; //队头
QueNode<T> * m_lpTail;  // 队尾
int m_nCount;     // 统计队列中结点个数

private:
Queue<T> & operator = (Queue<T> &);
Queue(Queue<T> &);

public:
Queue():m_lpFront(NULL), m_lpTail(NULL),m_nCount(0){}
~Queue()
{
ClearQue();
}

public:
// 入队
bool EnQue(const T& data);

// 出队
bool ExitQue(OUT T& data);

// 获取队列长度
int GetLenth()
{
return m_nCount;
}

// 获取队头结点, 而不出站
bool GetFront(OUT T& data)
{
if (m_lpFront != NULL)
{
data = m_lpFront->data;

return true;
}

return false;
}

// 清空队列
void ClearQue()
{
// 将队尾指针当做辅助指针, 一次删除每一个结点
while(m_lpFront)
{
m_lpTail = m_lpFront->pNext;
delete m_lpFront;
m_lpFront = m_lpTail;

m_nCount--;
}

assert(m_nCount == 0);
assert(m_lpFront == NULL && m_lpTail == NULL);
}
};

/////////////////////////////////////
// 队列成员函数的实现
// 入队
template <typename T>
bool Queue<T>::EnQue(const T& data)
{
assert(m_nCount >= 0);

// 如果入队的是第一个结点, 则它既是头结点,也是尾结点
if (m_nCount == 0)
{
m_lpFront = m_lpTail = new QueNode<T>;

// 如果新结点内存分配失败
if (m_lpTail == NULL)
{
m_lpTail = m_lpFront = NULL;
m_nCount = 0;

return false;
}

// 第一个结点成功入队
m_lpTail->pNext = NULL;
m_lpTail->data = data;

m_nCount++;

return true;
}

// 如果不是第一个入队的结点, 则将其插入队尾
m_lpTail->pNext = new QueNode<T>;
if (m_lpTail->pNext == NULL)
{
return false;
}

m_lpTail = m_lpTail->pNext;

m_lpTail->pNext = NULL;
m_lpTail->data = data;

m_nCount++;

return true;
}

// 出队
template <typename T>
bool Queue<T>::ExitQue(OUT T& data)
{
assert(m_nCount >= 0);

if (m_nCount == 0)
{
return false;
}

QueNode<T> * lpTmp = m_lpFront->pNext;

data = m_lpFront->data;
delete m_lpFront;
m_lpFront = lpTmp;

m_nCount--;

// 当最后一个结点也出队时, 小心! 记住要做如下操作!
if (m_nCount == 0)
{
m_lpTail = NULL;
}
return true;

}

///////////////////////////////////////////////////////////////////////
//   二叉树    ////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

// 二叉树结点类
template <typename T>
struct TreeNode
{
T data;
TreeNode * lpLChild;
TreeNode * lpRChild;

int m_nHeight;
};

// 二叉树类
template <typename T>
class BinaryTree
{
private:
TreeNode<T> *m_lpRoot;
int m_nHeight;

private:
BinaryTree(const BinaryTree<T> &);
BinaryTree & operator = (BinaryTree &);

public:
BinaryTree():m_lpRoot(NULL), m_nHeight(0){}

public:
// 增加一个结点(做lpInsertNode 的子树)
TreeNode<T> *  AddNode(const T& data, TreeNode<T> * lpInsertNode);

// 删除一个子树 (默认参表示清空树)
bool DelSubTree(const TreeNode<T> * lpNode = m_lpRoot);

// ...
typedef void (BinaryTree<T>::*funPtr)( TreeNode<T>* lpCurNode );

// 显示树
void PrintNode( TreeNode<T>* lpCurNode )
{
cout << "结点数据为: " << lpCurNode->data << '/t' << "所在层为:" << lpCurNode->m_nHeight << endl;
}

//////////////////////////////////////////////////////////////////////
// 非递归的实现树的四种遍历: PreOrder,MidOrder,AftOrder,LayerOrder  //
//////////////////////////////////////////////////////////////////////
// 先序遍历
void PreOrder(TreeNode<T> * lpCurNode , funPtr = PrintNode);

// 中序遍历
void MidOrder(TreeNode<T> * lpCurNode , funPtr = PrintNode);

// 后续遍历
void AftOrder(TreeNode<T> * lpCurNode , funPtr = PrintNode);

// 层序遍历
void LayerOrder(TreeNode<T> * lpCurNode , funPtr = PrintNode);
};

////////////////////////////////////
// 二叉树 成员函数实现

// 增加一个结点(做lpInsertNode 的子树)
// 如果插入成功, 返回新结点的指针, 如果失败, 则返回NULL
template <typename T>
TreeNode<T> *  BinaryTree<T>::AddNode(const T& data, TreeNode<T> * lpInsertNode)
{
TreeNode<T> * lpTmpNode = NULL;

// 如果 是向空树中插入新结点
if (m_lpRoot == NULL)
{
// 如果插入为之合法(即选择在根结点插入数据)
if (lpInsertNode == NULL)
{

lpTmpNode = new TreeNode<T>;
lpTmpNode->data = data;
lpTmpNode->lpLChild = NULL;
lpTmpNode->lpRChild = NULL;
lpTmpNode->m_nHeight = 1;

m_lpRoot = lpTmpNode;
m_nHeight = 1;

// 返回新插入结点的指针
return m_lpRoot;
}
// 如果选择的插入位置非法, 返回NULL
else return NULL;
}

// 以下判定 树非空的情况下 插入新结点 是否合法.
// 如果选择的插入位置合法, 则插入值, 否则返回为NULL, 不执行任何操作.

// 如果 选择的结点为空
else if (lpInsertNode == NULL)
{
return NULL;
}

// 优先检索 lpInsertNode左子树, 然后检索右子树, 找到可以插入新结点的位置.
// 如果左右子树都满了, 则返回假值
else if (lpInsertNode->lpLChild == NULL)
{
lpTmpNode = new TreeNode<T>;
lpTmpNode->data = data;
lpTmpNode->lpLChild = NULL;
lpTmpNode->lpRChild = NULL;
lpTmpNode->m_nHeight = lpInsertNode->m_nHeight+1;

lpInsertNode->lpLChild = lpTmpNode;
}
else if (lpInsertNode->lpRChild == NULL)
{
lpTmpNode = new TreeNode<T>;
lpTmpNode->data = data;
lpTmpNode->lpLChild = NULL;
lpTmpNode->lpRChild = NULL;
lpTmpNode->m_nHeight = lpInsertNode->m_nHeight+1;

lpInsertNode->lpRChild = lpTmpNode;
}
// 插入位置非法的一种情况( 选择的结点 左右孩子 都非空, 无法完成插入操作)
else
{
// 插入失败, 返回NULL
return NULL;
}

// 更新数的层数
if (lpTmpNode->m_nHeight > this->m_nHeight)
{
this->m_nHeight = lpTmpNode->m_nHeight;
}
// 返回 新插入结点的指针
return lpTmpNode;

}

// 删除一个子树 (默认参表示清空树)
template <typename T>
bool BinaryTree<T>::DelSubTree(const TreeNode<T> * lpNode)
{
return false;
}

// 先序遍历
template <typename T>
void BinaryTree<T>::PreOrder(TreeNode<T> * lpCurNode, funPtr fun)
{
if (fun == NULL)
{
return ;
}

Stack<TreeNode<T> * > s;

if (lpCurNode == NULL)
{
return ;
}

do
{
// 访问根结点
(this->*fun)(lpCurNode);

// 右子树入栈
if (lpCurNode->lpRChild != NULL)
{
s.Push(lpCurNode->lpRChild);
}

//左子树入栈
if (lpCurNode->lpLChild != NULL)
{
s.Push(lpCurNode->lpLChild);
}

} while (s.Pop(lpCurNode));
}

// 中序遍历
template <typename T>
void BinaryTree<T>::MidOrder(TreeNode<T> * lpCurNode, funPtr fun)
{
if (fun == NULL)
{
return ;
}

Stack< TreeNode<T> * > stack;

while (true)
{
// 一直走到最左下角的叶子节点
while (lpCurNode != NULL)
{
stack.Push(lpCurNode);
lpCurNode = lpCurNode->lpLChild;
}

// 出栈, 解决问题
if (stack.Pop(lpCurNode) == false)
{
//如果栈为空, 则问题得到完全解决.
return;
}

(this->*fun)(lpCurNode);
lpCurNode = lpCurNode->lpRChild;
}

}
// 后续遍历
template <typename T>
void BinaryTree<T>::AftOrder(TreeNode<T> * lpCurNode, funPtr fun)
{
if (fun == NULL)
{
return ;
}

Stack< TreeNode<T> * > stack;
TreeNode<T> * lpFlagNode = NULL;

while (true)
{
while (lpCurNode != NULL)
{
stack.Push(lpCurNode);
lpCurNode = lpCurNode->lpLChild;
}

// 出栈, 解决问题
if (stack.Pop(lpCurNode) == false)
{
//如果栈为空, 则问题得到完全解决.
return;
}

if (lpCurNode->lpRChild == lpFlagNode
|| lpCurNode->lpRChild == NULL)
{
(this->*fun)(lpCurNode);
lpFlagNode = lpCurNode;

lpCurNode = NULL;
}
else
{
stack.Push(lpCurNode);
lpCurNode = lpCurNode->lpRChild;
}
}

}

// 层序遍历
template <typename T>
void BinaryTree<T>::LayerOrder(TreeNode<T> * lpCurNode, funPtr fun)
{
if (fun == NULL)
{
return ;
}

Queue < TreeNode<T> * > que;
que.EnQue(lpCurNode);
while( que.ExitQue(lpCurNode) )
{
(this->*fun)(lpCurNode);
if (lpCurNode->lpLChild != NULL)
{
que.EnQue(lpCurNode->lpLChild);
}

if (lpCurNode->lpRChild != NULL)
{
que.EnQue(lpCurNode->lpRChild);
}
}

}

//////////////////////////////////////////////////////////////////////////
//   测试     ////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

void main()
{
BinaryTree<int> bt;

// 向树种插入数据
//      1
//   2     5
//  3 4  6
TreeNode<int> * Tmp1 = NULL, *Tmp2 = NULL;

Tmp1 = bt.AddNode(1, NULL);

Tmp2 = bt.AddNode(2, Tmp1);
bt.AddNode(3, Tmp2);
bt.AddNode(4, Tmp2);

Tmp2 = bt.AddNode(5, Tmp1);
bt.AddNode(6, Tmp2);

cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl;
cout << "先序遍历:" << endl;
bt.PreOrder(Tmp1);

cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl;
cout << "中序遍历:" << endl;
bt.MidOrder(Tmp1);

cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl;
cout << "后序遍历:" << endl;
bt.AftOrder(Tmp1);

cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl;
cout << "层序遍历:" << endl;
bt.LayerOrder(Tmp1);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐