几道二叉树的代码

几道二叉树的代码


FIRST

在二叉树中查找 data 域的值等于 key 的结点是否存在,如果存在,则将 q 指向该结点,否则 q 赋值为 NULL, 假设 data 为 int 型
解法一:

/*假设二叉树已经存在且 p 指向其根节点*/
void search(BTNode *p, BTNode *&q, int key)
/*注意要将参数 q 定义为引用型指针,因为 q 要改变*/
{
    if(p)
    {
        if(p -> data == key)
            q = p;
        else
            {
                search(p->lchild, q, key);
                search(p->rchild, q, key);
            }
    }
}

解法二:

void search(BTNode *p, BTNode *&q, int key)
{
    if(p)
    {
        if(p->data == key)
            q = p;
        else
            {
                search(p->lchild, q, key);
                if(q == NULL)   // 左子树搜索不到才到右子树去查找
                    search(p->rchild, q, key);
            }
    }
}

SECOND

输出先序序列遍历中第 k 个结点的值

int n = 0;
void trave(BTNode *p, int k)
{
    if(p)
    {
        ++n;
        if(k == n)
        {
            cout << p -> data << endl;
            return;
        }

        trave(p->lchild, k);
        trave(p->rchild, k);
    }
}

THIRD

二叉树的层次遍历

void level(BTNode *p)
{
    int front, rear;
    BTNode *que[maxSize];   // 定义一个循环队列,用来记录要访问的层次上的结点
    BTNode *q;
    front = rear = 0;

    if(p)
    {
        rear = (rear+1) % maxSize;
        que[rear] = p;  // 根节点入队
        while(front != rear)    // 当队列不为空时进行循环
        {
            front = (front+1) % maxSize;
            q = que[front];     // 队头结点出队
            visit[q];       // 访问队头结点

            if(q -> lchild)
            {
                rear = (rear+1) % maxSize;
                que[rear] = q -> lchild;
            }

            if(q->rchild)
            {
                rear = (rear+1) % maxSize;
                que[rear] = q -> rchild;
            }
        }
    }
}

FORTH

一个完全二叉树按顺序存储结构存储在数组 tree[] 中,假设二叉树结点值类型为 char 型,结点个数为 n,设计一个算法,求出离下标分别为 i 和 j 的两个结点最近的公共祖先结点的值。

char ancestor(char tree[], int i, int j)
{
    int p = i, q = j;
    while(p != q)
    {
        if(p > q)
            p = p / 2;  // p 往上走
        else
            q = q / 2;  // q 往上走
    }
    return tree[p];
}

FIFTH

已知二叉树的结点按先序遍历下的序列存储在一维数组 pre[left_1,……,right_1] 中,按中序遍历下的序列存储在一维数组 in[left_2,……,right_2] 中。写出由先序和中序序列构造二叉树的算法。

BTNode *CreateBT[cha pre[], char in[], int left_1, int right_1, int left_2, int right_2]
{
    BTNode *s;
    int i;
    if(left_1 > right_1)
        return NULL;

    s = (BTNode *s)malloc(sizeof(BTNode));
    s -> lchild = s -> rchild = NULL;

    //查找等于当前子树根的结点在 in[] 中的位置
    for(i = left_2; i <= right_2; i++)                                      
        if(in[i] == pre[left_1])
            break;
    s -> data = in[i];

    /*通过在 in[] 中找到分界点 i, 确定在 pre[] 和 in[] 中当前子树的左子树范围,再仿照之前的方法建立左子树,将左子树根连接在 s 的左指针域上*/
    s -> lchild = CreateBT(pre, in, left_1 + 1, left_1 + (i - left_2), left_2, i-1)

    s -> rchild = CreateBT(pre, in, left_1 + 1, left_1 + (i - l2), left_2, i-1)
}

SIXTH

计算一棵给定二叉树的所有结点数
解法一:

int n;
void count(BTNode *p)
{
    if(p)
    {
        n++;
        count(p -> lchild);
        count(p -> rchild);
    }
}

解法二:

int count(BTNode *p)
{
    int n1, n2;
    if(!p)
        return NULL;
    else
    {
        n1 = count(p -> lchild);
        n2 = count(p -> rchild);
        return n1+n2+1; // 每次都要加上当前根节点
    }
}

SEVENTH

计算一棵二叉树的所有叶子结点数
解法一:

int n;
void count(BTNode *p)
{
    if(p)
    {
        if(!p->lchild && ! p->rchild)
            n++;
        count(p -> lchild);
        count(p -> rchild);
    }
}

解法二:

int count(BTNode *p)
{
    int n1, n2;
    if(!p)
        return 0;
    else if(!p->lchild && !p->rchild)
        return 1;
    else
    {
        n1 = count(p -> lchild);
        n2 = count(p -> rchild);
        return n1+n2;
    }
}

EIGHTH

利用结点的 rchild 指针,将叶子结点从左往右串成一个单链表

void link(BTNode *p, BTNode *&head, BTNode *&tail)
{
    if(p)
    {
        if(!p->lchild && !p->rchild)
        {
            if(!head)   /*如果 head == NULL, 说明这是第一个叶子结点*/
            {
                head = p;
                tail = p;
            }
            else
            {
                tail -> rchild = p;
                tail = p;
            }
            link(p->lchild, head, tail);
            link(p->rchild, head, tail);
        }
    }
}

NINTH

二叉树采用二叉链式存储结构,增加一个指向双亲结点的 parent 指针,设计一个算法,给这个结点赋值,并输出所有结点到根结点的路径

