二叉树的概念及结构
1.概念:
一棵二叉树是结点的一个有限集合,该集合要么为空,要么是由一个根节点加上两棵分别成为左子树和右子树的二叉树组成。
二叉树的特点:
1.每个结点最多有两颗子树,即二叉树不存在度大于2的结点
2.二叉树的子树有左右之分,其子树的次序不能颠倒。
2.二叉树的结构
特殊的二叉树:
1.满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。若一个二叉树的层数为K,且结点总数是(2^K)-1;则称它是满二叉树
2.完全二叉树:完全二叉树失效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点——对应时称之为完全二叉树。*要注意的是满二叉树是一种特殊的完全二叉树*
//queue.h
#ifndef __QUEUE_H__
#define __QUEUE_H__
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
#include<stdbool.h>
//前置声明
struct BinaryTreeNode;
typedef struct BinaryTreeNode* Datatype;
typedef struct QueueNode
{
struct QueueNode* next;
Datatype data;
}QueueNode;
typedef struct Queue
{
QueueNode* head;
QueueNode* tail;
}Queue;
void QueueInit(Queue* pst);
void QueueDestroy(Queue* pst);
bool QueueEmpty(Queue* pst);
Datatype QueueBack(Queue* pst);
Datatype QueueFront(Queue* pst);
void QueuePush(Queue* pst, Datatype x);
void QueuePop(Queue* pst);
int QueueSize(Queue* pst);
#endif
//queue.cpp
#include"queue.h"
void QueueInit(Queue* pst)
{
assert(pst);
pst->head = pst->tail = NULL;
}
void QueueDestroy(Queue* pst)
{
assert(pst);
QueueNode* cur = pst->head;
while (cur)
{
QueueNode* next = cur->next;
free(cur);
cur = next;
}
pst->head = pst->tail = NULL;
}
bool QueueEmpty(Queue* pst)
{
assert(pst);
return pst->head == NULL;
}
Datatype QueueBack(Queue* pst)
{
assert(pst);
assert(!QueueEmpty(pst));
return pst->tail->data;
}
Datatype QueueFront(Queue* pst)
{
assert(pst);
assert(!QueueEmpty(pst));
return pst->head->data;
}
void QueuePush(Queue* pst, Datatype x)
{
assert(pst);
QueueNode*
newnode = (QueueNode*)malloc(sizeof(QueueNode));
if (newnode == NULL)
{
printf("malloc error!\n");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
if (pst->head == NULL)
{
pst->head = pst->tail = newnode;
}
else
{
pst->tail->next = newnode;
pst->tail = newnode;
}
}
void QueuePop(Queue* pst)
{
assert(pst);
assert(!QueueEmpty(pst));
if (pst->head->next == NULL)
{
free(pst->head);
pst->head = pst->tail = NULL;
}
else
{
QueueNode* next = pst->head->next;
free(pst->head);
pst->head = next;
}
}
int QueueSize(Queue* pst)
{
assert(pst);
int num = 0;
QueueNode* cur = pst->head;
while (cur)
{
num++;
cur = cur->next;
}
return num;
}
//tree.cpp
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"queue.h"
typedef char BTDataType;
typedef struct BinaryTreeNode
{
struct BinaryTreeNode* _left;
struct BinaryTreeNode* _right;
BTDataType data;
}BTNode;
void PrevOrder(BTNode* root)//前序
{
if (root == NULL)
{
//printf("NULL ");
return;
}
printf("%c ", root->data);
PrevOrder(root->_left);
PrevOrder(root->_right);
}
void InOrder(BTNode* root)//中序
{
if (root == NULL)
{
//printf("NULL ");
return;
}
InOrder(root->_left);
printf("%c ", root->data);
InOrder(root->_right);
}
void PostOrder(BTNode* root)//后序
{
if (root == NULL)
{
//printf("NULL ");
return;
}
PostOrder(root->_left);
PostOrder(root->_right);
printf("%c ", root->data);
}
//思路一:遍历计数的方式
//void TreeSize(BTNode* root,int* psize)
//{
// if (root == NULL)
// {
// //printf("NULL ");
// return;
// }
// ++(*psize);
// TreeSize(root->_left, psize);
// TreeSize(root->_right, psize);
//}
//子问题拆解 空:0 非空 = 左子树节点个数 + 右子树节点个数 + 1;
//分治算法: 大问题拆解成子问题
int TreeSize(BTNode* root)
{
return root == NULL ? 0 : TreeSize(root->_left) + TreeSize(root->_right) + 1;
}
BTNode* CreateTreeNode(BTDataType x)
{
BTNode* node = (BTNode*)malloc(sizeof(BTNode));
node->data = x;
node->_left = NULL;
node->_right = NULL;
return node;
}
int TreeLeafSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
if (root->_left == NULL && root->_right == NULL)
{
return 1;
}
return TreeLeafSize(root->_left) + TreeLeafSize(root->_right);
}
//k>0
int TreeKLevelSize(BTNode* root, int k)
{
assert(k > 0);
//求当前树的第K层的节点个数 = 左子树K-1层的节点个数 + 右子树K-1层的节点个数
if (root == NULL)
return 0;
if (k == 1)
return 1;
--k;
return TreeKLevelSize(root->_left, k) + TreeKLevelSize(root->_right, k);
}
BTNode* TreeFind(BTNode* root, BTDataType x)
{
//查找树里面值为x的那个节点
//1.root == NULL return NULL
//2.root节点不是我们要找的,先到左树去找,左树如果没有,再到右树去找,左右都没有
//3.左右都没有,当前树没有找到返回NULL
if (root == NULL)
return NULL;
if (root->data == x)
return root;
BTNode* lret = TreeFind(root->_left, x);
if (lret)
return lret;
BTNode* rret = TreeFind(root->_right, x);
if (rret)
return rret;
return NULL;
}
void BinaryTree_Destory(BTNode** pproot)
{
if (*pproot == NULL)
return;
BinaryTree_Destory(&(*pproot)->_left);
BinaryTree_Destory(&(*pproot)->_right);
free(*pproot);
*pproot = NULL;
}
//树的销毁
void BinaryTree_Destory(BTNode* root)
{
if (root == NULL)
return;
BinaryTree_Destory(root->_left);
BinaryTree_Destory(root->_right);
free(root);
}
//层序遍历
//void TreeLevelOrder(BTNode* root)
//{
// Queue q;
// QueueInit(&q);
// if (root)
// {
// QueuePush(&q, root);
// }
// while (!QueueEmpty(&q))
// {
// BTNode* front = QueueFront(&q);
// printf("%c ", front->data);
// QueuePop(&q);
//
// if (front->_left)
// QueuePush(&q, front->_left);
// if (front->_right)
// QueuePush(&q, front->_right);
// }
// QueueDestroy(&q);
//}
//
void TreeLevelOrder(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root == NULL)
return;
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
printf("%c ", front->data);
QueuePop(&q);
if (front == NULL)
break;
if (front->_left)
QueuePush(&q, front->_left);
if (front->_right)
QueuePush(&q, front->_right);
}
QueueDestroy(&q);
}
//判断是否是完全二叉树。
bool BinaryTreeComplete(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root == NULL)
return true;
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front)
{
QueuePush(&q, front->_left);
QueuePush(&q, front->_right);
}
else
break;
}
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front)
return false;
}
return true;
}
int main()
{
BTNode* A = CreateTreeNode('A');
BTNode* B = CreateTreeNode('B');
BTNode* C = CreateTreeNode('C');
BTNode* D = CreateTreeNode('D');
BTNode* E = CreateTreeNode('E');
BTNode* F = CreateTreeNode('F');
A->_left = B;
A->_right = C;
B->_left = D;
C->_left = E;
C->_right = F;
PrevOrder(A);
printf("\n");
InOrder(A);
printf("\n");
PostOrder(A);
printf("\n");
int size = 0;
//TreeSize(A, &size);
//printf("TreeSize: %d \n",size);
//size = 0;
//TreeSize(A, &size);
//
//printf("TreeSize: %d \n", TreeSize(A));
//printf("TreeSize: %d \n", TreeSize(A));
//printf("TreeLeafSize: %d \n", TreeLeafSize(A));
printf("TreeKLevelSize: %d \n", TreeKLevelSize(A, 3));
BTNode* p = TreeFind(A, 'c');
//销毁二叉树:后序遍历
printf("BinaryTreeComplete: %d \n", BinaryTreeComplete(A));
TreeLevelOrder(A);
BinaryTree_Destory(A);
A = NULL;
system("pause");
return 0;
}