您的位置:首页 > 理论基础 > 数据结构算法

数据结构:二叉树的递归实现

2017-12-26 19:10 295 查看

一,概念

二叉树就是一颗特殊的树,二叉树每个结点最多有两个孩子结点,即就是左孩子和右孩子。

接下来我们将以此树为例来进行分析!



表示

(1)数组表示

当二叉树的大小和形态不发生剧烈变化时,用一组连续的存储单元存储二叉树的数据元素,为反应各结点在二叉树中的位置及相互关系,须适当安排各结点的存储次序。

假若一个子结点的下标为i,那仫它的父节点的下标为:(i-1)/2;

假若一个父结点的下标为i,那仫它的左孩子的下标为:2*i+1,它的右孩子的下标为:2*i+2.

缺点:如果不是满二叉树和完全二叉树则有太多的内存浪费,且插入删除不便.

用数组表示一个树适用于满二叉树和完全二叉树.

(2)链式存储表示

在一棵树中进行插入和删除时,为反应结点层次的变动,可能需要移动许多节点,常用的是二叉链表,每一个结点至少包括数据data,左孩子leftchild和右孩子rightchild。

分类

(1)满二叉树:所有叶子节点在同一层,通俗点说就是每一层都是满的 (2)完全二叉树局:n-1层是满的

图示:



二,基本实现

(1)定义一个二叉树节点

template <class T>//定义一个二叉树节点
struct BinaryTreeNode
{
BinaryTreeNode<T>* _left;
BinaryTreeNode<T>* _right;
T _data;
BinaryTreeNode(const T& x)
:_left(NULL)
,_right(NULL)
,_data(x)
{}
};


(2)构造二叉树

BinaryTree()
:_root(NULL)
{}
BinaryTree(T* a,size_t n,const T& invalid)
{
size_t index = 0;
_root = CreateTree(a,n,invalid,index);
}
BinaryTree(const BinaryTree<T>& t)

{
_root = _Copy(t._root);
}

BinaryTree<T>& operator=(const BinaryTree<T> t)
{
if(this != %t)
{
swap(t._root,_root)
}
}


递归调用过程图:



(3)前序遍历

先访问根结点,再递归访问左子树,最后访问右子树

void _PrevOrder(Node* root)
{
if(root==NULL)
{
return;
}
cout<<root->_data<<" ";
_PrevOrder(root->_left);
_PrevOrder(root->_right);
}




(4)中序遍历

先访问左子树,再访问根结点,最后访问右子树.

void _InOrder(Node* root)
{
if(root==NULL)
{
return;
}
_InOrder(root->_left);
cout<<root->_data<<" ";
_InOrder(root->_right);
}




(5)后序遍历

先访问左子树,再访问右子树,最后访问根结点.

void _PosOrder(Node* root)
{
if(root==NULL)
{
return;
}
_PosOrder(root->_left);
_PosOrder(root->_right);
cout<<root->_data<<" ";
}




(6)层序遍历(广度优先遍历)

一层层结点依次遍历,在实现层序遍历的时候用到了队列先进先出的性质,将每一层的数据一次进队列,而每次出队列的元素就是层序遍历的当前元素.

void _LevelOrder (Node* root)
{
queue<Node*> q;
if(root!=NULL)
{
q.push(root);
while(!q.empty())
{
Node* front = q.front();
cout<<front->_data<<" "
4000
;
q.pop();
if(front->_left)
{
q.push(front->_left);
}
if(front->_right)
{
q.push(front->_right);
}

}
}
}


在这里用到了队列,先压入根节点,依据父节点出队列,子节点进队列原则,然后依次访问对头元素求得层序遍历顺序



(7)叶子节点个数

叶子节点(即没有左子树也没有右子树),左子树的叶子节点总数+右子树的叶子节点总数.

size_t _LeafSize(Node* root)
{
if(root==NULL)
{
return 0;
}
if(root->_left==NULL&&root->_right==NULL)
{
return 1;
}
size_t i = _LeafSize(root->_left);
size_t j = _LeafSize(root->_right);
return i+j;
}


(8)第k层节点数

size_t _GetKLevel(Node* root,size_t k)
{
if(root == NULL)
{
return 0;
}
if(k == 1)
{
return 1;
}
return _GetKLevel(root->_left,k-1)+(root->_right,k-1);
}


三,完整代码

using namespace std;
template <class T>//定义一个二叉树节点
struct BinaryTreeNode
{
BinaryTreeNode<T>* _left;
BinaryTreeNode<T>* _right;
T _data;
BinaryTreeNode(const T& x)
:_left(NULL)
,_right(NULL)
,_data(x)
{}
};

