面试题(二叉树相关) - 人是会思考的一棵苇草 - 博客频道 - CSDN.NET

转载 2012年06月20日 21:37:15
// 二叉树有关的操作

#include "stdafx.h"
#include "CommonDataStruct.h"
#include <stddef.h>
#include <stack>
#include <queue>

//////////////////////////////////////////////////////////////////////////
// 给定二叉搜索树,转换成双向链表
// lchild变成双链表的prev指针, rchild变成双链表的next指针.
BTNODE* BST2DLL(BTNODE* root)
{
    BTNODE* head = nullptr;

    if (root == nullptr)
    {
        return head;
    }

    BTNODE* p = nullptr; //p指向已经建好的部分双链表的最后一个元素
    BTNODE* q = root;
    std::stack<BTNODE*> stkTreeNode;
    while (q != nullptr || !stkTreeNode.empty())
    {
        if (q != nullptr) //压栈过程不建表
        {
            stkTreeNode.push(q);
            q = q->lchild;
        }
        else // 在pop过程中拼接双链表
        {
            q = stkTreeNode.top();
            stkTreeNode.pop();

            if (p != nullptr)
            {
                p->rchild = q; //p->next = p
            }
            q->lchild = p; //q->prev = p

            if (head == nullptr) // q is the head node.
            {
                head = q;
            }

            p = q;

            q = q->rchild;
        }
    }

    return head;
}

//////////////////////////////////////////////////////////////////////////
// 给定二叉树,求二叉树最大的宽度
struct QNODE
{
    QNODE(BTNODE* p, int l) {pTreeNode = p, nLevel = l;}
    BTNODE* pTreeNode;
    int nLevel;
};

unsigned int GetBTreeMaxWidth(BTNODE* root)
{
    if (root == nullptr)
    {
        return 0;
    }

    std::queue<QNODE*> q;
    QNODE* r = new QNODE(root, 0);
    q.push(r);
    unsigned int uMaxDepth = 1;
    while(!q.empty())
    {
        // dequeue all elements that on the same level, and enqueue their children.
        QNODE* pFront = q.front();
        int nCurLevel = pFront->nLevel;
        while (!q.empty() && (pFront = q.front())->nLevel == nCurLevel)
        {
            q.pop();
            if (pFront->pTreeNode->lchild != nullptr)
            {
                QNODE* lch = new QNODE(pFront->pTreeNode->lchild, pFront->nLevel + 1);
                q.push(lch);
            }
            if (pFront->pTreeNode->rchild != nullptr)
            {
                QNODE* rch = new QNODE(pFront->pTreeNode->rchild, pFront->nLevel + 1);
                q.push(rch);
            }

            delete pFront;
        }

        // After the while loop is finished, the queue only contains next level elements.
        // So let's check the length of the queue.
        if(uMaxDepth < q.size())
        {
            uMaxDepth = q.size();
        }
    }

    return uMaxDepth;
}

//////////////////////////////////////////////////////////////////////////
// 已知二叉树的前序和中序,递归构造二叉树
// ps, pe是preorder前序数组的起始元素下标和结束元素下标
// is, ie是inorder中序数组的起始元素下标和结束元素下标
BTNODE* BuildBinaryTree(int preorder[], int ps, int pe, int inorder[], int is, int ie)
{
    if (ps > pe || is > ie)
    {
        return nullptr;
    }

    int nPreOrderLen = pe - ps + 1;
    int nInOrderLen = ie - is + 1;
    if (nPreOrderLen != nInOrderLen)
    {
        return nullptr;
    }

    BTNODE* root = new BTNODE();
    root->val = preorder[ps];
    if (nPreOrderLen == 1)
    {
        root->lchild = nullptr;
        root->rchild = nullptr;
    }
    else
    {
        // Search the root in inorder
        int r;
        for (r = is; r <= ie; ++r)
        {
            if(inorder[r] == preorder[ps])
            {
                break;
            }
        }

        // if we cannot find root element in inorder, something wrong.
        if (r == ie && inorder[r] != preorder[ps])
        {
            delete root;
            return nullptr;
        }

        if (r - is > 0) // have left subtree.
        {
            root->lchild = BuildBinaryTree(preorder, ps+1, ps+(r-is), inorder, is, r-1);
        }

        if (ie - r > 0) // have right subtree
        {
            root->rchild = BuildBinaryTree(preorder, ps+(r-is)+1, pe, inorder, r+1, ie);
        }
    }

    return root;
}

//////////////////////////////////////////////////////////////////////////
// 递归后序遍历二叉树
void PostOrder(BTNODE* root)
{
    if (root != nullptr)
    {
        PostOrder(root->lchild);
        PostOrder(root->rchild);
        printf("%d ", root->val);
    }
}

// 递归前序遍历二叉树
void PreOrder(BTNODE* root)
{
    if(root != nullptr)
    {
        printf("%d ", root->val);
        PreOrder(root->lchild);
        PreOrder(root->rchild);
    }
}

// 非递归中序遍历二叉树
void NonRescursionInOrder(BTNODE* root)
{
    if (root == nullptr)
    {
        return;
    }

    std::stack<BTNODE*> stkTreeNode;
    BTNODE* p = root;

    while (p != nullptr || !stkTreeNode.empty())
    {
        if (p != nullptr)
        {
            stkTreeNode.push(p);
            p = p->lchild;
        }
        else
        {
            p = stkTreeNode.top();
            stkTreeNode.pop();
            printf("%d ", p->val);
            p = p->rchild;
        }
    }
}

