BST平衡二叉树相关
对于一些结构的先行说明
才发现vscode选中变量名按下F2可以替换所有原来有误变量,方便)
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>typedef struct BSTNode
{int data;struct BSTNode* left,*right;
}BSTNode;//这个队列结点的话,我们就存指向树节点的指针
//所以其实我们会发现,如果用typedef事先对data的元素类型定义为任意,其实也就跟c++,java里的泛型差不多了
typedef struct Node
{BSTNode* data;struct Node* next;
}Node;typedef struct Queue
{Node* front;Node* rear;
}Queue;此处是一些basic
BSTNode* createNode(int data)
{BSTNode* newNode=(BSTNode*)malloc(sizeof(BSTNode));newNode->data=data;newNode->left=NULL;newNode->right=NULL;return newNode;
}//这里用二重指针是因为,如果只使用单指针root的话,只是局部变量,若如此返回值应该是Node*
void insertNode(BSTNode** root,int data)
{if(*root==NULL) *root=createNode(data);else if(data<= (*root)->data) insertNode(&((*root)->left),data);else insertNode(&((*root)->right),data);
}bool search(BSTNode* root,int data)
{if(root==NULL) return false;else if(data<=root->data) return search(root->left,data);else return search(root->right,data);
}//BST就是平衡二叉树,左子树最大值一定不大于根节点,右子树最小值一定不小于根节点
//显然一直往左下方走就能找到最小的
//这里为什么用单指针,那当然是因为我们又不需要改变原有的树,所以当成局部变量就好了
BSTNode* findMin(BSTNode* root)
{if(root == NULL) return root;while(root->left!=NULL){root=root->left;}return root;
}BSTNode* findTarget(BSTNode* root,int data)
{if(root==NULL) return root;if(root->data==data) return root;else if(root->data >data) return findTarget(root->left,data);else return findTarget(root->right,data);
}int findHeight(BSTNode* root)
{if(root==NULL) return -1; //这里是-1是把深度按照边数来定义,抵消最后的+1,按照结点数的话也可以是0return max(findHeight(root->left),findHeight(root->right))+1; //显然,+1是因为要加上连接左右子树的那条边
}需要烧烤画图的部分
void initQueue(Queue* q)
{q->front=q->rear=(Queue*)malloc(sizeof(Queue)); //嗯 这里已经隐含了初始队列空两指针指向一个地址了if(!q->front) exit(1);q->front->next=NULL; //这里设置一个带头结点的链表,用于后面判断队列空
}//画图会非常好理解
void pushQueue(Queue* q,BSTNode* data)
{Node* newNode=(Node*)malloc(sizeof(Node));if(!newNode) exit(1);newNode->data=data;newNode->next=NULL;q->rear->next=newNode; //让新结点和原链表接起来q->rear=newNode; //移动尾指针
}BSTNode* getFront(Queue q)
{return q.front->next->data;
}void popQueue(Queue* q)
{if(q->front==q->rear) exit(1);Node* current=q->front->next;q->front->next=current->next;if(q->rear==current) q->rear=q->front;free(current);
}bool emptyQueue(Queue q)
{if(q.front==q.rear) return true;else return false;
}void leverOrder(BSTNode* root)
{if(root==NULL) return;Queue q;initQueue(&q);pushQueue(&q,root);while(!emptyQueue){BSTNode* current=getFront(q);printf("%d ",current->data);if(current->left!=NULL) pushQueue(&q,current->left);if(current->right!=NULL) pushQueue(&q,current->right);popQueue(&q);}
}//判断一棵树是不是BST,就是看符不符合定义,左子树严格小于根,右子树严格大于根
//所以其实应该对一些重复数据做额外处理的
//这里的话,其实就是靠定义来缩小向下每个结点的定义域,来减小成本
bool isBST(BSTNode* root,int minValue,int maxValue) //这里一般就用无穷小和无穷大
{ if(root==NULL) return true;if(root->data <minValue&& root->data> maxValue&&isBST(root->left,root->data,maxValue)&&isBST(root->right,minValue,root->data)) //左子最大与右子最小return true;else return false;
}void deleteBST(BSTNode** root,int data)
{if(*root==NULL) return;else if(data< (*root)->data) deleteBST(&((*root)->left),data);else if(data> (*root)->data) deleteBST(&((*root)->right),data);//这里往上是还没有找到目标时的递归else{if((*root)->left==NULL&&(*root)->right) //叶子结点直接删就好了{free(*root);root=NULL; //别忘了把指针的指针置空return;}else if((*root)->left!=NULL) //只有一个孩子的享受全部家产{BSTNode* temp=*root;*root=(*root)->right;free(temp);}else if((*root)->right!=NULL){BSTNode* temp=*root;*root=(*root)->left;free(temp);}else //有两个孩子的话,在一群高手中找个相对菜的把左子树的top1碾压一下{BSTNode* temp=findMin((*root)->right);(*root)->data=temp->data;deleteBST(&((*root)->right),temp->data);}}
}//在不改变树结点的结构的时候,按需找到想要的结点的后继
//这里和线索化的区别是,都有后继,同理其实也能找到前驱
BSTNode* getSuccessor(BSTNode* root,int data)
{BSTNode* current=findTarget(root,data);if(current==NULL) return NULL;//这里我们要看当前结点有没有右子//如果有右子的话,在右子中找最左下的,那个就是要的后继if(current->right != NULL) return findMin(root->right);//那如果没有右子的话,祖先结点和后继结点就要更新了else{BSTNode* successor=NULL;BSTNode* ancestor=root;while (ancestor!=current) //如果祖先结点还没到达当前结点{//向下的时候,我们要分成向左走和向右走讨论//因为如果向左走,说明当前结点是第一次访问,反之则是第二次(中序 左根右)//画图容易知道,对于没有右子的,后继应该是上一个只访问过一次的祖先结点if(current->data <ancestor->data){successor =ancestor;ancestor =ancestor->left;}else ancestor=ancestor->right;}return successor;}
}