数据结构二叉搜索树

 #include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10

typedef struct node
{
 int item;
 struct node *left;
 struct node *right;
}NODE;

typedef struct tree
{
 NODE *root;
 int size; 
}TREE;

typedef struct pair
{
 NODE *parent;
 NODE *child;
}PAIR;

void InitTree(TREE *ptree)
{
 ptree->root = NULL;
 ptree->size = 0;
}

bool TreeIsEmpty(const TREE *ptree)
{
 if(ptree->root == NULL)
  return true;
 else
  return false;
}

bool TreeIsFull(const TREE *ptree)
{
 if(ptree->size == MAXSIZE)
  return true;
 else
  return false;
}

int TreeItemCount(const TREE *ptree)
{
 return ptree->size;
}

static bool ToLeft(const int item1, const int item2)
{
 if(item1 <= item2)
  return true;
 else
  return false;
}

static bool ToRight(const int item1, const int item2)
{
 if(item1 <= item2)
  return true;
 else
  return false;
}

static NODE *MakeNode(const int item)
{
 NODE *new_node;
 new_node = (NODE *)malloc(sizeof(NODE));
 if(new_node != NULL)
 {
  new_node->item = item;
  new_node->left = NULL;
  new_node->right = NULL;
 }
 return new_node;
}

static void AddNode(NODE *new_node, NODE *root)
{
 if(ToLeft(new_node->item, root->item))
 {
  if((root->left)== NULL)
   root->left = new_node;
  else
   AddNode(new_node,root->left);
 }
 else if(ToRight(new_node, root->item))
 {
  if(root->right == NULL)
   root->right = new_node;
  else
   AddNode(new_node, root->right);
 }
 else
 {
  printf("loacation error in AddNode\n");
  exit(1);
 }
}

//注意ptr是指向目标节点的父节点(parent)指针成员(child)的地址即pair_ob.parent.child
static void DeleteNode(NODE **ptr)
{
 NODE *temp;
 puts((*ptr)->item);
 if((*ptr)->left == NULL)
 {
  temp = *ptr;
  *ptr = (*ptr)->right;
  free(temp);
 }
 else if((*ptr)->right == NULL)
 {
  temp = *ptr;
  *ptr = (*ptr)->left;
  free(temp);
 }
 else
 {
  for(temp = (*ptr)->left; temp->right != NULL; temp = temp->right)
  {
  }
  temp->right = (*ptr)->right;
  
  temp = *ptr;
  *ptr = (*ptr)->left;
  free(temp);
 }
}

static void DeleteAllNodes(NODE * root)

 NODE *pright;
 if(root != NULL)
 {
  pright = root->right;
  DeleteAllNodes(root->left);
  free(root);
  DeleteAllNodes(pright);
 }
}

void DeleteAll(TREE *ptree)
{
 if(ptree != NULL)
  DeleteAllNodes(ptree->root);
 ptree->root = NULL;
 ptree->size = 0;
}

//设计成返回包含两个指针的结构,一个指针指向包含该项目的节点,一个指向父节点。
static PAIR SeekItem(const int item, const TREE *ptree)
{
 PAIR look;
 look.parent = NULL;
 look.child = ptree->root;
 
 if(look.child == NULL)
  return look;
 while(look.child != NULL)
 {
  if(ToLeft(item,look.child.item))
  {
   look.parent = look.child;
   look.child = look.child->left;
  }
  else if(ToRight(item,look.child.item))
  {
   look.parent = look.child;
   look.child = look.child->right;
  }
  else
   break//如果前面都不是,则找到了,look.child是目标项目的地址
 }
 return look;
}

bool AddItem(const int item, TREE *ptree)
{
 NODE *new_node;
 if(TreeIsFull(ptree))
 {
  printf("Tree is full\n");
  return false;
 }
 if(SeekItem(pi,ptree).child != NULL)
 {
  printf("Attemped to add duplicate item\n");
  return false;
 }
 new_node = MakeNode(pi);
 if(new_node == NULL)
 {
  printf("canot create node\n");
  return false;
 }
 ptree->size++;
 if(ptree->root == NULL)
  ptree->root = new_node;
 else
  AddNode(new_node, ptree->root);
 return true;
}

bool DeleteItem(const int item, TREE *ptree)
{
 PAIR look;
 look = SeekItem(item, ptree);
 if(look.child == NULL)
  return false;
 if(look.parent == NULL)
  DeleteNode(&ptree->root);
 else if(look.parent->left == look.child)
  DeleteNode(&look.parent->left);
 else
  DeleteNode(&look.parent->right);
 ptree->size--;
 return true;
}

//遍历树,首先处理左子树,然后处理项目,最后处理右子树
static void InOrder(const NODE *root, void (*pfun)(int item))
{
 if(root != NULL)
 {
  InOrder(root->left, pfun);
  (*pfun)(root->item);
  InOrder(root->right, pfun);
 }
}

void Traverse(const TREE *ptree, void (*pfun)(int item))
{
 if(ptree != NULL)
  InOrder(ptree->root, pfun);
}

 

### 关于 PTA 平台上二叉搜索树的相关练习题及其解法 #### 了解二叉搜索树的基础概念 在深入探讨具体的练习之前,重要的是要理解什么是二叉搜索树(BST)。这是一种特殊的二叉树,在这种树中,对于任意节点而言,左子树中的所有键值小于该节点的键值;右子树中的所有键值大于该节点的键值[^1]。 #### 构建二叉搜索树 构建BST的过程涉及按照特定顺序插入新元素。每当有新的数值加入时,程序会从根部开始遍历整棵树直到找到合适的位置放置这个数。如果当前考察位置为空,则直接在此处创建一个新的叶子节点来容纳待插入的数据项。这一过程不仅有助于掌握基本的操作技能,而且可以增强对数据结构内部机制的认识。 #### 寻找共同祖先问题 当面对诸如“求两个指定节点之间的最低公共祖先”的挑战时,一种有效的方法是从根向下追踪路径直至遇到任一目标节点为止,并记录沿途访问过的每一个节点作为候选者。接着继续探索另一条分支并重复上述动作。最终对比两条路线所遇见过的所有节点集合,其中最深的那个交集成员即是答案所在之处[^3]。 ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def lowestCommonAncestor(root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': if not root or root == p or root == q: return root left_search_result = lowestCommonAncestor(root.left, p, q) right_search_result = lowestCommonAncestor(root.right, p, q) if left_search_result and right_search_result: return root elif left_search_result: return left_search_result else: return right_search_result ``` 此代码片段展示了如何实现寻找最小公共祖先的功能。它采用递归的方式分别检查左右两侧是否存在所需的目标节点p和q。一旦发现两者皆存在于不同方向之下,则说明当前处理的对象正是它们之间最近的一个共有前辈。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值