// 非递归逆中序遍历二叉树
void NonRescursionReverseInOrder(BTNODE* root)
{
    if (root == nullptr)
    {
        return;
    }

    std::stack<BTNODE*> stkNode;
    BTNODE* p = root;

    while (p != nullptr || !stkNode.empty())
    {
        if (p != nullptr)
        {
            stkNode.push(p);
            p = p->rchild;
        }
        else
        {
            p = stkNode.top();
            stkNode.pop();
            printf("%d ", p->val);
            p = p->lchild;
        }
    }
}

//////////////////////////////////////////////////////////////////////////
// 给定二叉搜索树,查找第K大个数,注意是大,所以是逆中序访问,修改非递归中序的访问左右子树的顺序即可.
void FindKthMax(BTNODE* root, int k)
{
    if (root == nullptr)
    {
        return;
    }

    std::stack<BTNODE*> stkNode;
    BTNODE* p = root;
    int nVisited = 0;

    while (p != nullptr || !stkNode.empty())
    {
        if (p != nullptr)
        {
            stkNode.push(p);
            p = p->rchild;
        }
        else
        {
            p = stkNode.top();
            stkNode.pop();
            if (++nVisited == k)
            {
                printf("We've got it, %dth maximum number is %d", k, p->val);
                break;
            }
            p = p->lchild;
        }
    }

    if (nVisited < k)
    {
        printf("Sorry, K overflowed.");
    }
}

//////////////////////////////////////////////////////////////////////////
// Test

#define countof(a) sizeof(a)/sizeof(a[0])

void TreeTest()
{
    int preorder[] = {11, 8, 3, 1, 4, 9, 17, 13, 12, 14, 19};
    int inorder[] = {1, 3, 4, 8, 9, 11, 12, 13, 14, 17, 19};

    BTNODE* root = BuildBinaryTree(preorder, 0, countof(preorder)-1, inorder, 0, countof(inorder)-1);

    printf("Pre order: ");
    PreOrder(root);
    printf("\r\n");

    printf("Post order : ");
    PostOrder(root);
    printf("\r\n");

    printf("In order : ");
    NonRescursionInOrder(root);
    printf("\r\n");

    printf("Reverse in order : ");
    NonRescursionReverseInOrder(root);
    printf("\r\n");

    FindKthMax(root, 5);
    printf("\r\n");

    printf("tree max width is %d\r\n", GetBTreeMaxWidth(root));

    BTNODE* head = BST2DLL(root);
    //正反向验证双链表
    BTNODE* a = head;
    while (a != nullptr)
    {
        printf("%d ", a->val);
        a = a->rchild;
    }
    printf("\r\n");
    a = head;
    while (a->rchild != NULL)
    {
        a = a->rchild;
    }
    while (a != nullptr)
    {
        printf("%d ", a->val);
        a = a->lchild;
    }
    printf("\r\n");
}


Softmax 函数的特点和作用

----------因为这里不太方便编辑公式,所以很多公式推导的细节都已经略去了,如果对相关数学表述感兴趣的话,请戳这里的链接Softmax的理解与应用 - superCally的专栏 - 博客频道 ...
  • Scythe666
  • Scythe666
  • 2017年07月17日 19:41
  • 377

iOS 中常用的动画效果

最近工作中刚好用到过其中的某些动画,所以在网上搜了下资料,了解了下这些动画。这里就自己的理解做一下总结,如有错误或遗漏,尽请谅解。...
  • u014641631
  • u014641631
  • 2014年04月25日 11:51
  • 586

使用消息队列

下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处。有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信——使用命名管道 一、什么是消息队列 消息...
  • u010027547
  • u010027547
  • 2015年10月10日 15:05
  • 177

Android——内存管理-lowmemorykiller 机制

前段时间碰到一个apk多个process依次开跑,跑到最后一个process的时候,第一个process给kill掉了,虽然第一个process中含有broadcast receive,被kill掉的...
  • jscese
  • jscese
  • 2015年08月07日 10:48
  • 10708

Linux进程间通信

一、进程间通信概述 进程通信有如下一些目的: A、数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间 B、共享数据:多个进程想要操作共享数据,一个进程对共享数...
  • xiegenwendada
  • xiegenwendada
  • 2013年01月07日 16:19
  • 240

vim插件taglist的安装和使用

vim插件taglist的安装和使用 转载:http://blog.csdn.net/g_brightboy/article/details/1684...
  • xxuffei
  • xxuffei
  • 2017年12月24日 21:31
  • 19

编辑文章 - 博客频道 - CSDN.NET

Android HAL层,即硬件抽象层,是Google响应厂家“希望不公开源码”的要求推出的新概念 1,源代码和目标位置 源代码: /hardware/libhardware目录,该目录的目录结构...
  • u012296694
  • u012296694
  • 2014年04月18日 16:45
  • 414

编辑文章 - 博客频道 - CSDN.NET

Protues 与 Keil 或 IAR 远程调试   (2013-07-26 11:44:38) 转载▼ 标签:  protues   keil   ...
  • power2008man
  • power2008man
  • 2014年06月17日 09:59
  • 417

二叉树相关面试题目总结

前言: 一、为什么要树结构? 不像数组、链表是线性的数据结构,树是一种分层的非线性数据结构 (1)使用树的一个原因是:我们需要存储有分层关系的信息(比如说文件系统) (2)另外一个是(BST)...
  • libo982792994
  • libo982792994
  • 2016年07月19日 15:30
  • 2582

二叉树的五道面试题

1、判断一棵树是否是完全二叉树; 2、求二叉树中最远两个结点的距离; 3、由前序和中序遍历序列重建二叉树 (前序序列:1 2 3 4 5 6 - 中序序列:3 2 4 1 6 5); 4、求二叉...
  • LLZK_
  • LLZK_
  • 2016年11月30日 10:14
  • 665
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:面试题(二叉树相关) - 人是会思考的一棵苇草 - 博客频道 - CSDN.NET
举报原因:
原因补充:

(最多只允许输入30个字)