二叉树经常会在笔试和面试中遇到,因此,有必要对二叉树的一些常见操作进行一下系统的学习。
二叉树的定义就不说了,数据结构里有,这里给出我自己写的一部分代码。
当然,代码还相当不完善。以后将代码改进成类的形式,并用上模板。
有位高手就写出了完善的代码:http://www.zhuxinquan.com/archives/2006/01/notes_of_introduction_to_algorithmbinary_search_tree.html
假设我们的二叉树如以下形式:
5
/ /
6 7
/ / / /
2 3 1 4
/
0
一般情况下,我们要对该二叉树进行的常操作有:
创建,各种形式的遍历,求深度,是否是平衡的二叉树,当然,还有插入,删除等。我这里只有前面的一些操作。待完善。。。
简单说明创建操作:我们通过输入一些整数来充当结点的值,当输入为-1时,该结点不会被创建
// 创建二叉树 输入顺序:5, 6, 2, 0, -1, -1, -1, 3, -1, -1, 7, 1, -1, -1, 4, -1, -1
// 5
// / /
// 6 7
// / / / /
// 2 3 1 4
// / /
// 0 (-1)
// / /
// (-1) (-1)
//
// 其中-1的结点实际上是没有被创建的,这里为了方便说明。(结点1和结点4没有画出-1的形式)
// 当左结点的值为-1时,停止创建该结点,返回上一层。准备进行其父结点的右子树的创建。
// 当右结点的值为-1时,停止创建该结点,返回上一层。其父结点的树的成功。
// 由于父结点已被创建成功,则开始进行爷爷结点的右子树的创建。
// 递归进行。
代码:
头文件:BTree.h
#include <tchar.h> #include <assert.h> #include <vector> #include <map> #include <list> #include <stack> #include <math.h> #include <iostream> using namespace std; typedef struct _BTreeNode { int m_nData; _BTreeNode* pLChild; _BTreeNode* pRChild; _BTreeNode() { m_nData = 0; pLChild = NULL; pRChild = NULL; } } BTREENODE_t, *LPBTREENODE; // 通过从控制台输入数据来创建树 void CreateBTree(LPBTREENODE* ppRoot); // 通过整数vector来创建树 void CreateBTree(LPBTREENODE* ppRoot, vector<int>& vecCreateData, int nCurrentIndex); // 删除树 void DeleteBTree(LPBTREENODE lpRoot); // 访问某个结点 void VisitNode(LPBTREENODE lpNode); // 递归先序遍历 void PreOrderTraverse_Recursion(LPBTREENODE lpRoot); // 非递归先序遍历 void PreOrderTraverse_NonRecursion(LPBTREENODE lpRoot); // 递归中序遍历 void InOrderTraverse_Recursion(LPBTREENODE lpRoot); // 非递归中序遍历 void InOrderTraverse_NonRecursion(LPBTREENODE lpRoot); // 递归后序遍历 void PostOrderTraverse_Recursion(LPBTREENODE lpRoot); // 非递归后序遍历 void PostOrderTraverse_NonRecursion(LPBTREENODE lpRoot); // 非递按层遍历 void LayerTraverse(LPBTREENODE lpRoot); // 二叉树的深度 int Depth(LPBTREENODE lpRoot); // 是否是平衡二叉树 bool IsBalanceBTree(LPBTREENODE lpRoot);
CPP文件:BTree.cpp
#include "BTree.h" void CreateBTree(LPBTREENODE* ppRoot) { int nData = 0; cout << "请输入数字(-1表示该结点不被创建): "; cin >> nData; if (-1 == nData) { return; } LPBTREENODE lpNode = NULL; lpNode = new BTREENODE_t; lpNode->m_nData = nData; *ppRoot = lpNode; CreateBTree( &((*ppRoot)->pLChild) ); CreateBTree( &((*ppRoot)->pRChild) ); return; } void CreateBTree(LPBTREENODE* ppRoot, vector<int>& vecCreateData, int nCurrentIndex) { //assert( nCurrentIndex < vecCreateData.size() ); static int s_nCurIx = nCurrentIndex; if ( nCurrentIndex >= vecCreateData.size() || -1 == vecCreateData.at(nCurrentIndex) ) { s_nCurIx++; return; } LPBTREENODE lpNode = NULL; lpNode = new BTREENODE_t; lpNode->m_nData = vecCreateData.at(nCurrentIndex); *ppRoot = lpNode; s_nCurIx++; CreateBTree( &((*ppRoot)->pLChild), vecCreateData, s_nCurIx/*nCurrentIndex + 1*/ ); CreateBTree( &((*ppRoot)->pRChild), vecCreateData, s_nCurIx/*nCurrentIndex + 1*/ ); return; } void DeleteBTree(LPBTREENODE lpRoot) { if (NULL == lpRoot) { return; } if (NULL == lpRoot->pLChild && NULL == lpRoot->pRChild) { delete lpRoot; lpRoot = NULL; return; } DeleteBTree(lpRoot->pLChild); lpRoot->pLChild = NULL; // 子结点虽然被delete掉了,但是父结点还没将其指针设置为NULL DeleteBTree(lpRoot->pRChild); lpRoot->pRChild = NULL; // 子结点虽然被delete掉了,但是父结点还没将其指针设置为NULL } void VisitNode(LPBTREENODE lpNode) { if (lpNode != NULL) { cout << lpNode->m_nData << " "; } } void PreOrderTraverse_Recursion(LPBTREENODE lpRoot) { if (NULL == lpRoot) { return; } VisitNode(lpRoot); PreOrderTraverse_Recursion(lpRoot->pLChild); PreOrderTraverse_Recursion(lpRoot->pRChild); } void PreOrderTraverse_NonRecursion(LPBTREENODE lpRoot) { if (NULL == lpRoot) { return; } stack<LPBTREENODE> tempStack; LPBTREENODE lpNode = lpRoot; while ( lpNode != NULL || !tempStack.empty() ) { if (lpNode != NULL) { // 向左走,进栈,访问“根”结点,一直走到左子树的尽头 VisitNode(lpNode); tempStack.push(lpNode); lpNode = lpNode->pLChild; } else { // 退栈,准备遍历右子树(主要在于找到下一次循环遍历的“根”结点) lpNode = tempStack.top(); tempStack.pop(); if (lpNode != NULL) { lpNode = lpNode->pRChild; } } } } void InOrderTraverse_Recursion(LPBTREENODE lpRoot) { if (NULL == lpRoot) { return; } InOrderTraverse_Recursion(lpRoot->pLChild); VisitNode(lpRoot); InOrderTraverse_Recursion(lpRoot->pRChild); } void InOrderTraverse_NonRecursion(LPBTREENODE lpRoot) { if (NULL == lpRoot) { return; } stack<LPBTREENODE> tempStack; LPBTREENODE lpNode = lpRoot; while ( lpNode != NULL || !tempStack.empty() ) { if (lpNode != NULL) { // 向左走,一直走到左子树的尽头 tempStack.push(lpNode); lpNode = lpNode->pLChild; } else { // 访问结点,退栈,准备遍历右子树 lpNode = tempStack.top(); tempStack.pop(); if (lpNode != NULL) { VisitNode(lpNode); lpNode = lpNode->pRChild; } } } } void PostOrderTraverse_Recursion(LPBTREENODE lpRoot) { if (NULL == lpRoot) { return; } PostOrderTraverse_Recursion(lpRoot->pLChild); PostOrderTraverse_Recursion(lpRoot->pRChild); VisitNode(lpRoot); } void PostOrderTraverse_NonRecursion(LPBTREENODE lpRoot) { if (NULL == lpRoot) { return; } stack<LPBTREENODE> tempStack; LPBTREENODE lpNode = lpRoot; LPBTREENODE lpLastVisitNode = NULL; while ( lpNode != NULL || !tempStack.empty() ) { // 向左走,进栈,访问“根”结点,一直走到左子树的尽头 while (lpNode != NULL) { tempStack.push(lpNode); lpNode = lpNode->pLChild; } lpNode = tempStack.top(); // 如果lpNode没有右孩子或者其右孩子已经被访问过 if (NULL == lpNode->pRChild || lpNode->pRChild == lpLastVisitNode) { VisitNode(lpNode); tempStack.pop(); lpLastVisitNode = lpNode; lpNode = NULL; } else { lpNode = lpNode->pRChild; } } } void LayerTraverse(LPBTREENODE lpRoot) { if (NULL == lpRoot) { return; } vector<LPBTREENODE> vecParent; vector<LPBTREENODE> vecChild; int nSizeParent = 0; int nSizeChild = 0; vecParent.push_back(lpRoot); while (vecParent.size() > 0) { nSizeParent = vecParent.size(); for (int nIx = 0; nIx < nSizeParent; ++nIx) { VisitNode( vecParent.at(nIx) ); if (vecParent.at(nIx)->pLChild != NULL) { vecChild.push_back(vecParent.at(nIx)->pLChild); } if (vecParent.at(nIx)->pRChild != NULL) { vecChild.push_back(vecParent.at(nIx)->pRChild); } } vecParent.clear(); nSizeChild = vecChild.size(); for (int nIx = 0; nIx < nSizeChild; ++nIx) { vecParent.push_back(vecChild.at(nIx)); } vecChild.clear(); } } int Depth(LPBTREENODE lpRoot) { if (NULL == lpRoot) { return 0; } int nLDepth = Depth(lpRoot->pLChild); int nRDepth = Depth(lpRoot->pRChild); return 1 + (nLDepth > nRDepth ? nLDepth : nRDepth); } bool IsBalanceBTree(LPBTREENODE lpRoot) { if (NULL == lpRoot) { return true; } if (abs( Depth(lpRoot->pLChild) - Depth(lpRoot->pRChild) ) > 1) { return false; } return true; }
测试程序:
#include "BTree.h" void _tmain() { // 创建二叉树 输入顺序:5, 6, 2, 0, -1, -1, -1, 3, -1, -1, 7, 1, -1, -1, 4, -1, -1 // 5 // / / // 6 7 // / / / / // 2 3 1 4 // / / // 0 (-1) // / / // (-1) (-1) // // 其中-1的结点实际上是没有被创建的,这里为了方便说明。 // 当左结点的值为-1时,停止创建该结点,返回上一层。准备进行其父结点的右子树的创建。 // 当右结点的值为-1时,停止创建该结点,返回上一层。其父结点的树的成功。 // 由于父结点已被创建成功,则开始进行爷爷结点的右子树的创建。 // 递归进行。 LPBTREENODE lpRoot = NULL; //CreateBTree(&lpRoot); // 创建方式一 vector<int> vecData; vecData.push_back(5); vecData.push_back(6); vecData.push_back(2); vecData.push_back(0); vecData.push_back(-1); vecData.push_back(-1); vecData.push_back(-1); vecData.push_back(3); vecData.push_back(-1); vecData.push_back(-1); vecData.push_back(7); vecData.push_back(1); vecData.push_back(-1); vecData.push_back(-1); vecData.push_back(4); vecData.push_back(-1); vecData.push_back(-1); CreateBTree(&lpRoot, vecData, 0); // 创建方式二 cout << "递归先序遍历:/t/t"; PreOrderTraverse_Recursion(lpRoot); cout << endl << "递归中序遍历:/t/t"; InOrderTraverse_Recursion(lpRoot); cout << endl << "递归后序遍历:/t/t"; PostOrderTraverse_Recursion(lpRoot); cout << endl; cout << "非递归先序遍历:/t"; PreOrderTraverse_NonRecursion(lpRoot); cout << endl << "非递归中序遍历:/t"; InOrderTraverse_NonRecursion(lpRoot); cout << endl << "非递归后序遍历:/t"; PostOrderTraverse_Recursion(lpRoot); cout << endl << "非递按层遍历:/t/t"; LayerTraverse(lpRoot); cout << endl; cout << "二叉树的深度:/t/t" << Depth(lpRoot) << endl; cout << "是否是平衡二叉树:/t" << (IsBalanceBTree(lpRoot) ? "true" : "false") << endl; DeleteBTree(lpRoot); }