链式二叉树的基本操作

目录

链式二叉树的结构体

链式二叉树的创建

二叉树的前、中、后序遍历的实现(递归)

前序遍历

中序遍历

后序遍历

二叉树非空结点的数量

二叉树叶子结点的数量

二叉树第K层非空节点的数量

二叉树最大深度

二叉树的层序遍历

判断二叉树是否为完全二叉树


链式二叉树的结构体

typedef char BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType _data;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right;
}BTNode;

 

链式二叉树的创建

如通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树,其中‘#’表示该节点为空。本文采用前序遍历,递归的方式建立一颗链式二叉树。

BTNode* BuyBTNode(BTDataType x) {
	BTNode* node  = (BTNode*)malloc(sizeof(BTNode));
	assert(node);
	node->_data = x;
	node->_left = NULL;
	node->_right = NULL;
	return node;
}
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a,int* pi) {
	if (a[*pi] == '#') {
		(*pi)++;
		return NULL;
	}
	BTNode* root = BuyBTNode(a[(*pi)++]);
	root->_left = BinaryTreeCreate(a, pi);
	root->_right = BinaryTreeCreate(a, pi);
	return root;
}

 

该数组建立的二叉树如图所示。要注意的是i作为数组下标,传参要是它的地址,因为在递归的过程中,i的下标每建立一个结点都要往后移。二叉树构建过程如下图所示(只画出部分构建过程,剩下部分以此类推) 

 

二叉树的前、中、后序遍历的实现(递归)

前序遍历

void BinaryTreePrevOrder(BTNode* root) {
	if (root == NULL)
		return;
	printf("%c", root->_data);
	BinaryTreePrevOrder(root->_left);
	BinaryTreePrevOrder(root->_right);
}

前序遍历的递归过程如图所示

中序遍历和后序遍历以此类推。 

 

中序遍历

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root) {
	if (root == NULL)
		return;
	BinaryTreeInOrder(root->_left);
	printf("%c", root->_data);
	BinaryTreeInOrder(root->_right);
}

后序遍历

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root) {
	if (root == NULL)
		return;
	BinaryTreeInOrder(root->_left);
	BinaryTreeInOrder(root->_right);
	printf("%c", root->_data);
}

 

二叉树非空结点的数量

int BinaryTreeSize(BTNode* root) {
	return root == NULL ? 0 : 1 + BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right);
}

 非空结点计数递归过程如图所示

非空结点的递归过程如图所示

 

二叉树叶子结点的数量

// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root) {
	if (root == NULL) {
		return 0;
	}
	if (root->_left == NULL && root->_right == NULL) {
		return 1;
	}
	else {
		return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
	}
}

 叶子结点的递归过程如图所示

 

二叉树第K层非空节点的数量

// 二叉树第k层节点个数(转化为子树的k-1层的结点)
//如求第三层的节点数,就是求根节点左子树的第二层
int BinaryTreeLevelKSize(BTNode* root, int k) {
	assert(k >= 1);
	if (root == NULL) {
		return 0;
	}
	if (k == 1)
		return 1;
	return BinaryTreeLevelKSize(root->_left, k - 1) + BinaryTreeLevelKSize(root->_right, k - 1);

}

 假设K==3,求二叉树第三层的非空结点数量

 

二叉树最大深度

//求二叉树的最大深度
int MaxBinaryTreeDepth(BTNode* root) {
	if (root == NULL)
		return 0;
	int left = MaxBinaryTreeDepth(root->_left) + 1;
	int right = MaxBinaryTreeDepth(root->_right) + 1;
	return left > right ? left : right;
}

求二叉树最大深度的递归过程如图所示

 

二叉树的层序遍历

用队列的结构层序遍历,队列的数据类型是二叉树结点的结构指针类型,所以队列存储的是二叉树结点的地址。先进双亲结点,判断队列是否为空,非空,取出队头数据,并删除,将该结点的非空孩子结点进入队列。循环下去,直到队列为空。

typedef BTNode* QDataType;

// 链式结构:表示队列 
typedef struct QListNode
{
	struct QListNode* _next;
	QDataType _data;
}QNode;

// 队列的结构 
typedef struct Queue
{
	QNode* _front;
	QNode* _rear;
}Queue;
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root) {
	Queue q;
	QueueInit(&q);
	if (root == NULL) {
		return;
	}
	QueuePush(&q, root);

	while (QueueEmpty(&q) == 0) {
		BTNode* front = QueueFront(&q);
		printf("%c ", front->_data);
		QueuePop(&q);
		if (front->_left) {
			QueuePush(&q, front->_left);
		}
		if (front->_right) {
			QueuePush(&q, front->_right);
		}
	}
	printf("\n");
	QueueDestroy(&q);
	return;
}

 

判断二叉树是否为完全二叉树

