查找之二叉树查找

转载自:http://blog.csdn.net/todd911/article/details/8471566


1.      查找树的创建(createTree)

假设有如下数组4,1,45,78,345,23,12,3,6,21

首先选定4为root,然后遍历剩下的数字,如果大于等于4则放到4的右侧,小于4放到4的左侧,最后构建成的树:所有的左孩子都小于父节点,所有的右孩子都大于等于父节点。如下图:




2.      遍历查找树(displayTree)

按照左中右的顺序遍历树,结果为:1,3,4,5,12,21,23,45,78,345,遍历的结果就是已经排好序的数字。

3.      查找树中的节点(searchTree)

从根节点开始,如果大于等于根节点,则查找根节点的右侧;如果小于根节点,则查找根节点的左侧,直到查找到节点。

比如要查找12:

比4大,往右走;

        比45小,往左走;

        比23小,往左走;

        找到12


4.      删除树中的节点(deleteNode)

这个是最复杂的,因为删除完节点后要重新构建树,涉及到的情况很多:

a.要删除的node没有左右孩子,有父节点。

如果要删除的node为父节点的左孩子,则将父节点的左孩子指针设置为NULL;如果要删除的node为父节点的右孩子,则将父节点的右孩子指针设置为NULL。最后删node。


b.要删除的node没有左右孩子,没有父节点(即根节点)。

根节点设为NULL,删除node。


c.要删除的node有左孩子没右孩子,有父节点

如果要删除的node为父节点的左孩子,则将父节点的左孩子设置为要被删除node的左孩子;如果要删除的node为父节点的右孩子,则将父节点的右孩子指针设置为要被除node的左孩子。最后删除node。


d.要被删除的node有左孩子没有右孩子,没有父节点

        将要被删除的node的左孩子设置为根节点,删除node。


e.要删除的node有右孩子没左孩子,有父节点

如果要删除的node为父节点的左孩子,则将父节点的左孩子设置为要被删除node的右孩子;如果要删除的node为父节点的右孩子,则将父节点的右孩子指针设置为要被除node的右孩子。最后删除node。


 f.要被删除的node有右孩子没有左孩子,没有父节点

        将要被删除的node的右孩子设置为根节点,删除node。


 g.要被删除的node左右孩子都有,有父节点

将要被删除node的右孩子插入到左孩子中去。如果要删除的node为父节点的左孩子,则将父节点的左孩子设置为要被删除node的左孩子;如果要删除的node为父节点右孩子,则将父节点的右孩子指针设置为要被删除node的左孩子。最后删除node。


h.要被删除的node左右孩子都有,无父节点

将要被删除node的右孩子插入到左孩子中去,父节点修改为要被删除node的左孩子,删除node节点。


