二叉树的基本操作

BinTree.h
​
#pragma once//防止头文件被重复引用

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>
#include "BinTree.h"
#include"stack.h"
#include"Queue.h"

//typedef int QDataType;
//extern struct BinTreeNode;
//typedef struct BinTreeNode BTNode;

#define QDataType pBTNode


typedef struct Node
{
	QDataType _data;//队列的数据类型
	struct Node* _pNext;//指向下一个结点
}Node,*pNode;
typedef struct Queue
{
	pNode _pHead;//指向队头的指针
	pNode _pTail;//指向队尾的指针
}Queue;
void QueueInit(Queue* q);//队列的初始化
pNode BuyNode(QDataType data);//创建新队列
void QueuePush(Queue* q, QDataType data);//入队列
void QueuePop(Queue* q);//出队列
QDataType QueueFront(Queue* q);//取队头元素
QDataType Queueback(Queue* q);//取队尾元素
int QueueSize(Queue* q);//获取队列中元素的个数
int QueueEmpty(Queue* q);//检测队列是否为空

​

 //stack.h

​
stack.h
#pragma once

#include<stdio.h>
#include<assert.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#include "BinTree.h"
#include"stack.h"
#include"Queue.h"
//typedef int DataType;//栈:后进先出
//typedef char DataType;

//extern struct BinTreeNode;
//typedef struct BinTreeNode BTNode;
//typedef pBTNode DataType;

#define DataType pBTNode

typedef struct stack
{
	DataType *_array;
	int _top; // 表示有效元素个数 栈顶位置 
	int _capacity; // 底层空间的总大小 栈底位置
}stack;

void stackInit(stack* s);//初始化
void stackPush(stack* s, DataType data);//入栈
void stackPop(stack* s);//出栈
DataType stackTop(stack* s);// 获取栈顶元素 
int stackSize(stack* s);//有效元素的个数
int stackEmpty(stack* s);// 检测栈是否为空
void stackPrint(stack *s);//输出
void stackBracket(stack* s, char *str); //括号匹配
void stackRPN(stack* s, char *str);//后缀表达式

​

//Queue.h 

​
Queue.h
#pragma once//防止头文件被重复引用

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>
#include "BinTree.h"
#include"stack.h"
#include"Queue.h"

//typedef int QDataType;
//extern struct BinTreeNode;
//typedef struct BinTreeNode BTNode;

#define QDataType pBTNode


typedef struct Node
{
	QDataType _data;//队列的数据类型
	struct Node* _pNext;//指向下一个结点
}Node,*pNode;
typedef struct Queue
{
	pNode _pHead;//指向队头的指针
	pNode _pTail;//指向队尾的指针
}Queue;
void QueueInit(Queue* q);//队列的初始化
pNode BuyNode(QDataType data);//创建新队列
void QueuePush(Queue* q, QDataType data);//入队列
void QueuePop(Queue* q);//出队列
QDataType QueueFront(Queue* q);//取队头元素
QDataType Queueback(Queue* q);//取队尾元素
int QueueSize(Queue* q);//获取队列中元素的个数
int QueueEmpty(Queue* q);//检测队列是否为空

​

//BinTree.c 

