算法-基于二叉树实现动态数组
动态数组
在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的满二叉树中序号为1至n的节点对应时,称之为完全二叉树
关于二叉树的实现 代码 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); }