typedef struct BTNode
{
    char data;
    BTNode *lchild;
    BTNode *rchild;
    BTNode *parent;
}BTNode;

BTNode *q = NULL;
void triBtree(BTNode *p, BTNode *q)
{   /*参数 q 始终指向当前访问结点 p 的双亲结点。当 P 为根结点时, q 应为 NULL*/
    if(p)
    {
        p -> praent = q;
        q = p;
        triBtree(p -> lchild);
        triBtree(p -> rchild);
    }
}

void printPath(BTNode *p)
{
    while(p)
    {
        cout << p -> data << " ";
        p = p -> parent;
    }
}

void allPath(BTNode *p)
{
    if(p)
    {
        printPath(p);
        allPath(p->lchild);
        allPath(p->rchild);
    }
}

TENTH

求二叉树中值为 x 的结点的层号

int L = 1;
void leno(BTNode *p)
{
    if(p)
    {
        if(p->data == x)
            cout << L << endl;
    }
    ++L;

    leno(p->lchild, x);
    leno(p->rchild, x); 
    /*这两句执行完后,p 指针要由下一层返回到上一层了,所以要 --L*/

    --L;
}

ELEVENTH

设计算法,输出根结点到每个叶子结点的路径

int i;
int top = -1;
char pathStack[maxSize];
void allPath(BTNode *p)
{
    if(p)
    {
        pathStack[++top] = p -> data;

        if(!p->lchild && !p->rchild)
        {
            for(i = 0; i <= top; i++)
                cout << pathStack[i];
        }
        allPath(p->lchild);
        allPath(p->rchild);

        --top;  /*所访问结点出栈*/
    }
}

TWELFTH

二叉树先序遍历的非递归算法

void preOrder(BTNode *root)
{
    BTNode *Stack[maxSize];
    int top = -1;
    BTNode *p;

    if(bt)
    {
        Stack[++top] = bt;  /*入栈顺序:根 -> 右 -> 左*/
        while(top != -1)
        {
            p = Stack[top--];
            cout << p->data << " ";
            if(p->rchild)
                Stack[++top] = p -> rchild;
            if(p->lchild)
                Stack[++top] = p -> lchild;
        }
    }
}

二叉树中序遍历的非递归算法

void inOrder(BTNode *root)
{
    BTNode *Stack[maxSize];
    int top = -1;
    BTNode *p;
    if(root)
    {
        p = root;
        /*在出栈过程中会出现栈空状态,但这时遍历还没有结束,因根结点的右子树还没有遍历,此时 p 非空,根据这一点来维持循环队的进行*/

        while(top != -1 || p)
        {
            while(p)    /*左孩子先全部入栈*/
            {   
                Stack[++top] = p;
                p = p -> lchild;
            }

            if(top != -1)
            {
                p = Stack[top--];
                cout << p -> data << " ";
                p = p -> rchild;
            }
        }
    }
}

二叉树后序遍历的非递归算法

void Postorder(BTNode* t)
{
    BTnode* Seqstack[MAXSIZE];
    int top = -1;
    int falg = 1;
    BTnode* p;
    if(t != NULL)
    {
        do
        {
            while(t != NULL)                    // 循环,将所有最左结点压栈
            {
                top ++;
                Seqstack[top] = t;
                t = t->lchild;
            }
            flag = 1;                          
            // 辅助变量flag为1表示当前结点的左孩子为空或者已被访问
            p = NULL;                          
            // 指针变量p指向当前结点的前驱结点
            while(top > -1&& falg == 1)
            {
                t = Seqstack[top];             
                // 注意:这里只是获取栈顶元素,而并没有出栈
                if(t->rchild == p)              
                // 如果当前结点右孩子为空,或者已经被访问过,则访问当前结点
                {
                    top --;                     // 当前结点出栈
                    printf("%d ", p->data);
                    p = t;                      // 指针变量指向当前结点
                }
                else                            // 如果当前结点右孩子不为空,则先去处理右孩子
                {
                    t = t->rchild;              // 处理右孩子
                    flag = 0;                   
                    // *t的左孩子未被访问,flag置为0
                }
            }
        }while(top > -1)
    }

}

将二叉树 bt 中每一个结点的左右子树互换

void Exchange(BTNode *bt)
{
    BTNode *p, *q;
    if(bt)
    {
        EnQueue(Q,bt);
        while(!Empty(Q))
        {
            p = DeQueue(Q);
            if(p->lchild)
                EnQueue(p->lchild);
            if(p->rchild)
                EnQueue(p->rchild);
            q = p -> rchild;
            p -> rchild = p -> lchild;
            p -> lchild = q;
        }
    }
}

求二叉树的高度

int Height(BTNode *p)
{
    if(p)
    {
        if(!p->lchild)
            lh = 0;
        else
            lh = Height(p->lchild);
        if(!p->rchild)
            rh = 0;
        else
            rh = Height(p->rchild);
        if(lh > rh)
            hi = lh + 1;
        else
            hi = rh + 1;
    }
    else
        hi = 0;
    return hi;
}

求出以 T 为根的二叉树的结点个数

int size(BTNode *T)
{
    if(!T)
        return 0;
    else
        return 1 + size(T->lchild) + size(T->rchild);
}

计算根为 r 的树中叶子结点的个数
int numberofleaf(BTNode *r)
{
    int num;
    if(!r)
        num = 0;
    else if(!l->lchild)
        num = 1 + numberofleaf(r->rchild);
    else
        num = numberofleaf(r->lchild) + numberofleaf(r->rchild);
    return num;
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值