​
BinTree.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"BinTree.h"
#include "stack.h"
#include"Queue.h"
pBTNode BuyBTNode(BTDataType data)
{
	pBTNode pRoot = NULL;
    pRoot = (pBTNode)malloc(sizeof(BTNode));
	if (NULL == pRoot)
	{
		return NULL;
	}
	pRoot->_data = data;
	pRoot->_pLeft = NULL;
	pRoot->_pRight = NULL;
	return pRoot;
}
//二叉树的创建
void _CreatNode(pBTNode* pRoot, BTDataType array[], int size, int* index, BTDataType invaild)
{
	assert(pRoot);
	if (*index < size && array[*index] != invaild)
	{
		//根
		*pRoot = BuyBTNode(array[*index]);
		//左孩子
		++(*index);
		_CreatNode(&(*pRoot)->_pLeft, array, size, index, invaild);
		//右孩子
		++(*index);
		_CreatNode(&(*pRoot)->_pRight, array, size, index, invaild);
	}
}
void CreatNode(pBTNode* pRoot, BTDataType array[], int size, BTDataType invaild)
{
	int index = 0;
	_CreatNode(pRoot, array, size, &index, invaild);
}
//二叉树的拷贝
pBTNode CopyBinTree(pBTNode pRoot)
{
	pBTNode pNewNode = NULL;
	pNewNode = (pBTNode)malloc(sizeof(BTNode));
	if (NULL == pNewNode)
	{
		return NULL;
	}
	//拷贝根
	pNewNode = BuyBTNode(pRoot->_data);
	//拷贝左子树
	if (pRoot->_pLeft)
	{
		pNewNode->_pLeft = CopyBinTree(pRoot->_pLeft);
	}
	//拷贝右子树
	if (pRoot->_pRight)
	{
		pNewNode->_pRight = CopyBinTree(pRoot->_pRight);
	}
	return pNewNode;
}
//二叉树的打印
void printBinTree(pBTNode pRoot)
{
	//assert(pRoot);
	if (NULL == pRoot)
	{
	  return;
	}
	if (pRoot)
	{
		printf("%c", pRoot->_data);
		printBinTree(pRoot->_pLeft);
		printBinTree(pRoot->_pRight);
	}
}
//二叉树的前序
void PreOrder(pBTNode pRoot)
{
	if (NULL == pRoot)
	{
		return;
	}
	if (pRoot)
	{
		printf("%c", pRoot->_data);
		PreOrder(pRoot->_pLeft);
		PreOrder(pRoot->_pRight);
	}
}
//二叉树的前序--非递归   根-左-右
void PreOrderNor(pBTNode pRoot)
{
	//二叉树为空返回空
	if (NULL == pRoot)
	{
		return;
	}
	//不为空
	stack s;
	stackInit(&s);
	pBTNode pCur = NULL;
	//先入根,再入右,后入左
	stackPush(&s, pRoot);
	pCur = pRoot;
	while (stackEmpty(&s))
	{
		   //取出栈顶元素
			pCur = stackTop(&s);
			printf("%c", pCur->_data);
			stackPop(&s);
			//如果有右孩子,入栈
			if (pCur->_pRight)
			{
				stackPush(&s, pCur->_pRight);
			}
			//如果有左孩子,入栈
			if (pCur->_pLeft)
			{
				stackPush(&s, pCur->_pLeft);
			}
	}
}
//二叉树的中序
void InOrder(pBTNode pRoot)
{
	//assert(pRoot);
	if (NULL == pRoot)
	{
		return;
	}
	if (pRoot)
	{
		InOrder(pRoot->_pLeft);
		printf("%c", pRoot->_data);
		InOrder(pRoot->_pRight);
	}
}
//二叉树的中序--非递归   左-根-右
void InOrderNor(pBTNode pRoot)
{
	if (NULL == pRoot)
	{
		return;
	}
	stack s;
	stackInit(&s);
	pBTNode pCur = pRoot;
	//找当前树的最左边的结点,并保存所经过的路径中所有结点
	while (pCur || stackEmpty(&s))
	{
		while (pCur)
		{
			stackPush(&s, pCur);
			pCur = pCur->_pLeft;
		}
			//取栈顶元素
			pCur = stackTop(&s);//读取目前最左边的结点
			printf("%c", pCur->_data);
			//出栈
			stackPop(&s);
			//取右元素
			pCur = pCur->_pRight;

	}
}

