数据结构之查找二叉树
前不久去腾讯笔试,居然几道数据结构方面的题目,让我情何以堪啊,都做不动,忘完了,趁着这里想找实习的地方,肯定还要笔试,所以复习一下。
注意:函数指针传递的用法
1.二叉树重要性质:
性质1:在二叉树的第i层上至多有2^(i-1)个节点(i >= 1)
性质2:深度为k的二叉树至多有2^(k-1)个节点(k >=1)
性质3:对于任意一棵二叉树T而言,其叶子节点数目为N0,度为2的节点数目为N2,则有
N0 = N2 + 1。
2. 二叉树的遍历
(1)前序遍历:先访问根节点,然后先序遍历左子树,最后先序遍历右子树;
(2)中序遍历:先序遍历左子树,然后访问根节点,最后先序遍历右子树;
(3)后序遍历:先序遍历左子树,然后先序遍历右子树,最后访问根节点;
假如有如下二叉树:
前序遍历:ABDHEICFGJ
中序遍历:HDBEIAFCGJ
后序遍历:HDIEBFJGCA
递归遍历具体实现代码:
void PreOrder(BTree T)
{
if(T)
{
PrintNode(T);
PreOrder(T->l);
PreOrder(T->r);
}
}
void MidOrder(BTree T)
{
if(T)
{
MidOrder(T->l);
PrintNode(T);
MidOrder(T->r);
}
}
void BehOrder(BTree T)
{
if(T)
{
BehOrder(T->l);
BehOrder(T->r);
PrintNode(T);
}
}
3. 二叉树存储结构设计:我们设计左子树的项目比根节点小
typedef struct item
{
int key;
}Item;
typedef struct BiNode
{
Item item;
int count;
struct BiNode *l;
struct BiNode *r;
}BNode, *PBNode, *BTree; // struct BiNode =Bnode
设计树的节点为结构体是为了以后扩展树节点做铺垫,设计PBNode表示节点指针,设计Btree树的结构。
4. 递归生成二叉树:compare()函数是比较两个节点之间项目大小的函数,这里以及后面的函数大都设计为参数为指针传递,因为指针大小一般比值参数小,所以这样设计可以节约栈空间,使用const关键字来修饰不变的变量从而增强程序的健壮性。
int compare(const Item *item1, const Item *item2)
{
if(item1->key < item2->key)
return -1;
else if(item1->key == item2->key)
return 0;
else
return 1;
}
BTree Create(BTree T, const Item *item)
{
if(T == NULL)
{
if(!(T=(PBNode)malloc(sizeof(BNode)))) //一定是结构体类
perror("malloc error!");
T->item = *item;
T->count = 1;
T->l = NULL;
T->r = NULL;
}
else if(compare(&(T->item), item) == 1)
{
T->l = Create(T->l, item);
}
else if(compare(&(T->item), item) == 0)
{
T->count ++;
}
else
T->r = Create(T->r, item);
return T;
}
5. 设计树深度的函数和查找最大项节点,最小项节点函数
int Height(BTree T)
{
int h1, h2;
if(T == NULL)
{
return 0;
}
else
{
h1 = Height(T->l);
h2 = Height(T->r);
return max(h1,h2)+1; //函数也可以不再main 中声名而直接调用
}
}
PBNode FindMax(BTree T)
{
if(T->r == NULL)
return T;
else return FindMax(T->r);
}
PBNode FindMin(BTree T)
{
if(T->l == NULL)
return T;
else return FindMin(T->l);
}
6. 删除单节点函数
设计删除单节点函数时需要考虑两点:
(1) 删除的点为根节点:如果右子树为空,则直接将左子树的根节点直接设置为整棵树的根节点;如果非空,则把左子树挂载右子树最小项的左子树上。
情况1示例如下:
如果要删除根节点,则直接将左子树的根节点直接设置为整棵树的根节点,并且更新根节点。
情况2示例如下:
如果要删除根节点,则把左子树挂载右子树最左项即右子树最小值的左子树上,并且更新根节点。
(2) 删除节点不为根节点:找到需要删除的点的父节点,如果删除节点的右子树为空则直接将删除节点的子树挂载他的父节点上;如果删除节点的右子树不为空,则将删除节点的左子树挂载到右子树的最小项上,并把右子树挂在删除节点的父节点上面。
情况1示例如下:
需要删除节点值为3的节点,因为没有右子树,则直接将删除节点的子树挂载他的父节点上。
情况2示例如下:
需要删除节点值为3的节点,因为有右子树,则将删除节点的左子树挂载到右子树的最小项上,并把右子树挂在删除节点的父节点上面。
BTree DeteleNode(BTree T, const Item *item)
{
PBNode fnode = NULL;
PBNode node = NULL, temp = NULL;
int dir = 0;
node = FindNode(T, item);//查找符合条件节点
if(node == T)//如果删除的点为根节点
{
printf("root delete \n");
fnode = FindMin(T->r);//找到根节点右子树最小值
if(fnode == NULL)//如果右子树为空 则将左子树直接设为根节点
{
return node->l;
}
fnode->l = node->l;
fnode = node->r;
free(node);
return fnode;//注意返回最新的根节点的指针
}
else if(node == NULL)
{
printf("not find the item\n");
}
else
{
fnode = FindFNode(T, node, &dir);
//方向1 代表左子树 2代表右子树
if(node->r == NULL)
{
if(dir == 1)
{
fnode->l = node->l;
}
else
{
fnode->r = node->l;
}
}
else
{
if(dir == 1)
{
fnode->l = node->r;
node->r->l = node->l;
}
else
{
fnode->r = node->r;
node->r->l = node->l;
}
}
free(node);
return T;
}
}
7. 实现二叉树所有代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#define max(a,b) a>b ? a : b
#define min(a,b) a<b ? a : b
typedef struct item
{
int key;
}Item;
typedef struct BiNode
{
Item item;
int count;
struct BiNode *l;
struct BiNode *r;
}BNode, *PBNode, *BTree; // struct BiNode =BNode
int compare(const Item *item1, const Item *item2)
{
if(item1->key < item2->key)
return -1;
else if(item1->key == item2->key)
return 0;
else
return 1;
}
BTree Create(BTree T, const Item *item)
{
if(T == NULL)
{
if(!(T=(PBNode)malloc(sizeof(BNode)))) //一定是结构体类
perror("malloc error!");
T->item = *item;
T->count = 1;
T->l = NULL;
T->r = NULL;
}
else if(compare(&(T->item), item) == 1)
{
T->l = Create(T->l, item);
}
else if(compare(&(T->item), item) == 0)
{
T->count ++;
}
else
T->r = Create(T->r, item);
return T;
}
void PrintItem(const Item * const item)
{
printf("key = %d ", item->key);
}
void PrintNode(const PBNode node)
{
PrintItem(&node->item);
printf("count is %d\n", node->count);
}
void PreOrder(BTree T)
{
if(T)
{
PrintNode(T);
PreOrder(T->l);
PreOrder(T->r);
}
}
void MidOrder(BTree T)
{
if(T)
{
MidOrder(T->l);
PrintNode(T);
MidOrder(T->r);
}
}
void BehOrder(BTree T)
{
if(T)
{
BehOrder(T->l);
BehOrder(T->r);
PrintNode(T);
}
}
int Height(BTree T)
{
int h1, h2;
if(T == NULL)
{
return 0;
}
else
{
h1 = Height(T->l);
h2 = Height(T->r);
return max(h1,h2)+1; //函数也可以不再main 中声名而直接调用
}
}
PBNode FindMax(BTree T)
{
if(T->r == NULL)
return T;
else return FindMax(T->r);
}
PBNode FindMin(BTree T)
{
if(T->l == NULL)
return T;
else return FindMin(T->l);
}
PBNode FindNode(const BTree T, const Item *item)
{
if(T)
{
if(compare(&T->item, item) == 0 )
{
return T;
}
else if (compare(&T->item, item) == 1 )
{
return FindNode(T->l, item);
}
else
return FindNode(T->r, item);
}
return NULL;
}
PBNode FindFNode(const BTree T, const PBNode node, int *dir)
{
PBNode my;
if(T->l == node)
{
*dir = 1;
return T;
}
else if(T->r == node)
{
*dir = 2;
return T;
}
else
{
my = FindFNode(T->l, node, dir);
if(my == NULL)
return FindFNode(T->r, node, dir);
else
return my;
}
return NULL;
}
BTree DeteleNode(BTree T, const Item *item)
{
PBNode fnode = NULL;
PBNode node = NULL, temp = NULL;
int dir = 0;
node = FindNode(T, item);
if(node == T)
{
printf("root delete \n");
fnode = FindMin(T->r);
if(fnode == NULL)
{
return node->l;
}
fnode->l = node->l;
fnode = node->r;
free(node);
return fnode;
}
else if(node == NULL)
{
printf("not find the item\n");
}
else
{
fnode = FindFNode(T, node, &dir);
//方向1 代表左子树 2代表右子树
if(node->r == NULL)
{
if(dir == 1)
{
fnode->l = node->l;
}
else
{
fnode->r = node->l;
}
}
else
{
if(dir == 1)
{
fnode->l = node->r;
node->r->l = node->l;
}
else
{
fnode->r = node->r;
node->r->l = node->l;
}
}
free(node);
return T;
}
}
void DeleteAll(BTree *T)
{
if(*T)
{
if((*T)->l == NULL && (*T)->r == NULL)
{
free(*T);
*T = NULL;
return ;
}
if((*T)->l != NULL)
DeleteAll(&(*T)->l);
if((*T)->r != NULL)
DeleteAll(&(*T)->r);
}
return ;
}
void DeleteAll(BTree T)
{
if(T)
{
if((T)->l == NULL && (T)->r == NULL)
{
free(T);
return ;
}
if(T->l != NULL)
DeleteAll(T->l);
if(T->r != NULL)
DeleteAll(T->r);
}
return ;
}
static void DeleteAllNodes(BTree T)
{
PBNode pright;
if(T != NULL)
{
pright = T->r;
DeleteAllNodes(T->l);
free(T);
DeleteAllNodes(pright);
}
}
int main(void)
{
int tHeight,b,x;
Item item;
PBNode node = NULL;
BTree t = NULL;
int chose = 0;
while(1)
{
printf("1.create tree(-1 exit)\n");
printf("2.preorder travser\n");
printf("3.miderorder travser\n");
printf("4.beherorder travser\n");
printf("5.tree height\n");
printf("6.find key = x:\n");
printf("7.delete key = x\n");
printf("8.delete all\n");
printf("9.find min and max\n");
printf("0.exit\n");
scanf("%d", &chose);
switch(chose)
{
case 1:
while(1)
{
scanf("%d", &(item.key));
if(item.key == -1)
break;
t=Create(t,&item); //也用递归 创建
}
break;
case 2:
PreOrder(t);
printf("\n");
break;
case 3:
MidOrder(t);
printf("\n");
break;
case 4:
BehOrder(t);
printf("\n");
break;
case 5:
tHeight = Height(t);
printf("\n tree height is %d\n",tHeight);
break;
case 6:
printf("\ninput the x to find :");
scanf("%d",&x );
item.key = x;
node = FindNode(t,&item);
if(node == NULL)
printf("not find \n");
else
{
PrintNode(node);
}
printf("\n");
break;
case 7:
printf("\ninput the x to delete:");
scanf("%d",&x );
item.key = x;
node = FindNode(t,&item);
if(node == NULL)
printf("not find \n");
else
{
PrintNode(node);
t = DeteleNode(t, &item);
}
printf("\n");
break;
case 8:
// DeleteAll(&t);
DeleteAllNodes(t);
// DeleteAll(t);
t = NULL;
break;
case 9:
node = FindMax(t);
PrintNode(node);
node = FindMin(t);
PrintNode(node);
break;
case 0:
break;
}
if(chose == 0)
break;
}
return 0;
}