数据结构--二叉树的基本操作实现(链式)

本文详细介绍了二叉树的各种操作,包括通过前序遍历构建二叉树、销毁二叉树、计算节点个数、叶子节点个数、第k层节点个数、查找节点、遍历(前序、中序、后序、层序)以及判断是否为完全二叉树。同时提供了递归和非递归的遍历方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉树

功能包括:
// 通过前序遍历的数组,例如:"ABD##E#H##CF##G##"构建二叉树
// 二叉树销毁
// 二叉树节点个数
// 二叉树叶子节点个数
// 二叉树第k层节点个数
// 二叉树查找值为x的节点
// 二叉树前序遍历
// 二叉树中序遍历
// 二叉树后序遍历
// 层序遍历
//判断是否为完全二叉树

注意:调用的栈跟队列没写出来,但是注意要把它们的typedef的元素改成BTNode*

//二叉树的链式实现
//二叉树的结构体
typedef char BTDataType;
typedef struct BinaryTreeNode
{
 BTDataType data;
 struct BinaryTreeNode* left;
 struct BinaryTreeNode* right;
}BTNode;
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int* pi) {
 if (a[*pi] != '#') {
  BTNode* root = (BTNode*)malloc(sizeof(BTNode));
  root->data = a[*pi];
  ++(*pi);
  root->left = BinaryTreeCreate(a, pi);
  ++(*pi);
  root->right = BinaryTreeCreate(a, pi);
  return root;
 }else {
  return NULL;
 }
}

// 二叉树销毁
void BinaryTreeDestory(BTNode** root) {
 BTNode* cur = *root;
 if (cur) {
  BinaryTreeDestory(&cur->left);
  BinaryTreeDestory(&cur->right);
  free(cur);
  *root = NULL;
 }
}

// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root) {
 if (root == NULL) {
  return 0;
 }
 //是叶子节点就返回1
 if (root->left == NULL && root->right == NULL) {
  return 1;
 }
 //把左右子树的返回来的1加起来
 return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

// 二叉树节点个数
int BinaryTreeSize(BTNode* root, int* num) {
 if (root) {
  //全局变量num遍历记录个数
  ++(*num);
  BinaryTreeSize(root->left, num);
  BinaryTreeSize(root->right, num);
 }
 return *num;
}

// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k) {
 if (root == NULL) {
  return 0;
 }
 if (k == 1) {
  return 1;
 }
 return BinaryTreeLevelKSize(root->left, k - 1) 
  + BinaryTreeLevelKSize(root->right, k - 1);
}

// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x) {
 BTNode* ret;
 if (root == NULL) {
  return NULL;
 }
 if (root->data == x) {
  return root;
 }
 //先查找左子树
 ret = BinaryTreeFind(root->left, x);
 if (ret) {  //左子树有x,则返回ret
  return ret;
 }
 //左没有就查找右边,不管什么值直接返回
 return BinaryTreeFind(root->right, x);
}

// 二叉树前序遍历--非递归
void BinaryTreePrevOrder(BTNode* root) {
 Stack st;
 StackInit(&st, 10);
 BTNode* cur = root;
 BTNode* top;
 while (cur || StackEmpty(&st) != 1) {
  while (cur) {
   //前序遍历访问当前节点
   printf("%c ", cur->data);
   //把当前节点压入栈
   StackPush(&st, cur);
   //当左子树为空就出这个循环
   cur = cur->left;
  }
  //获取栈顶元素并出栈
  top = StackTop(&st);
  StackPop(&st);
  //访问右子树
  cur = top->right;
 }
 printf("\n");
}

// 二叉树中序遍历--非递归
void BinaryTreeInOrder(BTNode* root) {
 Stack st;
 StackInit(&st, 10);
 BTNode* cur = root;
 BTNode* top;
 while (cur || StackEmpty(&st) != 1) {
  while (cur) {
   //把当前节点压入栈
   StackPush(&st, cur);
   //当左子树为空就出这个循环
   cur = cur->left;
  }
  //获取栈顶元素并出栈
  top = StackTop(&st);
  //中序遍历访问当前节点
  printf("%c ", top->data);
  StackPop(&st);
  //访问右子树
  cur = top->right;
 }
 printf("\n");
}

