二叉搜索树(BST)
每个子节点最多只有两个子节点,并且两个子节点要按照一定顺序排列左节点和右节点
c语言具体实现
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct node_tree
{
int data;
struct node_tree *l,*r;
}tree,*linktree;
linktree new_node(int num)
{
linktree ne = (linktree)malloc(sizeof(tree));
if(ne != NULL)
{
ne->data = num;
ne->l = ne->r = NULL;
}
return ne;
}
linktree insert_tree(linktree root, linktree ne)
{
if(root == NULL)
return ne;
if(ne->data < root->data)
root->l = insert_tree(root->l, ne);
else
root->r = insert_tree(root->r, ne);
return root;
}
linktree remove_tree(linktree root, int num)
{
if(root == NULL)
return NULL;
if(num < root->data)
root->l = remove_tree(root->l, num);
else if(num > root->data)
root->r = remove_tree(root->r, num);
else
{
linktree tmp;
if(root->l != NULL)
{
for(tmp = root->l; tmp->r != NULL; tmp = tmp->r);
root->data = tmp->data;
root->l = remove_tree(root->l, tmp->data);
}
else if(root->r != NULL)
{
for(tmp = root->r; tmp->l != NULL; tmp = tmp->l);
root->data = tmp->data;
root->r = remove_tree(root->r, tmp->data);
}
else
{
free(root);
return NULL;
}
}
return root;
}
int main()
{
linktree root = NULL;
int n;
while(1)
{
scanf("%d", &n);
if(n == 0)
break;
linktree ne = new_node(n);
root = insert_tree(root, ne);
}
while(1)
{
scanf("%d", &n);
if(n == 0)
break;
root = remove_tree(root, n);
}
return 0;
}
前、中、后序遍历(递归方式)
//树的前、中、后遍历 递归
void bianli(struct TreeNode *root, int *num, int *size)
{
if(root == NULL)
return;
/*前序遍历
num[(*size)++] = root->val;
bianli(root->left, num, size);
bianli(root->right, num, size);
*/
/*中序遍历
bianli(root->left, num, size);
num[(*size)++] = root->val;
bianli(root->right, num, size);
*/
/*后序遍历
bianli(root->left, num, size);
bianli(root->right, num, size);
num[(*size)++] = root->val;
*/
}
int* postorderTraversal(struct TreeNode* root, int* returnSize){
*returnSize = 0;
int *num = malloc(sizeof(int) * 100);
bianli(root, num, returnSize);
return num;
}
前、中、后序遍历(非递归)
//树的前、中、后遍历 非递归
struct TreeNode *a[20];
int top = -1;
//前序遍历
void bianli(struct TreeNode* root)
{
struct TreeNode *p;
push(root);
while(top != -1)
{
p = gettop(a);
pop();
while(p)
{
printf("root->val");
if(p->rchild)
push(a, p->rchild);
p = p->lchild;
}
}
}
//中序遍历 1
void bianli(struct TreeNode *root)
{
struct TreeNode *p;
push(root);
while(top != -1)
{
while((p = gettop()) && p)
{
push(p->lchild);
}
pop();
if(top != -1)
{
p = gettop();
pop();
printf(p->val);
push(p->rchild);
}
}
}
//中序遍历 2
void bianli(struct TreeNode *root)
{
struct TreeNode *p = root;
while(p || top != -1)
{
if(p)
{
push(p);
p = p->lchild;
}
else
{
p = gettop();
pop();
printf(p->val);
p = p->rchild;
}
}
}
//后序遍历
struct SNode
{
struct TreeNode *p;
int tag;
}SNode;
SNode a[20];
void bianli(struct TreeNode *root)
{
struct TreeNode *p = root;
int tag;
SNode sdata;
while(p || top != -1)
{
while(p)
{
sdata.p = p;
sdata.tag = 0;
push(sdata);
p = p->lchild;
}
sdata = a[top];
pop();
p = sdata.p;
tag = sdata.tag;
if(tag == 0)
{
sdata.p = p;
sdata.tag = 1;
push(sdata);
p = p->rchild;
}
else
{
printf(p->val);
p = NULL;
}
}
}
层遍历
//层遍历
struct TreeNode *a[20];
int front = 0, rear = 0;
void push(struct TreeNode *root)
{
a[rear++] = root;
}
struct TreeNode * pop()
{
return a[front++];
}
void bianli(struct TreeNode *root)
{
struct TreeNode *p;
push(root);
while(front < rear)
{
p = pop();
printf(p->val);
if(p->lchild)
push(p->lchild);
if(p->rchild)
push(p->rchild);
}
}
AVL(二叉平衡搜索树)的概念和思路
- 任意一个节点 左子树高度 - 右子树高度 <= 1
- 要想让BST保持平衡,必须在每一次插入、删除之后,检查是否其左右子树满足平衡的定义
- 如果不满足,就做“旋转”操作,使其恢复平衡
- 加入以上平衡策略算法后的BST,称为AVL,AVL是一种绝对平衡的二叉树
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX(a,b) (a)>(b)?(a):(b)
typedef struct node_tree
{
int data;
struct node_tree *l,*r;
int height;
}tree,*linktree;
int height(linktree root)
{
if(root == NULL)
return 0;
return root->height;
}
linktree new_node(int num)
{
linktree ne = (linktree)malloc(sizeof(tree));
if(ne != NULL)
{
ne->data = num;
ne->l = ne->r = NULL;
}
return ne;
}
linktree left_rotate(linktree root)
{
if(root == NULL)
return NULL;
linktree tmp = root->r;
root->r = tmp->l;
tmp->l = root;
root->height = MAX(height(root->l), height(root->r)) + 1;
tmp->height = MAX(height(tmp->l), height(tmp->r)) + 1;
return tmp;
}
linktree right_rotate(linktree root)
{
if(root == NULL)
return NULL;
linktree tmp = root->l;
root->l = tmp->r;
tmp->r = root;
root->height = MAX(height(root->l), height(root->r)) + 1;
tmp->height = MAX(height(tmp->l), height(tmp->r)) + 1;
return tmp;
}
linktree left_right_rotate(linktree root)
{
root->l = left_rotate(root->l);
return right_rotate(root);
}
linktree right_left_rotate(linktree root)
{
root->r = right_rotate(root->r);
return left_rotate(root);
}
linktree insert_tree(linktree root, linktree ne)
{
if(root == NULL)
return ne;
if(ne->data < root->data)
root->l = insert_tree(root->l, ne);
else
root->r = insert_tree(root->r, ne);
//插入过后判断树的平衡性
//左子树不平衡
if(height(root->l) - height(root->r) >= 2)
{
//左左不平衡
if(ne->data < root->l->data)
{
root = right_rotate(root);
}
//左右不平衡
else if(ne->data > root->l->data)
{
root = left_right_rotate(root);
}
}
//右子树不平衡
if(height(root->r) - height(root->l) >= 2)
{
if(ne->data > root->r->data)
{
root = left_rotate(root);
}
else if(ne->data < root->r->data)
{
root = right_left_rotate(root);
}
}
root->height = MAX((height(root->l)), (height(root->r))) + 1;
return root;
}
linktree remove_tree(linktree root, int num)
{
if(root == NULL)
return NULL;
if(num < root->data)
root->l = remove_tree(root->l, num);
else if(num > root->data)
root->r = remove_tree(root->r, num);
else
{
linktree tmp;
if(root->l != NULL)
{
for(tmp = root->l; tmp->r != NULL; tmp = tmp->r);
root->data = tmp->data;
root->l = remove_tree(root->l, tmp->data);
}
else if(root->r != NULL)
{
for(tmp = root->r; tmp->l != NULL; tmp = tmp->l);
root->data = tmp->data;
root->r = remove_tree(root->r, tmp->data);
}
else
{
free(root);
return NULL;
}
}
//删除节点后,判断平衡性
//左子树不平衡
if(height(root->l) - height(root->r) >= 2)
{
//左左不平衡
if(height(root->l->l) > height(root->l->r))
{
root = right_rotate(root);
}
//左右不平衡
else
{
root = left_right_rotate(root);
}
}
//右子树不平衡
if(height(root->r) - height(root->l) >= 2)
{
if(height(root->r->r) > height(root->r>l))
{
root = left_rotate(root);
}
else
{
root = right_left_rotate(root);
}
}
root->height = MAX((height(root->l)), (height(root->r))) + 1;
return root;
}
int main()
{
linktree root = NULL;
int n;
while(1)
{
scanf("%d", &n);
if(n == 0)
break;
linktree ne = new_node(n);
root = insert_tree(root, ne);
}
while(1)
{
scanf("%d", &n);
if(n == 0)
break;
root = remove_tree(root, n);
}
return 0;
}