运用队列来判断一颗二叉树是否为完全二叉树。先将非空的结点入队,判断队列是否为空,非空,取出队头数据,并删除,如果该结点非空,将该节点的孩子入队,循环下去。当队头数据为空时,中断循环,再依次取出队头数据,如果队列后面的数据出现非空结点,则该二叉数不是完全二叉树。完全二叉树在队列遇到空节点时,队列非空取出的结点都是空节点。

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root) {
	Queue q;
	QueueInit(&q);
	if (root == NULL) {
		return 0;
	}
	QueuePush(&q, root);
	while (QueueEmpty(&q) == 0) {
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front) {
			QueuePush(&q, front->_left);
			QueuePush(&q, front->_right);
		}
		else {
			break;//队头遇到空指针中断循环
		}
	}
	while (QueueEmpty(&q) == 0) {
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front) {
			QueueDestroy(&q);
			return 0;
		}
	}
	QueueDestroy(&q);
	return 1;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
叉树基本操作包括创建、遍历、插入、删除等。 下面是C语言实现链叉树基本操作示例代码: ```c #include <stdio.h> #include <stdlib.h> // 定义二叉树结构体 typedef struct TreeNode{ int data; struct TreeNode *left; struct TreeNode *right; }TreeNode, *Tree; // 创建二叉树 void createTree(Tree *t){ int data; scanf("%d", &data); if(data == -1){ // 输入-1表示该节点为空 *t = NULL; }else{ *t = (Tree)malloc(sizeof(TreeNode)); (*t)->data = data; createTree(&((*t)->left)); // 递归创建左子树 createTree(&((*t)->right)); // 递归创建右子树 } } // 先序遍历 void preOrder(Tree t){ if(t != NULL){ printf("%d ", t->data); preOrder(t->left); preOrder(t->right); } } // 中序遍历 void inOrder(Tree t){ if(t != NULL){ inOrder(t->left); printf("%d ", t->data); inOrder(t->right); } } // 后序遍历 void postOrder(Tree t){ if(t != NULL){ postOrder(t->left); postOrder(t->right); printf("%d ", t->data); } } // 插入节点 void insert(Tree t, int data){ if(t == NULL){ t = (Tree)malloc(sizeof(TreeNode)); t->data = data; t->left = NULL; t->right = NULL; }else{ if(data < t->data){ insert(t->left, data); }else{ insert(t->right, data); } } } // 查找节点 Tree search(Tree t, int data){ if(t == NULL){ return NULL; }else{ if(data == t->data){ return t; }else if(data < t->data){ return search(t->left, data); }else{ return search(t->right, data); } } } // 删除节点 Tree delete(Tree t, int data){ Tree p = t, q = NULL; while(p != NULL && p->data != data){ q = p; if(data < p->data){ p = p->left; }else{ p = p->right; } } if(p == NULL){ // 没有找到要删除的节点 return t; } if(p->left == NULL){ // 要删除的节点没有左子树 if(q == NULL){ // 要删除的节点是根节点 t = p->right; }else if(p == q->left){ // 要删除的节点是其父节点的左子节点 q->left = p->right; }else{ // 要删除的节点是其父节点的右子节点 q->right = p->right; } free(p); }else if(p->right == NULL){ // 要删除的节点没有右子树 if(q == NULL){ // 要删除的节点是根节点 t = p->left; }else if(p == q->left){ // 要删除的节点是其父节点的左子节点 q->left = p->left; }else{ // 要删除的节点是其父节点的右子节点 q->right = p->left; } free(p); }else{ // 要删除的节点有左右子树 Tree s = p->left, r = p; while(s->right != NULL){ r = s; s = s->right; } p->data = s->data; if(r == p){ // 要删除的节点的左子树没有右子树 r->left = s->left; }else{ // 要删除的节点的左子树有右子树 r->right = s->left; } free(s); } return t; } int main(){ Tree t = NULL; createTree(&t); // 创建二叉树 printf("先序遍历:"); preOrder(t); // 先序遍历 printf("\n中序遍历:"); inOrder(t); // 中序遍历 printf("\n后序遍历:"); postOrder(t); // 后序遍历 printf("\n"); int data; printf("请输入要插入的节点值:"); scanf("%d", &data); insert(t, data); // 插入节点 printf("中序遍历:"); inOrder(t); // 中序遍历 printf("\n请输入要查找的节点值:"); scanf("%d", &data); Tree node = search(t, data); // 查找节点 if(node != NULL){ printf("找到了节点:%d\n", node->data); }else{ printf("没有找到节点:%d\n", data); } printf("请输入要删除的节点值:"); scanf("%d", &data); t = delete(t, data); // 删除节点 printf("中序遍历:"); inOrder(t); // 中序遍历 return 0; } ``` 以上代码实现了创建二叉树、先序遍历、中序遍历、后序遍历、插入节点、查找节点、删除节点等操作

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值