// 二叉树后序遍历--非递归
void BinaryTreePostOrder(BTNode* root) {
 Stack st;
 StackInit(&st, 10);
 BTNode* cur = root;
 BTNode* top;
 BTNode* prev = root;//上一次访问的位置
 while (cur || StackEmpty(&st) != 1) {
  while (cur) {
   //把当前节点压入栈
   StackPush(&st, cur);
   //当左子树为空就出这个循环
   cur = cur->left;
  }
  //获取栈顶元素并出栈
  top = StackTop(&st);
  if (top->right == NULL || top->right == prev) {
   //右子树为空或者已经访问,就打印这个节点
   printf("%c ", top->data);
   StackPop(&st);
   //更新prev
   prev = top;
  }
  else {
   //右子树还没有访问,先访问右子树
   cur = top->right;
  }
 }
 printf("\n");
}

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root) {
 Queue q;
 QueueInit(&q);
 //根元素先入队
 if (root) {
  QueuePush(&q, root);
 }
 //队列不为空就继续遍历
 while (QueueEmpty(&q) != 1) {
  //获取队头元素
  BTNode* front = QueueFront(&q);
  QueuePop(&q);
  //访问队头元素
  printf("%c ", front->data);
  //子节点入队,先左后右
  if (front->left) {
   QueuePush(&q, front->left);
  }
  if (front->right) {
   QueuePush(&q, front->right);
  }
 }
}

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNohde* root) {
 Queue q;
 QueueInit(&q);
 if (root) {
  QueuePush(&q, root);
 }
 while (QueueEmpty(&q) != 1) {
  //队头入队
  BTNode* front = QueueFront(&q);
  QueuePop(&q);
  //如果队头不为空,孩子入队
  if (front) {
   QueuePush(&q, front->left);
   QueuePush(&q, front->right);
  }
  else {
   //遇到第一个空节点,停止入队
   break;
  }
 }
 //判断队列中剩余元素是否都为空
 while (QueueEmpty(&q) != 1) {
  BTNode* front = QueueFront(&q);
  QueuePop(&q);
  if (front) {
   //剩余节点里有一个非空就不是完全二叉树
   return -1;
  }
 }
 //剩余节点全是空,则就是完全二叉树
 return 1;
}

//前序递归遍历
void preOrder(BTNode* root){
 if (root){
  //前序遍历,保存当前节点的值
  printf("%c ", root->data);
  preOrder(root->left);
  preOrder(root->right);
 }
}

//中序递归遍历
void InOrder(BTNode* root){
 if (root){
  InOrder(root->left);
  printf("%c ", root->data);
  InOrder(root->right);
 }
}

//后徐递归遍历
void postorderTraversal(BTNode* root){
 if (root){
  postorderTraversal(root->left);
  postorderTraversal(root->right);
  printf("%c ", root->data);
 }
}

int main() {
 char str[] = "abc##de#g##f###";
 int pi = 0;
 int num = 0;
 BTNode* root = BinaryTreeCreate(str, &pi);
 BinaryTreeSize(root, &num);
 printf("节点个数:%d\n", num);

 printf("前序递归遍历:\n");
 preOrder(root);
 printf("\n");
 printf("前序非递归遍历:\n");
 BinaryTreePrevOrder(root);
 
 printf("中序递归遍历:\n");
 InOrder(root);
 printf("\n");
 printf("中序非递归遍历\n");
 BinaryTreeInOrder(root);
 
 printf("后序递归遍历:\n");
 postorderTraversal(root);
 printf("\n");
 printf("后序非递归遍历\n");
 BinaryTreePostOrder(root);
 
 printf("层序遍历:\n");
 BinaryTreeLevelOrder(root);
 printf("\n");
 printf("是完全二叉树吗?%d\n",BinaryTreeComplete(root));
 return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值