二叉树线索化

来源:互联网 发布:珠海航展歼20知乎 编辑:程序博客网 时间:2024/05/08 21:34
如果我们想在排序二叉树中删除一段数据的节点怎么办呢?按照现在的结构,我们只能一个一个数据查找验证,首先看看在不在排序二叉树中,如果在那么删除;如果没有这个数据,那么继续查找。那么有没有方法,可以保存当前节点的下一个节点是什么呢?这样就不再需要进行无谓的查找了。其实这样的方法是存在的,那就是在排序二叉树中添加向前向后双向节点。
    现在数据结构定义如下:
[cpp] view plaincopy
  1. typedef struct _TREE_NODE  
  2. {  
  3.     int data;  
  4.     struct _TREE_NODE* prev;  
  5.     struct _TREE_NODE* next;  
  6.     struct _TREE_NODE* left;  
  7.     struct _TREE_NODE* right;  
  8. }TREE_NODE;  
    拿节点的添加来说,我们可能需要添加prev、next的处理步骤。
[cpp] view plaincopy
  1. void set_link_for_insert(TREE_NODE* pParent, TREE_NODE* pNode)  
  2. {  
  3.     if(NULL == pParent || NULL == pNode)  
  4.         return;  
  5.   
  6.     if(pNode = pParent->left){  
  7.         pNode->prev = pParent->prev;  
  8.         if(pParent->prev)  
  9.             pParent->prev->next = pNode;  
  10.         pNode->next = pParent;  
  11.         pParent->prev = pNode;  
  12.     }else{  
  13.         pNode->next = pParent->next;  
  14.         if(pParent->next)  
  15.             pParent->next->prev = pNode;  
  16.         pNode->prev = pParent;  
  17.         pParent->next = pNode;  
  18.     }  
  19.   
  20.     return;  
  21. }  
  22.   
  23. STATUS add_node_into_tree(TREE_NODE** ppTreeNode, int data)  
  24. {  
  25.     TREE_NODE* pHead;  
  26.     TREE_NODE* pNode;  
  27.   
  28.     if(NULL == ppTreeNode)  
  29.         return FALSE;  
  30.   
  31.     if(NULL == *ppTreeNode){  
  32.         *ppTreeNode = create_new_node(data);  
  33.         return TRUE;  
  34.     }  
  35.   
  36.     if(NULL != find_data_in_tree(*ppTreeNode, data))  
  37.         return FALSE;  
  38.   
  39.     pHead = *ppTreeNode;  
  40.     while(1){  
  41.         if(data < pHead->data){  
  42.             if(pHead->left){  
  43.                 pHead = pHead->left;  
  44.             }else{  
  45.                 pNode = create_new_node(data);  
  46.                 pHead->left = pNode;  
  47.                 break;  
  48.             }  
  49.         }else{  
  50.             if(pHead->right){  
  51.                 pHead = pHead->right;  
  52.             }else{  
  53.                 pNode = create_new_node(data);  
  54.                 pHead->right = pNode;  
  55.                 break;  
  56.             }  
  57.         }  
  58.     }  
  59.   
  60.     set_link_for_insert(pHead, pNode);  
  61.     return TRUE;  
  62. }  
    添加节点如此,删除节点的工作也不能马虎。