//二叉树的后序
void PostOrder(pBTNode pRoot)
{
	//assert(pRoot);
	if (NULL == pRoot)
	{
		return;
	}
	if (pRoot)
	{
		PostOrder(pRoot->_pLeft);
		PostOrder(pRoot->_pRight);
		printf("%c", pRoot->_data);
	}
}
//二叉树的后序--非递归
void PostOrderNor(pBTNode pRoot)
{
	if (NULL == pRoot)
	{
		return;
	}
	stack s;
	stackInit(&s);
	pBTNode pCur = pRoot;
	pBTNode pTop = NULL;
	pBTNode pPer = NULL;
	while (pCur || stackEmpty(&s))
	{
		while (pCur)//将左边的结点全部入栈
		{
			stackPush(&s, pCur);
			pCur = pCur->_pLeft;
		}
		pTop = stackTop(&s);
		if (NULL == pTop->_pRight || pPer == pTop->_pRight)//判断是否有右子树,或者右子树已经访问过
		{
			pPer = pTop;//记录当前结点,作为已访问的右子树
			printf("%c", pTop->_data);//输出当前结点
			stackPop(&s);
		}
		else//如果右子树存在且没有访问过
		{
			pCur = pTop->_pRight;
		}
	}
}
//二叉树的销毁
void DestoyBinTree(pBTNode* pRoot)
{
	assert(pRoot);
	if (*pRoot)
	{
		//销毁左子树
		DestoyBinTree(&(*pRoot)->_pLeft);
		//销毁右子树
		DestoyBinTree(&(*pRoot)->_pRight);
		//销毁根
		free(*pRoot);
		*pRoot = NULL;
	}
}
//层序遍历
void LevelOrder(pBTNode pRoot)
{
	//Queue q;
	//QueueInit(&q);
	//pBTNode pCur = pRoot;
	//QueuePush(&q, pRoot);
	//while (pCur || QueueEmpty(&q))
	//{
	//    pCur = QueueFront(&q);
	//	//pCur = q._pHead->_data;
	//	QueuePop(&q);
	//	if (pCur)
	//	{
	//		printf("%c", pCur->_data);
	//		QueuePush(&q, pCur->_pLeft);
	//		QueuePush(&q, pCur->_pRight);
	//	}
	//}





	Queue q;
	QueueInit(&q);
	if (pRoot)
	{
		QueuePush(&q, pRoot);
		while (pRoot && QueueEmpty(&q))
		{
			pRoot = QueueFront(&q);
			QueuePop(&q);
			printf("%c", pRoot->_data);
			if (pRoot->_pLeft)
				QueuePush(&q, pRoot->_pLeft);
			if (pRoot->_pRight)
				QueuePush(&q, pRoot->_pRight);
		}
	}
}
//二叉树的镜像--递归
void MirrorBinTree(pBTNode pRoot)
{
	pBTNode pLeft = NULL;
	pBTNode pRight = NULL;
	if (pRoot)
	{
		pLeft = pRoot->_pLeft;
		pRight = pRoot->_pRight;
		MirrorBinTree(pLeft);
		MirrorBinTree(pRight);
		pRoot->_pLeft = pRight;
		pRoot->_pRight = pLeft;
	}
}
//二叉树的镜像--非递归
void swap(pBTNode* pRoot)
{
	assert(*pRoot);
	pBTNode tmp = (*pRoot)->_pLeft;
	(*pRoot)->_pLeft = (*pRoot)->_pRight;
	(*pRoot)->_pRight = tmp;
}
void MirrorBinTreeNor(pBTNode pRoot)
{
	pBTNode pCur = NULL;
	Queue q;
	QueueInit(&q);
	QueuePush(&q, pRoot);
	while (!QueueEmpty(&q))
	{
		pCur = QueueFront(&q);
		QueuePop(&q);
		swap(&pCur);
		if (pCur->_pLeft)
			QueuePush(&q, pCur->_pLeft);
		if (pCur->_pRight)
			QueuePush(&q, pCur->_pRight);
	}
}
// 求二叉树中结点的个数 
int BinTreeSize(pBTNode pRoot)
{
	if (NULL == pRoot)
	{
		return 0;
	}
	return 1 + BinTreeSize(pRoot->_pLeft) + BinTreeSize(pRoot->_pRight);
}
// 求二叉树中叶子结点的个数 
int BinTreeLeaf(pBTNode pRoot)
{
	if (NULL == pRoot)
	{
		return 0;
	}
	if (NULL == pRoot->_pLeft && NULL == pRoot->_pRight)
	{
		return 1;
	}
	return BinTreeLeaf(pRoot->_pLeft) + BinTreeLeaf(pRoot->_pRight);
}
// 求二叉树中第K层结点的个数 
int BinTreeKLevelNode(pBTNode pRoot, int k)
{
	if (NULL == pRoot || k<=0)
	{
		return 0;
	}
	if (1 == k)
	{
		return 1;
	}
	return BinTreeKLevelNode(pRoot->_pLeft,k-1) + BinTreeKLevelNode(pRoot->_pRight,k-1);
}
// 求二叉树的高度(高度就是层数)
int BinTreeHeight(pBTNode pRoot)
{
	//空树
	if (NULL == pRoot)
	{
		return 0;
	}
	if (NULL == pRoot->_pLeft && NULL == pRoot->_pRight)
	{
		return 1;
	}
	//存在(如果左高>右高,返回左+1(1为根),否则返回右+1)
	return BinTreeHeight(pRoot->_pLeft) > BinTreeHeight(pRoot->_pRight) ? BinTreeHeight(pRoot->_pLeft) + 1 : BinTreeHeight(pRoot->_pRight) + 1;
}
// 在二叉树中查找值为data的结点,找到返回该结点,否则返回空 
pBTNode Find(pBTNode pRoot, BTDataType data)
{
	pBTNode pCur = NULL;
	if (NULL == pRoot)
	{
		return NULL;
	}
	if (data == pRoot->_data)
	{
		return pRoot;
	}
	//先找左子树
	if ((pCur = Find(pRoot->_pLeft, data)))
	{
		return pCur;
	}
	else
	{
		return Find(pRoot->_pRight, data);
	}
}
// 检测一个节点是否在二叉树中 
int IsNodeInBinTree(pBTNode pRoot, pBTNode pNode)
{
	if (NULL == pRoot || NULL == pNode)
	{
		return 0;
	}
	if (pRoot == pNode)
	{
		return 1;
	}
	if (IsNodeInBinTree(pRoot->_pLeft, pNode))
	{
		return 1;
	}
	return IsNodeInBinTree(pRoot->_pRight, pNode);
}
// 检测一棵树是否为完全二叉树 
int IsCompleteBinTree(pBTNode pRoot)
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, pRoot);
	int flag = 1;
	pBTNode pCur = NULL;
	while (!QueueEmpty(&q))
	{
		pCur = QueueFront(&q);
		QueuePop(&q);
		if (flag)
		{
			if (pCur->_pLeft && pCur->_pRight)
			{
				QueuePush(&q, pCur->_pLeft);
				QueuePush(&q, pCur->_pRight);
			}
			else if (pCur->_pLeft && NULL== pCur->_pRight)
			{
				flag = 0;
				QueuePush(&q, pCur->_pLeft);
			}
			else if (NULL == pCur->_pLeft && pCur->_pRight)
			{
				return 0;
			}

		}
		else
		{
			if (pCur->_pLeft || pCur->_pRight)
			{
				return 0;
			}
		}
	}
	return 1;
}

