1、准备工作
- 二叉搜索树 Binary search tree
- 每个节点的值大于其左子树,小于其右子树(左小右大)
typedef struct BST{
int data;
struct BST* left;
struct BST* right;
}BstNode,*Bst;
typedef struct LNode {
BstNode* bst;
struct LNode *next;
}LNode;
typedef struct Queue{
LNode *front;
LNode *rear;
}Queue;
void Enqueue (BstNode* data,Queue **Q);
void Dequeue(Queue **Q);
2、插入(递归)
void Insert(Bst *root,int data){
if(*root == NULL){
BstNode *newnode = (BstNode *)malloc(sizeof( BstNode));
newnode->data = data;
newnode->left = NULL;
newnode->right = NULL;
*root = newnode;
}
else if(data<(*root)->data){
Insert( &((*root)->left), data);
}
else if(data>(*root)->data){
Insert( &((*root)->right),data);
}
}
3、查找
BstNode* Search(Bst root,int data){
BstNode *p = root;
while(1){
if(p == NULL){ return NULL; }
else if(p->data == data){ return p; }
else if(p->data>data){ p = p->left; }
else if(p->data<data){ p = p->right; }
}
}
4、返回树的高度(递归)
- 对于树的高度和深度说法不一,但我更倾向于这种
一个节点的高度 = 该节点到最底层节点的边数
一个节点的深度 = 该节点到根节点的边数
空树:节点的高度 = 深度 = -1
int FindHeight(Bst root){
BstNode * p = root;
if(p == NULL){
return -1;
}
int l = FindHeight(p->left);
int r = FindHeight(p->right);
return l>r?l+1:r+1;
}
5、二叉树的遍历(广度优先)
void PrintBST_BF(Bst root,Queue *Q){
BstNode *p = root;
if(p == NULL){
printf("空树\n");
return;
}
Enqueue(p,&Q);
printf("代码判断:");
while(Q->front != NULL){
printf("%d",Q->front->bst->data);
if(Q->front->bst->left != NULL){
Enqueue(Q->front->bst->left,&Q);
}
if(Q->front->bst->right != NULL){
Enqueue(Q->front->bst->right,&Q);
}
Dequeue(&Q);
}
printf("\n");
}
5、二叉树的遍历(深度优先)
- 当前节点root 左节点left 右节点right
root - left - right 前序遍历preorder
left - root - right中序遍历inorder
left - right - root 后序遍历postorder
void PrintBST_DF(Bst root,int type){
if(root == NULL) return;
if(type == 1){
printf("%d",root->data);
PrintBST_DF(root->left,1);
PrintBST_DF(root->right,1);
}
else if(type == 2){
PrintBST_DF(root->left,2);
printf("%d",root->data);
PrintBST_DF(root->right,2);
}
else if(type == 3){
PrintBST_DF(root->left,3);
PrintBST_DF(root->right,3);
printf("%d",root->data);
}
}
6、删除一个节点(递归 难点)
BstNode * Del(Bst root,int data){
if (root == NULL) return NULL;
if (data > root->data) root->right = Del(root->right,data);
else if(data < root->data) root->left = Del(root->left,data);
else{
if(root->left == NULL && root->right == NULL) {
free(root);
root = NULL;
}
else if(root->left == NULL){
BstNode *p = root;
root = root->right;
free(p);
}
else if(root->right== NULL){
BstNode *p = root;
root = root->left;
free(p);
}
else if(root->right != NULL && root->left != NULL){
root->data = root->left->data;
root->left = Del(root->left,root->data);
}
}
return root;
}
7、判断是否为二叉搜索树
- 节点区间判定
对于左节点: 当前节点的父节点的父节点 < 当前节点 < 当前节点的父节点
root->data < root->right->left->data < right->left->data
对于右节点: 当前节点的父节点的父节点 < 当前节点 < 当前节点的父节点
root->data >right->left->right->data > right->left->data
int IsBST(Bst root,int type){
if(type == 1){
return IsBST_IN(root,0);
}
else if(type == 2){
return IsBST_SE(root,0,1000);
}
else{
return -1;
}
}
int IsBST_IN(Bst root,int pre){
if(root == NULL) return 1;
if(IsBST_IN(root->left,pre)){
if(root->data>pre){
pre = root->data;
return IsBST_IN(root->right,pre);
} else{
return 0;
}
}else{
return 0;
}
}
int IsBST_SE(Bst root,int min,int max){
if(root == NULL) return 1;
if (root->data > min && max > root->data) {
if (IsBST_SE(root->left, min, root->data)
&& IsBST_SE(root->right, root->data, max))
return 1;
else{
return 0;
}
} else {
return 0;
}
}
8、完整演示
#include <stdio.h>
#include <stdlib.h>
typedef struct BST{
int data;
struct BST* left;
struct BST* right;
}BstNode,*Bst;
typedef struct LNode {
BstNode* bst;
struct LNode *next;
}LNode;
typedef struct Queue{
LNode *front;
LNode *rear;
}Queue;
void Enqueue (BstNode* data,Queue **Q);
void Dequeue(Queue **Q);
void Insert(Bst *root,int data);
BstNode* Search(Bst root,int data);
int FindHeight(Bst root);
void PrintBST_BF(Bst root,Queue *Q);
void PrintBST_DF(Bst root,int type);
BstNode * Del(Bst root,int data);
int IsBST(Bst root,int type);
int IsBST_IN(Bst root,int pre);
int IsBST_SE(Bst root,int min,int max);
BstNode *FindInPrecursor(Bst root,int data);
int main() {
Bst root;
root = NULL;
int data[10] = {5,7,3,9,2,6,4,1,8,3};
for(int i = 0;i<9;i++){
Insert(&root,data[i]);
}
Queue *Q = (Queue *) malloc(sizeof(Queue));
Q->front = NULL;
Q->rear = NULL;
printf("树的高度为%d; ", FindHeight(root));
printf("查找 %d 返回地址:%p\n",data[9],Search(root,data[9]));
printf("\n深度优先遍历:理论 -> 实际 \n");
printf("前序:532147698 -> ");
PrintBST_DF(root,1);
printf("\n中序:123456789 -> ");
PrintBST_DF(root,2);
printf("\n后序:124368975 -> ");
PrintBST_DF(root,3);
printf("\n");
printf("广度优先遍历:理论 -> 实际 \n");
printf("537246918 -> ");
PrintBST_BF(root,Q);
printf("\n删除 %d\n",data[9]);
Del(root,data[9]);
PrintBST_BF(root,Q);
printf("查找 %d 返回地址:%p\n",data[9],Search(root,data[9]));
printf("\n判断是否为二叉搜索树:(是1 否0)\n");
printf("中序遍历判断:%d ",IsBST(root,1));
printf("节点区间判断:%d\n",IsBST(root,2));
int e = 4;
if( FindInPrecursor(root,e) != NULL){
printf("\n数据%d在中序遍历中的前驱节点为:%d\n",e,
FindInPrecursor(root,e)->data);
}
return 0;
}
void Enqueue (BstNode* data,Queue **Q){
LNode *tmp = (LNode *) malloc(sizeof(LNode));
tmp->bst = data;
tmp->next = NULL;
if( (*Q)->front == NULL){
(*Q)->front = tmp;
(*Q)->rear = tmp;
} else{
(*Q)->rear->next = tmp;
(*Q)->rear = tmp;
}
}
void Dequeue(Queue **Q){
if( (*Q)->front != NULL){
LNode *tmp = (*Q)->front;
(*Q)->front = (*Q)->front->next;
free(tmp);
}else{
printf("队为空\n");
return;
}
}
void Insert(Bst *root,int data){
if(*root == NULL){
BstNode *newnode = (BstNode *)malloc(sizeof( BstNode));
newnode->data = data;
newnode->left = NULL;
newnode->right = NULL;
*root = newnode;
}
else if(data<(*root)->data){
Insert( &((*root)->left), data);
}
else if(data>(*root)->data){
Insert( &((*root)->right),data);
}
}
BstNode* Search(Bst root,int data){
BstNode *p = root;
while(1){
if(p == NULL){ return NULL; }
else if(p->data == data){ return p; }
else if(p->data>data){ p = p->left; }
else if(p->data<data){ p = p->right; }
}
}
int FindHeight(Bst root){
BstNode * p = root;
if(p == NULL){
return -1;
}
int l = FindHeight(p->left);
int r = FindHeight(p->right);
return l>r?l+1:r+1;
}
void PrintBST_BF(Bst root,Queue *Q){
BstNode *p = root;
if(p == NULL){
printf("空树\n");
return;
}
Enqueue(p,&Q);
while(Q->front != NULL){
printf("%d",Q->front->bst->data);
if(Q->front->bst->left != NULL){
Enqueue(Q->front->bst->left,&Q);
}
if(Q->front->bst->right != NULL){
Enqueue(Q->front->bst->right,&Q);
}
Dequeue(&Q);
}
printf("\n");
}
void PrintBST_DF(Bst root,int type){
if(root == NULL) return;
if(type == 1){
printf("%d",root->data);
PrintBST_DF(root->left,1);
PrintBST_DF(root->right,1);
}
else if(type == 2){
PrintBST_DF(root->left,2);
printf("%d",root->data);
PrintBST_DF(root->right,2);
}
else if(type == 3){
PrintBST_DF(root->left,3);
PrintBST_DF(root->right,3);
printf("%d",root->data);
}
}
BstNode * Del(Bst root,int data){
if (root == NULL) return NULL;
if (data > root->data) root->right = Del(root->right,data);
else if(data < root->data) root->left = Del(root->left,data);
else{
if(root->left == NULL && root->right == NULL) {
free(root);
root = NULL;
}
else if(root->left == NULL){
BstNode *p = root;
root = root->right;
free(p);
}
else if(root->right== NULL){
BstNode *p = root;
root = root->left;
free(p);
}
else if(root->right != NULL && root->left != NULL){
root->data = root->left->data;
root->left = Del(root->left,root->data);
}
}
return root;
}
int IsBST(Bst root,int type){
if(type == 1){
return IsBST_IN(root,0);
}
else if(type == 2){
return IsBST_SE(root,0,1000);
}
else{
return -1;
}
}
int IsBST_IN(Bst root,int pre){
if(root == NULL) return 1;
if(IsBST_IN(root->left,pre)){
if(root->data>pre){
pre = root->data;
return IsBST_IN(root->right,pre);
} else{
return 0;
}
}else{
return 0;
}
}
int IsBST_SE(Bst root,int min,int max){
if(root == NULL) return 1;
if (root->data > min && max > root->data) {
if (IsBST_SE(root->left, min, root->data)
&& IsBST_SE(root->right, root->data, max))
return 1;
else{
return 0;
}
} else {
return 0;
}
}
BstNode *FindInPrecursor(Bst root,int data){
BstNode *c = Search(root,data);
if(c == NULL){
printf("数据 %d 不在二叉树中\n",data);
return NULL;
}
if (c->left != NULL){
c = c->left;
BstNode *p = c;
while(c != NULL){
p = c;
c = c->right;
}
return p;
}
else{
BstNode *a = root;
BstNode *p = NULL;
while (a != c){
if(a->data < data){
p = a;
a = a->right;
}
else {
a = a->left;
}
}
if(p == NULL){
printf("数据 %d 没有前驱节点\n",data);
}
return p;
}
}