Stay Hungry,Stay Foolish!

算法-基于二叉树实现动态数组

动态数组

在C语言等静态编码语言中, 数组必须有容量, 不能够像脚本中一样, 容量根据使用语句动态扩充。

C语言数组:

int arr[23]; // arr support 23 个元素. arr[100] not support.

 

JS数组:

var arr = new Array()

arr[1000] = 1

 

二叉树

http://www.cnblogs.com/sunysen/p/3225605.html

在计算机科学中,二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。

二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有个结点;深度为k的二叉树至多有个结点;对任何一棵二叉树T,如果其终端结点数为,度为2的结点数为,则。

 

 

完全二叉树和满二叉树

 

满二叉树:一棵深度为k,且有个节点成为满二叉树

 

完全二叉树:深度为k,有n个节点的二叉树,当且仅当其每一个节点都与深度为k的满二叉树中序号为1n的节点对应时,称之为完全二叉树

 

 

关于二叉树的实现 代码 https://github.com/Ironsongming/BinaryTree

 

基于二叉树实现动态数组思路

利用完全满二叉树, 数组的index, 对应到完全满二叉树的最高层, 叶子节点层, 从左到右边, 一次为 0 1 2 。。。 index

深度为 1 的二叉树 , 表示index [0, 0]

深度为 2 的二叉树 , 表示index [0, 1]

深度为 3 的二叉树 , 表示index [0, 3]

深度为 4 的二叉树 , 表示index [0, 7]

......

 

index 本身含有 从 根节点 到 对应叶子节点的 路径信息:

如果深度为1,不用关注index(只能为 0), 节点为 root

如果深度为2,index = 0 表示左儿子节点, index = 1 表示右儿子节点

如果深度为3,index = 0 = bit 00 表示左儿子 的 左儿子

      index = 1 = bit 01 表示 左儿子的 右儿子

      index = 2 = bit 10 表示 右儿子的 左儿子

      index = 3 = bit 11 表示 右儿子的 右儿子

 

 这样, 通用的定义path=index二进制表示法, 对应任意子树左右结构, 0 对应左儿子 1 对应右儿子。

 

C code complete

https://github.com/fanqingsong/code-snippet/blob/master/C/DynamicArr_on_BinaryTree/main.c

其中,当index大于目前树表达的能力时候,  树的深度增高, 增高的方法, 先计算增高的高度, 然后逐层递增。

typedef struct {
    BinaryTree * treeRoot;
    int treeDepth;
} T_DYNAMIC_ARR, *PT_DYNAMIC_ARR;

/* 创建动态数组 */
PT_DYNAMIC_ARR GetDynamicArr()
{
    PT_DYNAMIC_ARR ptDynamicArr = NULL;

    ptDynamicArr = malloc(sizeof(T_DYNAMIC_ARR));
    if ( !ptDynamicArr )
    {
        return NULL;
    }

    memset(ptDynamicArr, 0, sizeof(T_DYNAMIC_ARR));
    ptDynamicArr->treeRoot = InitBiTree();
    if ( !ptDynamicArr->treeRoot )
    {
        free(ptDynamicArr);
        return NULL;
    }

    ptDynamicArr->treeDepth = 1;

    ptDynamicArr->treeRoot->data = 0; 
    
    return ptDynamicArr;
}


void FreeDynamicArr(PT_DYNAMIC_ARR *pptDynamicArr)
{
    PT_DYNAMIC_ARR ptDynamicArr = *pptDynamicArr;
    
    DestroyBiTree( ptDynamicArr->treeRoot );

    free(ptDynamicArr);

    *pptDynamicArr = NULL;
}

/* create a full complete binary tree by depth */
BinaryTree* createFullCompleteBTree_ByDepth( int depth )
{
    BinaryTree * treeRoot = NULL;

    if ( depth <=0 )
    {
        return NULL;
    }

    if ( depth == 1 )
    {
        return InitBiTree();
    }
    else
    {
        treeRoot = InitBiTree();
        if ( ! treeRoot )
        {
            return NULL;
        }

        treeRoot->lChild = createFullCompleteBTree_ByDepth(depth-1);
        treeRoot->rChild = createFullCompleteBTree_ByDepth(depth-1);
    }
}

/* enlarge full complete tree by one depth, left tree leaves is same as orignal */
void enlargeOneDepth_OnfullCompleteTree(PT_DYNAMIC_ARR ptDynamicArr)
{
    BinaryTree* leftTree = ptDynamicArr->treeRoot;
    BinaryTree* rightTree = NULL;
    int depth = ptDynamicArr->treeDepth;

    rightTree = createFullCompleteBTree_ByDepth(depth);
    if ( ! rightTree )
    {
        return;
    }

    ptDynamicArr->treeRoot = InitBiTree();
    if ( ! ptDynamicArr->treeRoot )
    {
        ptDynamicArr->treeRoot = leftTree;
        return ;
    }

    ptDynamicArr->treeRoot->lChild = leftTree;
    ptDynamicArr->treeRoot->rChild = rightTree;

    ptDynamicArr->treeDepth++;
}