​

//stack.c 

​
stack.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"stack.h"
#include "BinTree.h"
//#include"Queue.h"
void stackInit(stack* s)//初始化
{
	if (NULL == s)
	{
		return;
	}
	s->_capacity =3;
	s->_array = (DataType*)malloc(sizeof(DataType)*(s->_capacity));

	//malloc函数原型 void *malloc(size_t size);
	//malloc()在内存的动态存储区中分配一块长度为size字节的连续区域,参数size为需要的内存空间的长度,返回该区域的地址。
	//sizeof(DataType)*(s->_capacity)为需要的内存空间的长度,  
	//_capacity;  底层空间的总大小 栈底位置

	s->_top =0;
}
void stackPush(stack* s, DataType data)//入栈
{
	if (NULL == s)
	{
		return ;
	}
	if (s->_top == s->_capacity)//栈中只有一个元素
	{
		//开辟空间
		s->_capacity = (s->_capacity)*2;//_capacity;  底层空间的总大小 栈底位置
		DataType* pCur = (DataType*)realloc(s->_array, sizeof(DataType)*(s->_capacity));
		s->_array = pCur;

		//realloc函数原型void *realloc(void *ptr, size_t size);
		//realloc()是给一个已经分配了地址的指针重新分配空间,参数ptr为原有的空间地址,newsize是重新申请的地址空间。
		//realloc可以对给定的指针所指向的空间进行扩大或缩小,原有的内存中的内容将保持不变。
		//realloc并不保持调整后的内存空间和原来的内存空间保持同一内存地址,返回的指针很可能指向新的地址。

		//realloc是从堆空间上分配内存,当扩大一块内存空间时,realloc试图直接从现存的数据后面的哪些字节中获得附加的字节,
		//如果能够满足需求,自然天下太平,如果后面的字节不够,那么就使用堆上第一个足够满足要求的自由空间块,
		//现存的数据然后就被拷贝到新的位置上,而老块则放回堆空间,这句话传递的一个很重要的信息就是数据可能被移动。 
	}
	s->_array[s->_top++] = data;
}
void stackPop(stack* s)//出栈
{
	if (NULL == s)
	{
		return ;
	}
	s->_top--;
}
DataType stackTop(stack* s) 获取栈顶元素 
{
	if (NULL == s)
	{
		return 0;
	}
	return s->_array[s->_top-1];
}
int stackSize(stack* s)//有效元素的个数
{
	if (NULL == s)
	{
		return 0;
	}
	return s->_top;
}
int stackEmpty(stack* s)// 检测栈是否为空
{
	if (NULL == s)
	{
		return 0;
	}
	if (s->_top == 0)
	{
		return 0;
	}
	else
	{
		return 1;
	}
}
void stackPrint(stack *s)
{
	assert(s);
	while (stackEmpty(s))
	{
		printf("%d ", stackTop(s));
		stackPop(s);
	}
}

