二叉树实现

二叉树的链式结构
二叉树是一种特殊的树形结构,由根节点加上左右两棵子树组成,每个节点最多有两棵子树,不存在度大于2的节点。没有节点存在时也称为空二叉树。
二叉树不适合顺序存储,顺序结构只包含有效元素,没法确定哪个节点有还是没有左右孩子这层关系。链式结构更适合建立二叉树。

二叉树有双亲表示法,孩子表示法,孩子兄弟表示法等,这里实现用的是孩子表示法,即节点中表示出与其孩子的关系

创建一个二叉树节点的结构,left指针指向左孩子,right指向右孩子

typedef int BDatatype;

typedef struct BTNode {
	BDatatype data;
	struct BTNode* left;
	struct BTNode* right;
}BTNode;

给到一个序列, -1表示空值,int array[] = { 1,2,3,-1,-1,-1,4,5,-1,-1,6};

二叉树的创建,
首先给出创建一个节点的方法
然后用index从数组第0号元素开始,遇到不是空值的数据就为该值创建一个节点,先创建的是根节点,然后递归创建左子树右子树,这个顺序是先序的顺序。invalid表示传入的空值。

BTNode* BuyBinaryTreeNode(BDatatype data) {
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL) {
		assert(0);
		return NULL;
	}                                                   
	node->data = data;
	node->left = node->right = NULL;
	return node;
}
BTNode* _CreateBinaryTree(BDatatype array[], int size, int* index,BDatatype invalid) {
	BTNode* root = NULL;
	if (*index < size && invalid != array[*index]) {
		root = BuyBinaryTreeNode(array[*index]);
		++(*index);
		root->left = _CreateBinaryTree(array, size, index, invalid);
		++(*index);
		root->right = _CreateBinaryTree(array, size,index, invalid);
	}
	return root;
}
BTNode* CreateBinaryTree(BDatatype array[], int size, BDatatype invalid) {
	int index = 0;
	return _CreateBinaryTree(array, size, &index, invalid);
}

二叉树的先序遍历
从根节点开始,再遍历左子树再遍历右子树

void PreOrder(BTNode* root) {
	if(root) {
		printf("%d ", root->data);
		PreOrder(root->left);
		PreOrder(root->right);
	}
}

中序遍历
左子树->根->右子树

void InOrder(BTNode* root) {
	if (root) {
		InOrder(root->left);
		printf("%d ", root->data);
		InOrder(root->right);
	}
}

后序遍历
左子树->右子树->根

void PostOrder(BTNode* root) {
	if (root) {
		PostOrder(root->left);
		PostOrder(root->right);
		printf("%d ", root->data);
	}
}

层序遍历
二叉树的层序遍历用到了队列的特性,先创建一个队列,从根节点开始入队列,用一个指针指向队头元素,如果该节点的左孩子存在,将左孩子入队列,接下来判断右孩子,如果右孩子存在,将右孩子也入队列,每次打印队头元素,然后将队头元素出队列再去找下一个。就实现了层序遍历。

void LeveOrder(BTNode* root) {
	Queue q;
	if (NULL == root) {
		return;
	}
	QueueInit(&q);
	QueuePush(&q, root);
	while (!QueueEmpty(&q)) {
		BTNode* cur = Queuefront(&q);
		printf("%d ", cur->data);
		if (cur->left) {
			QueuePush(&q, cur->left);
		}
		if (cur->right) {
			QueuePush(&q, cur->right);
		}
		QueuePop(&q);
	}
	QueueDestroy(&q);
}

二叉树销毁
后序遍历的规则来删除可以保证不破坏二叉树的特性,所以后续遍历找到一个节点就释放一个。

void BinaryTreeDestroy(BTNode** root) {
	if (NULL == *root) {
		return;
	}
	BinaryTreeDestroy(&(*root)->left);
	BinaryTreeDestroy(&(*root)->right);
	free(root);
	root = NULL;
}

求节点的个数
如果是空树则节点个数为0,不是的话根节点算一个,然后递归去找它的左子树和右子树,找到一个加一个。

int BinaryTreesize(BTNode* root) {
	if (NULL == root) {
		return 0;
	}
	return 1 + BinaryTreesize(root->left) + BinaryTreesize(root->right);
}

求叶子节点的个数
根据叶子节点的特性,它的左孩子和右孩子都不存在,直接递归找左子树和右子树中左孩子和右孩子都为空的节点。

int Binaerleafsize(BTNode* root) {
	if (NULL == root) {
		return 0;
	}
	//左右孩子都不存在,
	if (NULL == root->left && NULL == root->right) {
		return 1;
	}
	return Binaerleafsize(root->left) + Binaerleafsize(root->right);
}

求第K层的节点个数
根据二叉树的特性,一个节点最多只有左子树和右子树两个子树,一个二叉树有K层,它的至少一个子树有k-1层,所以递归去求左右子树中k-1层的节点个数,直到剩下根节点那一层就返回1。

int BinaryTreeLevelKSize(BTNode* root, int k) {
	if (NULL == root || k <= 0) {
		return 0;
	}
	if (k == 1) {
		return 1;
	}
	return BinaryTreeLevelKSize(root->left, k - 1) + 
		   BinaryTreeLevelKSize(root->right, k - 1);
 }

求数的高度,
递归求左子树高度,再递归求右子树高度, 哪个高,哪个就是二叉树的高度。

int BinaryTreeHeight(BTNode* root) {
	if (NULL == root) {
		return 0;
	}
	int hleft = BinaryTreeHeight(root->left)+1;
	int hright = BinaryTreeHeight(root->right)+1;
	if (hleft > hright) {
		return hleft;
	}
	else {
		return hright;
	}
}

查找值为x的节点
先将这个值与根节点中的data值比较,存在就返回,不存在再递归去左子树中找,没有就递归去右子树中找。

BTNode* BinaryTreeFind(BTNode* root, BDatatype x) {
	if (NULL == root) {
		return NULL;
	}
	if (x == root->data) {
		return root;
	}
	int ret = BinaryTreeFind(root->left, x);
	if (ret) {
		return ret;
	}
	else {
		return BinaryTreeFind(root->right, x);
	}
}

判断是不是完全二叉树
思路是找到树中第一个不饱和的节点,要满足完全二叉树的特性,那从该节点往后所有的节点都不能有孩子。借助队列的特性来实现,首先将根节点入队列,定义一个cur取到队头元素,如果左右孩子都存在,将它的左右孩子分别入队列,再删除队头元素,此时cur就指向队列中下一个元素,再进行判断,如果只有左孩子没有右孩子,那这个节点就是最后一个不饱和的节点,将标记置为1,进入判断语句中,如果这个节点之后的节点有一个孩子存在,那就不是完全二叉树。

int BinaryTreeComplete(BTNode* root) {
	//空树也是完全二叉树
	if (root == NULL) {
		return 1;
	}
	//层序检测检测 空树也是完全二叉树
	Queue q;
	int flag = 0;
	QueueInit(&q);
	QueuePush(&q, root);
	while (!QueueEmpty(&q)) {
		BTNode* cur = Queuefront(&q);
		if (flag) {
			if (cur->left || cur->right) {
				QueueDestroy(&q);
				return 0;
			}
		}
		else {
			if (cur->left && cur->right) {
				QueuePush(&q, cur->left);
				QueuePush(&q, cur->right);
			}
			//左孩子不空 右空
			else if (cur->left) {
				QueuePush(&q, cur->left);
				flag = 1;
			}
			else if (cur->right) {
				QueueDestroy(&q);
				return 0;
			}
			else {
				flag = 1;
			}
		}
	}
	QueuePop(&q);
	return 1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值