C语言二叉树

二叉搜索树(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;
}

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值