c代码如下:

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. #define SIZE 10  
  5.   
  6. typedef struct tagNode{  
  7.         int value;  
  8.         struct tagNode* left;  
  9.         struct tagNode* right;  
  10. }treeNode;  
  11.   
  12. //打印数组  
  13. void displayArray(int array[],int size){  
  14.         printf("the array is:");  
  15.         int i;  
  16.         for(i=0;i<size;i++){  
  17.                 printf("%d ",array[i]);  
  18.         }  
  19.         printf("\n");  
  20. }  
  21.   
  22. //按左中右顺序遍历树  
  23. void displayTree(treeNode* node){  
  24.         if(node == NULL) return;  
  25.   
  26.         if(node->left != NULL){  
  27.                 displayTree(node->left);  
  28.         }  
  29.   
  30.         printf("%d ",node->value);  
  31.   
  32.         if(node->right != NULL){  
  33.                 displayTree(node->right);  
  34.         }  
  35. }  
  36.   
  37. //查找以node为节点的树中上是否存在vlaue的节点  
  38. treeNode* searchTree(treeNode* node, int value){  
  39.         if(node->value == value){  
  40.                 return node;  
  41.         }else if(node->value > value){  
  42.                 if(node->left != NULL){  
  43.                         return searchTree(node->left, value);  
  44.                 }else{  
  45.                         return NULL;  
  46.                 }  
  47.         }else{  
  48.                 if(node->right != NULL){  
  49.                         return searchTree(node->right, value);  
  50.                 }else{  
  51.                         return NULL;  
  52.                 }  
  53.         }  
  54. }  
  55.   
  56. //查找以node为节点的树中上是否存在vlaue的节点,parent为查找到的节点的父节点。  
  57. //dir为1表示parent节点的左节点为查找结果  
  58. //dir为2表示parent节点的右节点为查找结果  
  59. treeNode* searchTreeWithParent(treeNode* node, treeNode** parent, int* dir, int value){  
  60.         if(node->value == value){  
  61.                 return node;  
  62.         }else if(node->value > value){  
  63.                 if(node->left != NULL){  
  64.                         *dir = 1;  
  65.                         *parent = node;  
  66.                         return searchTreeWithParent(node->left, parent, dir, value);  
  67.                 }else{  
  68.                         return NULL;  
  69.                 }  
  70.         }else{  
  71.                 if(node->right != NULL){  
  72.                         *dir = 2;  
  73.                         *parent = node;  
  74.                         return searchTreeWithParent(node->right, parent, dir, value);  
  75.                 }else{  
  76.                         return NULL;  
  77.                 }  
  78.         }  
  79. }  
  80.   
  81. //将iNode插入到以node为根节点的树中  
  82. void insertNode(treeNode* node, treeNode* iNode){  
  83.         if(iNode->value >= node->value && node->right != NULL){  
  84.                 insertNode(node->right, iNode);  
  85.                 return;  
  86.         }  
  87.   
  88.         if(iNode->value < node->value && node->left != NULL){  
  89.                 insertNode(node->left, iNode);  
  90.                 return;  
  91.         }  
  92.   
  93.         if(iNode->value >= node->value && node->right == NULL){  
  94.                 node->right = iNode;  
  95.         }  
  96.   
  97.         if(iNode->value < node->value && node->left == NULL){  
  98.                 node->left = iNode;  
  99.         }  
  100. }  
  101.   
  102. //从以root为根节点的树中删除值为value的节点  
  103. void deleteNode(treeNode** root, int value){  
  104.         treeNode* parent = NULL;  
  105.         int dir = -1;  
  106.         treeNode* deleteNode = searchTreeWithParent(*root,&parent,&dir,value);  
  107.         if(deleteNode == NULL){  
  108.                 printf("%s\n""node not found");  
  109.         }else{  
  110.                 if(deleteNode->left == NULL && deleteNode->right == NULL){  
  111.             //对应说明中的a  
  112.                         if(parent != NULL){  
  113.                                 if(dir == 1)  
  114.                                         parent->left = NULL;  
  115.                                 else  
  116.                                         parent->right = NULL;  
  117.                         }else{//对应说明中的b  
  118.                                 *root = NULL;  
  119.                         }  
  120.                 }else if(deleteNode->left != NULL && deleteNode->right == NULL){  
  121.                         //对应说明中的c  
  122.             if(parent != NULL){  
  123.                                 if(dir == 1)  
  124.                                         parent->left = deleteNode->left;  
  125.                                 else  
  126.                                         parent->right = deleteNode->left;  
  127.                         }else{//对应说明中的d  
  128.                                 *root = deleteNode->left;  
  129.                         }  
  130.                 }else if(deleteNode->left == NULL && deleteNode->right != NULL){  
  131.                         //对应说明中的e  
  132.             if(parent != NULL){  
  133.                                 if(dir == 1)  
  134.                                         parent->left = deleteNode->right;  
  135.                                 else  
  136.                                         parent->right = deleteNode->right;  
  137.                         }else{//对应说明中的f  
  138.                                 *root = deleteNode->right;  
  139.                         }  
  140.                 }else{  
  141.                         insertNode(deleteNode->left,deleteNode->right);  
  142.                         //对应说明中的g  
  143.             if(parent != NULL){  
  144.                                 if(dir == 1)  
  145.                                         parent->left = deleteNode->left;  
  146.                                 else  
  147.                                         parent->right = deleteNode->left;  
  148.                         }else{//对应说明中的h  
  149.                                 *root = deleteNode->left;  
  150.                         }  
  151.                 }  
  152.                 free(deleteNode);  
  153.                 deleteNode = NULL;  
  154.         }  
  155. }  
  156.   
  157. //使用array数组中的数,创建以root为根节点的树,  
  158. void createTree(treeNode** root, int array[], int size){  
  159.         int i;  
  160.   
  161.         *root = (treeNode*)malloc(sizeof(treeNode));  
  162.         (*root)->value = array[0];  
  163.         (*root)->left = NULL;  
  164.         (*root)->right = NULL;  
  165.   
  166.         for(i=1;i<size;i++){  
  167.                 treeNode* child = (treeNode*)malloc(sizeof(treeNode));  
  168.                 child->value = array[i];  
  169.                 child->left = NULL;  
  170.                 child->right = NULL;  
  171.                 insertNode(*root, child);  
  172.         }  
  173. }  
  174.   
  175. //删除以node为根节点的树  
  176. void deleteTree(treeNode* node){  
  177.         if(node == NULL) return;  
  178.   
  179.         if(node->left != NULL){  
  180.                 deleteTree(node->left);  
  181.         }  
  182.   
  183.         if(node->right != NULL){  
  184.                 deleteTree(node->right);  
  185.         }  
  186.   
  187.         if(node->left == NULL && node->right == NULL){  
  188.                 free(node);  
  189.                 node = NULL;  
  190.         }  
  191. }  
  192.   
  193. int main(int argc, char* argv[]){  
  194.   
  195.         int array[SIZE] = {4,1,45,78,345,23,12,3,6,21};  
  196.         displayArray(array,SIZE);  
  197.   
  198.         treeNode *root = NULL;  
  199.   
  200.         createTree(&root, array, SIZE);  
  201.   
  202.         printf("the tree is(left->middle->right):");  
  203.         displayTree(root);  
  204.         printf("\n");  
  205.   
  206.         int value = atoi(argv[1]);  
  207.         treeNode* parent = NULL;  
  208.         int dir = -1;  
  209.         printf("search value %d:",value);  
  210.         if(searchTree(root,value) != NULL){  
  211.                 printf("%s\n","exist");  
  212.         }else{  
  213.                 printf("%s\n","not exist");  
  214.         }  
  215.   
  216.         printf("delete value:%d ",value);  
  217.         deleteNode(&root,value);  
  218.         printf("\n");  
  219.         printf("the tree is(left->middle->right):");  
  220.         displayTree(root);  
  221.         printf("\n");  
  222.   
  223.         deleteTree(root);  
  224.         return 0;  
  225. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值