查找之二叉树查找

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代码如下:

  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 }
时间: 2024-10-11 22:51:15

查找之二叉树查找的相关文章

数据结构之二叉树查找

数据结构之--二叉树查找 定义:它是一棵树,或者具有以下性质的树.  若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值: 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值:  它的左.右子树也分别为二叉排序树: 图解: ?        ?    ?    ?    ?    ?? #include<stdio.h> #include<stdlib.h> typedef int Status; #define TRUE 1 #define FALSE 0 t

深入浅出数据结构C语言版(12)——从二分查找到二叉树

在很多有关数据结构和算法的书籍或文章中,作者往往是介绍完了什么是树后就直入主题的谈什么是二叉树balabala的.但我今天决定不按这个套路来.我个人觉得,一个东西或者说一种技术存在总该有一定的道理,不是能解决某个问题,就是能改善解决某个问题的效率.如果能够先了解到存在的问题以及已存在的解决办法的不足,那么学习新的知识就更容易接受,也更容易理解. 万幸的是,二叉树的讲解是可以按照上述顺序来进行的.那么,今天在我们讨论二叉树之前,我们先来讨论一种情形.一种操作:假设现在有一个数组,数组中的数据按照某

二叉树——查找两个任意节点的最近祖先

很久没有用过二叉树了,最近由于需要用到了,发现很多知识需要巩固了,中间涉及到一个算法就是找任意两个节点的最近祖先.通过本人回顾和演算,最终提出了下面一个方法,网上也有很多其他的方式实现,再次仅对自己好几个小时的工作作个记录和积累吧! 程序是用C语言写的,个人觉得如果用C#实现会更加方便. 首先是数据结构定义: [cpp] view plaincopyprint? typedef char TElemType; typedef bool Status; typedef struct BiTNode

分治法-折半查找和二叉树的相关特性

4.3 折半查找 对于有序数组的查找来说,折半查找是一种性能卓越的算法.它通过比较查找健K和数组中间元素A[m]来完成查找工作.如果它们相等,算法结束.否则,如果K<A[m],就对数组的左半部分执行该操作,如果K>A[m],则对数组的右半部分执行该操作. 折半查找是基于递归思想的,但也可以以迭代方式实现. 代码实现: /** * 折半查找(递归方式实现) * @author xiaofeig * @since 2015.9.16 * @param array 查找的目标数组 * @param

Python中的二叉树查找算法模块

问题 思路说明 二叉树查找算法,在开发实践中,会经常用到.按照惯例,对于这么一个常用的东西,Python一定会提供轮子的.是的,python就是这样,一定会让开发者省心,降低开发者的工作压力. python中的二叉树模块内容: BinaryTree:非平衡二叉树 AVLTree:平衡的AVL树 RBTree:平衡的红黑树 以上是用python写的,相面的模块是用c写的,并且可以做为Cython的包. FastBinaryTree FastAVLTree FastRBTree 特别需要说明的是:树

递归函数的设计--以二叉树查找为例

工作后发现,大学计算机课程里面的树结构相当有用,很多现实中的东西把它看成树就容易理解多了. ----大学舍友 最近和二叉树有关的代码频繁地打交道.由于函数的递归实现占用巨大的计算机运行时间(尤其是深层递归调用,存储函数参数的程序栈会占据很大的运行时间,参见图1),我的目的是将递归实现改为非递归的循环实现(以前的编程经验表明,两者的运行速度相差悬殊).本文以二叉树查找为例,对递归函数的设计进行分析说明,最后给出查找的非递归实现思路. 图1. 递归调用示意图 递归,就是函数调用自身的一种方式[1].

查找二,二叉树查找与2-3树红黑树

BST: 每个节点的键,都大于其左自述中的任意节点的键,而小于有字数的任意结点的键. 部分实现 get(Node x , Key key){ if(x == null) return null; cmp = key.compareTo(x.key); if(cmp<0) retrun get(x.right,key); else if(cmp>0) retrun get(x.left,key); else return x.val; } 2-3树红黑树: 属于平衡查找树,为了希望保持二分查找树

折半查找/二分查找 以及二叉树的 三种遍历方式

二分查找   线性查找 1.二分查找 public class BinarySearch { /** * 二分查找 * @param data * @return */ public int binarySearch(long[] data,long n) { //左右 端点 int left =0; int right =data.length-1; //中间元素 int mid=-1; while(left<right){ // 有两种情况 1.left = right 2. left>r

在路上---学习篇(一)Python 数据结构和算法 (5)二分查找、二叉树遍历

独白: 利用算法进行查找指定元素,最近学习二分查找和二叉树遍历.二分查找前提是在有序中进行查找,二叉树引入了树的概念.树的概念其中有许多小知识点,也是一种新的数据结构.还是之前的感悟,需了解其本质才会写出更好的算法. 二分查找 二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表.首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用