[cpp] view plaincopy
  1. void set_link_for_delete(TREE_NODE* pNode)  
  2. {  
  3.     if(pNode->prev){  
  4.         if(pNode->next){  
  5.             pNode->prev->next = pNode->next;  
  6.             pNode->next->prev = pNode->prev;  
  7.         }else  
  8.             pNode->prev->next = NULL;  
  9.     }else{  
  10.         if(pNode->next)  
  11.             pNode->next->prev = NULL;  
  12.     }  
  13. }  
  14.   
  15. TREE_NODE* _delete_node_from_tree(TREE_NODE* root, TREE_NODE* pNode)  
  16. {  
  17.     TREE_NODE* pLeftMax;  
  18.     TREE_NODE* pLeftMaxParent;  
  19.     TREE_NODE* pParent = get_parent_of_one(root, pNode);  
  20.   
  21.     if(NULL == pNode->left && NULL == pNode->right){  
  22.         if(pNode == pParent->left)  
  23.             pParent->left = NULL;  
  24.         else  
  25.             pParent->right = NULL;  
  26.     }else if(NULL != pNode->left && NULL == pNode->right){  
  27.         if (pNode == pParent->left)  
  28.             pParent->left = pNode->left;  
  29.         else  
  30.             pParent->right = pNode->left;  
  31.     }else if(NULL == pNode->left && NULL != pNode->right){  
  32.         if(pNode == pParent->left)  
  33.             pParent->left = pNode->right;  
  34.         else  
  35.             pParent->right = pNode->right;  
  36.     }else{  
  37.         pLeftMax = get_max_node_of_one(pNode->left);  
  38.         if(pLeftMax == pNode->left){  
  39.             pNode->left->right = pNode->right;  
  40.             if(pNode == pParent->left)  
  41.                 pParent->left = pNode->left;  
  42.             else  
  43.                 pParent->right = pNode->left;  
  44.         }else{  
  45.             pLeftMaxParent = get_parent_of_one(root, pLeftMax);  
  46.             pNode->data = pLeftMax->data;  
  47.             pLeftMaxParent->right = NULL;  
  48.             pNode = pLeftMax;  
  49.         }  
  50.     }  
  51.   
  52.     return pNode;  
  53. }  
  54.   
  55. STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data)  
  56. {  
  57.     TREE_NODE* pNode;  
  58.     TREE_NODE* pLeftMax;  
  59.     TREE_NODE* pLeftMaxParent;  
  60.   
  61.     if(NULL == ppTreeNode || NULL == *ppTreeNode)  
  62.         return FALSE;  
  63.   
  64.     if(NULL == (pNode = find_data_in_tree(*ppTreeNode, data)))  
  65.         return FALSE;  
  66.   
  67.     if(pNode == *ppTreeNode){  
  68.         if(NULL == pNode->left && NULL == pNode->right)  
  69.             *ppTreeNode = NULL;  
  70.         else if(NULL != pNode->left && NULL == pNode->right)  
  71.             *ppTreeNode = pNode->left;  
  72.         else if(NULL == pNode->left && NULL != pNode->right)  
  73.             *ppTreeNode = pNode->right;  
  74.         else {  
  75.             pLeftMax =  get_max_node_of_one(pNode->left);  
  76.             if(pNode->left == pLeftMax){  
  77.                 pNode->left->right = pNode->right;  
  78.                 *ppTreeNode = pNode->left;  
  79.             }else{  
  80.                 pLeftMaxParent = get_parent_of_one(*ppTreeNode, pLeftMax);  
  81.                 pNode->data = pLeftMax->data;  
  82.                 pLeftMaxParent->right = NULL;  
  83.                 pNode = pLeftMax;  
  84.             }  
  85.         }  
  86.   
  87.         goto final;  
  88.     }  
  89.   
  90.     pNode = _delete_node_from_tree(*ppTreeNode, pNode);  
  91.   
  92. final:  
  93.     set_link_for_delete(pNode);  
  94.   
  95.     free(pNode);  
  96.     return TRUE;  
  97. }  

    其中,寻找最大值节点和寻找父节点的代码如下所示:

[cpp] view plaincopy
  1. TREE_NODE* get_max_node_of_one(TREE_NODE* pNode)  
  2. {  
  3.     if(NULL == pNode)  
  4.         return NULL;  
  5.   
  6.     while(pNode->right)  
  7.         pNode = pNode->right;  
  8.   
  9.     return pNode;  
  10. }  
  11.   
  12. TREE_NODE* get_parent_of_one(TREE_NODE* root, TREE_NODE* pNode)  
  13. {  
  14.     if(NULL == root || NULL == pNode)  
  15.         return NULL;  
  16.   
  17.     while(root){  
  18.         if(pNode == root->left || pNode == root->right)  
  19.             return root;  
  20.         else if(pNode->data < root->data)  
  21.             root = root->left;  
  22.         else  
  23.             root = root->right;  
  24.     }  
  25.   
  26.     return NULL;  
  27. }  

总结:
    (1)排序二叉树的序列化关键就是在二叉树节点添加前向指针和后继指针
    (2)排序二叉树是空间换时间的典型案例
    (3)排序二叉树是很多结构的基础,写多少遍都不为多,有机会朋友们应该多加练习
    (4)测试用例的编写是代码编写的关键,编写程序的目的就是为了消除bug,特别是低级bug
0 0