​

//Queue.c 

​
Queue.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"
#include "BinTree.h"
//#include "stack.h"
//队列的初始化
void QueueInit(Queue* q)
{
	assert(q);
	q->_pHead = NULL;
	q->_pTail = NULL;
}
//创建新队列
pNode BuyNode(QDataType data)
{
	pNode pNewNode = malloc(sizeof(Node));
	if (NULL == pNewNode)
	{
		printf("开辟内存失败\n");
		assert(0);
	}
	
		pNewNode->_data = data;
		pNewNode->_pNext = NULL;
	
	return pNewNode;
}
//入队列(相当于尾插)
void QueuePush(Queue* q, QDataType data)
{
	pNode pNewNode = NULL;
    pNewNode = BuyNode(data);
	if (NULL == q->_pHead)//若链队为空,则新结点是队头又是队尾
	{
		q->_pHead = q->_pTail = pNewNode;
		q->_pTail = pNewNode;
	}
	//非空
	else
	{
		q->_pTail->_pNext=pNewNode;
		q->_pTail = pNewNode;
	}
}
//检测队列是否为空
int QueueEmpty(Queue* q)
{
	if (NULL == q)
	{
		return 0;
	}
	return 1;
}
//出队列
void QueuePop(Queue* q)
{
	assert(q);
	if (NULL == q)
	{
		return;
	}
	//一个元素
	if (q->_pHead==q->_pTail)
	{
		free(q->_pHead);
		q->_pHead = q->_pTail= NULL;
		return;
	}
	//多个元素
	else
	{
		q->_pHead = q->_pHead->_pNext;
	}
	free(q->_pTail);
	q->_pTail = q->_pHead;
	q->_pHead->_pNext = NULL;
}
//取队头元素
QDataType QueueFront(Queue* q)
{
	assert(q);
	if (!QueueEmpty(q))
	{
		printf("队列为空\n");
		exit(1);
	}
	return q->_pHead->_data;
}
//取队尾元素
QDataType Queueback(Queue* q)
{
	assert(q);
	if (!QueueEmpty(q))
	{
		printf("队列为空\n");
		exit(1);
	}
	return q->_pTail->_data;
}
//获取队列中元素的个数
int QueueSize(Queue* q)
{
	assert(q);
	int count = 0;
	while (q->_pHead)
	{
		count++;
		q->_pHead = q->_pHead->_pNext;
	}
	return count;
}