/* search tree leaf by path */
BinaryTree* SearchTreeLeafByPath(BinaryTree* ptTreeRoot, int depth,  int path )
{
    int mask_for_first_step = 0;
    int first_step = 0;

    if ( depth == 1 )
    {
        return ptTreeRoot;
    }
    else
    {
        mask_for_first_step = 0x1 << (depth -2);
        first_step = path & mask_for_first_step;

        if ( first_step == 0 )
        {
            ptTreeRoot = ptTreeRoot->lChild;
        }
        else
        {
            ptTreeRoot = ptTreeRoot->rChild;
        }

        depth--;
        
        return SearchTreeLeafByPath(ptTreeRoot, depth-1, path);
    }
}

/* find the tree node(leaf) according to index */
BinaryTree* GetTreeNodeByIndex(PT_DYNAMIC_ARR ptDynamicArr, int index)
{
    BinaryTree* ptTreeLeaf = NULL;

    BinaryTree* ptTreeRoot = ptDynamicArr->treeRoot;
    int depth = ptDynamicArr->treeDepth;

    /*  
    if tree depth is 2, ie, two tiers: 
        root
        /   \
       /     \
    leaf1   leaf2
    then index can be 0 or 1
        0 - leaf1
        1 - leaf2
   the path shall be  0 or 1.
    
    if depth is 3, the path can be
        index 0 - path 00
        index 1 - path 01
        index 2 - path 10
        index 3 - path 11
        
    if tree depth is 1, ie root is leaf
    path is null
    */
    int path = index; 

    ptTreeLeaf = SearchTreeLeafByPath( ptTreeRoot, depth,  path );

    return ptTreeLeaf;
}

/* set value in dynamic array */
void SetValue_DynamicArr(PT_DYNAMIC_ARR ptDynamicArr, int index, int value)
{
    int capacity = pow(2, (ptDynamicArr->treeDepth-1));
    printf("SetValue_DynamicArr capacity(%d) ptDynamicArr->treeDepth(%d)  \r\n", capacity, ptDynamicArr->treeDepth);
    // arr index = [0, capacity-1]
    int maxIndex = capacity - 1;
    int depthGain = 0;
    BinaryTree * ptTreeNode = NULL;

    printf("SetValue_DynamicArr begin enlarge  \r\n");
    // if index overlow, then deepen the tree, tree is full complete binary tree
    if ( index > maxIndex )
    {
        printf("SetValue_DynamicArr index(%d) maxIndex(%d)  \r\n", index, maxIndex);
        
        // calculate the depth that need to be increased
         do {
            capacity = capacity * 2;
            maxIndex = capacity -1;
            depthGain++;
         } while( index > maxIndex );
         
         printf("SetValue_DynamicArr depthGain(%d) \r\n", depthGain); 
         
         // deepen the tree
         while( depthGain > 0 )
         {
            enlargeOneDepth_OnfullCompleteTree(ptDynamicArr);
            depthGain--;
         }
    }

    printf("SetValue_DynamicArr begin get tree node  \r\n");
    ptTreeNode = GetTreeNodeByIndex(ptDynamicArr, index);
    if ( ! ptTreeNode )
    {
        return;
    }
    
    ptTreeNode->data = value;
}

int GetValue_DynamicArr(PT_DYNAMIC_ARR ptDynamicArr, int index)
{
    BinaryTree* ptTreeLeaf = NULL;

    ptTreeLeaf = GetTreeNodeByIndex(ptDynamicArr, index);
    if ( !ptTreeLeaf )
    {
        return 0;
    }

    return ptTreeLeaf->data;
}

void main(void)
{
    PT_DYNAMIC_ARR ptDynamicArr = GetDynamicArr();

    printf(" setvale of dynamic arr index(%d) value(%d) \r\n", 3, 10);
    SetValue_DynamicArr(ptDynamicArr, 3, 10);

    printf("--------------- \r\n");
    
    printf("--------------- \r\n");

    int value = GetValue_DynamicArr(ptDynamicArr, 3);
    printf(" getvalue of dynamic arr index(%d), value(%d)  \r\n", 3, value);

    FreeDynamicArr(&ptDynamicArr);
}

 

 

posted @ 2015-12-23 23:45  lightsong  阅读(532)  评论(0编辑  收藏  举报
Life Is Short, We Need Ship To Travel