二叉树的定义:
二叉树的非递归先序
二叉树的递归中序
递归后序遍历
前面三种非递归算法的实质就是用栈来模拟递归,入栈即递归,出栈即回溯。前序和中序都很好理解,关键是后序,后序遍历因为会回溯两次,所以必须新增一个字段 is-first,当第一次访问的时候置为1,第二次访问置为0,这样就可以判断出是否要输出
这一种方法虽然更好理解,但并不是模拟递归过程,它 把入栈顺序是 自己-右边-左边 从上到小没有儿子就输出。
求结点个数
树的同构
二叉搜索树的插入和删除
typedef char ElementType;
typedef struct BiTreeNode
{
ElementType data;
struct BiTreeNode* lchild;
struct BiTreeNode* rchild;
}BiTreeNode, *BiTree;
二叉树的创建:
//递归的建立一棵二叉树
//输入为二叉树的先序序列
void createBiTree(BiTree &T)
{
char data;
data = getchar();
if(data == '#')
{
T = NULL;
}
else
{
T = new BiTreeNode;
T->data = data;
createBiTree(T->lchild);
createBiTree(T->rchild);
}
}
void preOrder1(BinTree *root) //递归前序遍历
{
if(root!=NULL)
{
cout<<root->data<<" ";
preOrder1(root->lchild);
preOrder1(root->rchild);
}
}
二叉树的非递归先序
void preOrder2(BinTree *root) // 非递归前序遍历
{
stack<BinTree*> s;
BinTree *p=root;
while(p!=NULL||!s.empty())
{
while(p!=NULL)
{
cout<<p->data<<" ";
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
s.pop();
p=p->rchild;
}
}
} //不断向左访问 并输出 然后右边
二叉树的递归中序
void inOrder1(BinTree *root) //递归中序遍历
{
if(root!=NULL)
{
inOrder1(root->lchild);
cout<<root->data<<" ";
inOrder1(root->rchild);
}
}
void inOrder2(BinTree *root) // 非递归中序遍历
{
stack<BinTree*> s;
BinTree *p=root;
while(p!=NULL||!s.empty())
{
while(p!=NULL)
{
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
cout<<p->data<<" ";
s.pop();
p=p->rchild;
}
}
}
递归后序遍历
void postOrder1(BinTree *root) //递归后序遍历
{
if(root!=NULL)
{
postOrder1(root->lchild);
postOrder1(root->rchild);
cout<<root->data<<" ";
}
}
非递归后序遍历(一)
//非递归后序遍历-迭代
void postorderTraversal(TreeNode *root)
{
stack<TempNode *> s;
TreeNode *p = root;
TempNode *temp;
while(p != NULL || !s.empty())
{
while(p != NULL) //沿左子树一直往下搜索,直至出现没有左子树的结点
{
TreeNode *tempNode = new TreeNode;
tempNode->btnode = p;
tempNode->isFirst = true;
s.push(tempNode);
p = p->left;
}
if(!s.empty())
{
temp = s.top();
if(!temp->btnode->right||!temp->isFirst)
{
s.pop();
vist(tmp->btnode);
}
else //第二次出现在栈顶
{
p = temp->btnode->right;
temp->isFirst ==False
}
}
}
}
前面三种非递归算法的实质就是用栈来模拟递归,入栈即递归,出栈即回溯。前序和中序都很好理解,关键是后序,后序遍历因为会回溯两次,所以必须新增一个字段 is-first,当第一次访问的时候置为1,第二次访问置为0,这样就可以判断出是否要输出
非递归后序遍历(二)
void postOrder3(BinTree * root) //非递归后序遍历
{
stack < BinTree *> s;
BinTree * cur; //当前结点
BinTree * pre = NULL; //前一次访问的结点
s.push(root);
while ( ! s.empty())
{
cur = s.top();//拿最上面的
//如果当前结点没有孩子结点或者孩子节点都已被访问过
if ((cur ->lchild == NULL && cur -> rchild == NULL) ||
(pre!= NULL && (pre == cur -> lchild || pre == cur -> rchild)))//上一次的是现在的儿子
{
cout << cur -> data <<" " ;
s.pop();
pre = cur;
}
else
{
if (cur -> rchild != NULL)
s.push(cur -> rchild);
if (cur -> lchild != NULL)
s.push(cur -> lchild);//先右再左
}
}
}
这一种方法虽然更好理解,但并不是模拟递归过程,它 把入栈顺序是 自己-右边-左边 从上到小没有儿子就输出。
层序遍历
void LevelorderTraversal ( BinTree BT )
{
Queue Q;
BinTree T;
if ( !BT ) return; /* 若是空树则直接返回 */
Q = CreatQueue(); /* 创建空队列Q */
AddQ( Q, BT );
while ( !IsEmpty(Q) ) {
T = DeleteQ( Q );
printf("%d ", T->Data); /* 访问取出队列的结点 */
if ( T->Left ) AddQ( Q, T->Left );
if ( T->Right ) AddQ( Q, T->Right );
}
}
求结点个数
int GetNodeNum(BinaryTreeNode * pRoot)
{
if(pRoot == NULL) // 递归出口
return 0;
return GetNodeNum(pRoot->m_pLeft) + GetNodeNum(pRoot->m_pRight) + 1;
}
求深度
int GetDepth(BinaryTreeNode * pRoot)
{
if(pRoot == NULL) // 递归出口
return 0;
int depthLeft = GetDepth(pRoot->m_pLeft);
int depthRight = GetDepth(pRoot->m_pRight);
return depthLeft > depthRight ? (depthLeft + 1) : (depthRight + 1);
}
树的同构
bool StructureCmp(BinaryTreeNode * pRoot1, BinaryTreeNode * pRoot2)
{
if(pRoot1 == NULL && pRoot2 == NULL) // 都为空,返回真
return true;
else if(pRoot1 == NULL || pRoot2 == NULL) // 有一个为空,一个不为空,返回假
return false;
bool resultLeft = StructureCmp(pRoot1->m_pLeft, pRoot2->m_pLeft); // 比较对应左子树
bool resultRight = StructureCmp(pRoot1->m_pRight, pRoot2->m_pRight); // 比较对应右子树
return (resultLeft && resultRight);
}
二叉搜索树的插入和删除
BinTree Insert( BinTree BST, ElementType X )
{
if( !BST ){ /* 若原树为空,生成并返回一个结点的二叉搜索树 */
BST = (BinTree)malloc(sizeof(struct TNode));
BST->Data = X;
BST->Left = BST->Right = NULL;
}
else { /* 开始找要插入元素的位置 */
if( X < BST->Data )
BST->Left = Insert( BST->Left, X ); /*递归插入左子树*/
else if( X > BST->Data )
BST->Right = Insert( BST->Right, X ); /*递归插入右子树*/
/* else X已经存在,什么都不做 */
}
return BST;
}
BinTree Delete( BinTree BST, ElementType X )
{
Position Tmp;
if( !BST )
printf("要删除的元素未找到");
else {
if( X < BST->Data )
BST->Left = Delete( BST->Left, X ); /* 从左子树递归删除 */
else if( X > BST->Data )
BST->Right = Delete( BST->Right, X ); /* 从右子树递归删除 */
else { /* BST就是要删除的结点 */
/* 如果被删除结点有左右两个子结点 */
if( BST->Left && BST->Right ) {
/* 从右子树中找最小的元素填充删除结点 */
Tmp = FindMin( BST->Right );
BST->Data = Tmp->Data;
/* 从右子树中删除最小元素 */
BST->Right = Delete( BST->Right, BST->Data );
}
else { /* 被删除结点有一个或无子结点 */
Tmp = BST;
if( !BST->Left ) /* 只有右孩子或无子结点 */
BST = BST->Right;
else /* 只有左孩子 */
BST = BST->Left;
free( Tmp );
}
}
}
return BST;
}