​

//testbintree.c 

​
testbintree.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"BinTree.h"
#include"stack.h"
#include"Queue.h"
void testBinTree()
{
	BTDataType* str = "ABD###CE##F";
	pBTNode pRoot=NULL;
	pBTNode pCur = NULL;
	CreatNode(&pRoot, str, strlen(str), '#');
	pCur = CopyBinTree(pRoot);

	printf("原序列:");
	printBinTree(pRoot);
	printf("\n");

	//printf("层序遍历:");
	//LevelOrder(pRoot);
	//printf("\n");

	//printf("拷贝:");
	//printBinTree(pCur);
	//printf("\n");

	//printf("前序:");
	//PreOrder(pRoot);
	//printf("\n");

	//printf("前序非递归:");
	//PreOrderNor(pRoot);
	//printf("\n");

	//printf("中序:");
	//InOrder(pRoot);
	//printf("\n");

	//printf("中序非递归:");
	//InOrderNor(pRoot);
	//printf("\n");

	//printf("后序:");
	//PostOrder(pRoot);
	//printf("\n");

	//printf("后序非递归:");
	//PostOrderNor(pRoot);
	//printf("\n");

	//printf("销毁:");
	//DestoyBinTree(&pRoot);
	//printf("\n");

	/*printf("镜像递归:");
	MirrorBinTree(pRoot);
	PreOrder(pRoot);
	printf("\n");

	printf("镜像非递归:");
	MirrorBinTreeNor(pRoot);
	PreOrder(pRoot);
	printf("\n");*/


	//printf("结点个数:%d\n", BinTreeSize(pRoot));

	//printf("叶子结点个数:%d\n", BinTreeLeaf(pRoot));

	//printf("k层结点个数:%d\n", BinTreeKLevelNode(pRoot,2));

	//printf("二叉树的高度:%d\n", BinTreeHeight(pRoot));


	/*pCur = Find(pRoot, 'E');
	printf("查找结果:%c\n",pCur);*/
	
	//if (IsNodeInBinTree(pRoot, Find(pRoot, 'E')))
	//{
	//	printf("存在\n");
	//}

	printf("是否为完全二叉树 :%d\n", IsCompleteBinTree(pRoot));

}

int main()
{
	testBinTree();
	system("pause");
	return 0;
}






​

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉树是一种非常重要的数据结构,它的基本操作包括创建、销毁、遍历、查找等。下面是二叉树基本操作的实现方法: 1. 创建二叉树:通过前序遍历的数组构建二叉树,其中 '#' 表示空节点。具体实现方法可以参考引用中的 BinaryTreeCreate 函数。 2. 销毁二叉树:遍历二叉树,依次释放每个节点的内存空间。具体实现方法可以参考引用中的 BinaryTreeDestory 函数。 3. 遍历二叉树二叉树的遍历包括前序遍历、中序遍历、后序遍历和层序遍历。具体实现方法可以参考引用中的 BinaryTreePrevOrder、BinaryTreeInOrder、BinaryTreePostOrder 和 BinaryTreeLevelOrder 函数。 4. 查找二叉树节点:在二叉树中查找值为 x 的节点,具体实现方法可以参考引用中的 BinaryTreeFind 函数。 5. 计算二叉树节点个数:计算二叉树中节点的个数,具体实现方法可以参考引用[2]中的 BinaryTreeSize 函数。 6. 计算二叉树叶子节点个数:计算二叉树中叶子节点的个数,具体实现方法可以参考引用中的 BinaryTreeLeafSize 函数。 7. 计算二叉树第 k 层节点个数:计算二叉树中第 k 层节点的个数,具体实现方法可以参考引用中的 BinaryTreeLevelKSize 函数。 8. 判断二叉树是否是完全二叉树:判断二叉树是否是完全二叉树,具体实现方法可以参考引用中的 BinaryTreeComplete 函数。 9. 计算二叉树的深度:计算二叉树的深度,具体实现方法可以参考引用中的 BinaryTreeDeep 函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值