template <class T>
class BinaryTree
{
typedef BinaryTreeNode<T> Node;
public:
BinaryTree() :_root(NULL) {} BinaryTree(T* a,size_t n,const T& invalid) { size_t index = 0; _root = CreateTree(a,n,invalid,index); } BinaryTree(const BinaryTree<T>& t) { _root = _Copy(t._root); } BinaryTree<T>& operator=(const BinaryTree<T> t) { if(this != %t) { swap(t._root,_root) } }

void PrevOrder()//前序遍历
{
return _PrevOrder(_root);
}
void InOrder()//中序遍历
{
return _InOrder(_root);
}
void PosOrder()//后续遍历
{
return _PosOrder(_root);
}
void LevelOrder()//层序遍历
{
return _LevelOrder(_root);
}
size_t Size()//大小
{
return _Size(_root);
}
Node* find(const T&x)//查找一个节点
{
return _find(_root,x);
}
size_t Depth()//求深度
{
return _Depth(_root);
}
size_t LeafSize()
{
return _LeafSize(_root);
}
size_t GetKLevel(size_t k)
{
return _GetKLevel(_root,k);
}

protected:
//成员函数
Node* _find(Node* root,const T& x)
{
if(root==NULL)
{
return NULL;
}
if(root->_data == x)
{
return root;
}
Node* ret=_find(root->_left,x);
if(ret)
{
return ret;
}
return _find(root->_right,x);
}
size_t _LeafSize(Node* root) { if(root==NULL) { return 0; } if(root->_left==NULL&&root->_right==NULL) { return 1; } size_t i = _LeafSize(root->_left); size_t j = _LeafSize(root->_right); return i+j; }
size_t _GetKLevel(Node* root,size_t k) { if(root == NULL) { return 0; } if(k == 1) { return 1; } return _GetKLevel(root->_left,k-1)+(root->_right,k-1); }
size_t _Size(Node* root)
{
if(root==NULL)
{
return 0 ;
}
size_t i =_Size(root->_left);
size_t j =_Size(root->_right);
return i+j+1;
}
void _LevelOrder (Node* root)
{
queue<Node*> q;
if(root!=NULL)
{
q.push(root);
while(!q.empty())
{
Node* front = q.front();
cout<<front->_data<<" ";
q.pop();
if(front->_left)
{
q.push(front->_left);
}
if(front->_right)
{
q.push(front->_right);
}

}
}
}
size_t _Depth(Node* root)
{
if(root==NULL)
{
return 0;
}
else
{
size_t i = _Depth(root->_left);
size_t j = _Depth(root->_right);
if(i>j)
{
return i+1;
}
else
{
return j+1;
}

}
}

//前序遍历
void _PrevOrder(Node* root) { if(root==NULL) { return; } cout<<root->_data<<" "; _PrevOrder(root->_left); _PrevOrder(root->_right); }
//中序遍历
void _InOrder(Node* root) { if(root==NULL) { return; } _InOrder(root->_left); cout<<root->_data<<" "; _InOrder(root->_right); }
//后序遍历
void _PosOrder(Node* root) { if(root==NULL) { return; } _PosOrder(root->_left); _PosOrder(root->_right); cout<<root->_data<<" "; }
Node* _Copy(Node* root)
{
if(root==NULL)
{
return NULL;
}
Node* newroot = new Node(root->_data);
newroot->_left = _Copy(root->_left);
newroot->_right = _Copy(root->_right);
return newroot;
}
//构建二叉树
Node* CreateTree(T* a,size_t n,const T& invalid,size_t& index)
{
Node* root =NULL;
if(index < n && a[index] != invalid)
{
root = new Node(a[index]);
root ->_left = CreateTree(a,n,invalid,++index);
root ->_right = CreateTree(a,n,invalid,++index);
}
return root;
}

protected:
Node* _root;
size_t index;
size_t invalid;
};
int main()
{
int a1[10] = {1, 2, 3, '#', '#', 4, '#' , '#', 5, 6};
BinaryTree<int>t1(a1,sizeof(a1)/sizeof(a1[0]),'#');
//t1.PosOrder();
//cout<<endl;
//cout<<t1.Size()<<" ";
//cout<<t1.LeafSize();
//cout<<t1.GetKLevel(2);
t1.LevelOrder();
//cout<<(t1.find(3));
//cout<<t1.Depth();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二叉树-c 递归 遍历
相关文章推荐