基本概念
结点:结点包括一个数据元素及若干指向其他子树的分支(指针(索引))。
结点的度:结点所拥有子树的个数为该结点的度。
叶子结点(终端结点):度为0的结点。
分支结点(非终端结点):度不为0的结点。一般树中除了叶子结点外都是分支结点。
祖先结点:从根结点到该结点所经分支上的所有结点。
子孙结点:以某结点为根结点的子树中所有结点。
双亲结点:树中某结点有孩子结点,则这个结点称为他孩子结点的双亲结点,双亲结点也称为前驱结点。
孩子结点:树中一个结点的子树的根结点,孩子结点也称后继结点。
兄弟结点:具有相同双亲结点的结点。
树的度:树中所有结点的度的最大值称为该树的度。
结点的层次:从根结点到树中某结点所经路径上的分支数为该结点的层次。根结点的层次为1,其他结点层次是双亲层次加1.
树的深度:树中所有结点的层次的最大值。
有序树:树中结点的各棵树T0,T1,T2.....是有序的,即为有序树.
无序树:树中节点的各棵子树之间的次序不重要,可以相互交换位置。
森林:树M棵树的集合(M>=0).在自然界中树和森林是两个不同的概念,但是在数据结构中,它们之间的差别很小。删去 一棵非空树的根结点,树就会变成森林;反之,若增加一个根结点,让森林中每一棵树的根结点都变成他 子女,森林就变 成一棵树
二叉树的特点:
1.每个结点最多有两棵子树,即二叉树不存在度大于2的结点。
2.二叉树的子树有左右之分,其子树的次序不能颠倒。
满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子结点都在同一层上。如下图所示。
完全二叉树:如果一棵树具有N个结点的二叉树的结构与满二叉树的前N个结点的结构相同,称为完全二叉树。如上图所示。
二叉树的性质:
1.若规定根结点的层数为1,则一颗非空二叉树的第i层上最多有2^(i-1) ( i>0) 个结点。
2.若规定只有根结点的二叉树的深度为1,则深度为K的二叉树的最大结点树是(2^k)-1 ( k>=0)。
3.具有n个结点的完全二叉树的深度k为log2(n+1)向上取整。
4.对任何一棵二叉树,如果其叶子结点个数为n0,度为2的非叶子节点个数为n2,则有n0=n2+1;
二叉树的基本操作:
二叉树的遍历:前序(根左右)
中序(左根右)
后序(左右根)
层序(从上到下,从左到右)
二叉树的层序遍历算法:
a. 初始化一个队列。
b. 将根结点的指针入队列。
c. 当队列非空时,循环执行以下步骤:
> 取队头元素并访问。
> 若该结点的左子树非空,将该结点的左子树入队列。
> 若该结点的右子树非空,将该结点的右子树入队列。
d.结束
二叉树代码:
Tree.h:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<windows.h>
#include"Queue.h"
#include"stack.h"
typedef char DataType;
typedef struct TreeNode{
struct TreeNode *pLeft;
struct TreeNode *pRight;
DataType data;
}TreeNode;
TreeNode* CreateRoot(DataType data)
{
TreeNode *pRoot = (TreeNode*)malloc(sizeof(TreeNode));
assert(pRoot);
pRoot->data = data;
pRoot->pLeft = NULL;
pRoot->pRight = NULL;
return pRoot;
}
//例如:前序是:ABD###CE##F还原二叉树
//还原二叉树
TreeNode* CreateTree(DataType preOrder[], int size, int *pIndex)
{
if (*pIndex >= size){
return NULL;
}
if (preOrder[*pIndex] == '#'){
*pIndex += 1;
return NULL;
}
TreeNode* pRoot = CreateRoot(preOrder[*pIndex]);
(*pIndex)++;//用了1个字符;
pRoot->pLeft = CreateTree(preOrder, size, pIndex);
pRoot->pRight = CreateTree(preOrder, size, pIndex);
return pRoot;
}
//前序遍历(递归)
void PreOrder(TreeNode* pRoot)
{
if (pRoot == NULL){
return;
}
printf("%c ", pRoot->data);
PreOrder(pRoot->pLeft);
PreOrder(pRoot->pRight);
}
//前序(非递归)
void PreOrderLoop(TreeNode *pRoot)
{
TreeNode *pCur = pRoot;
TreeNode *pTop = NULL;
Stack stack;
StackInit(&stack);
while (pCur != NULL || !StackIsEmpty(&stack)){
while (pCur != NULL){
printf("%c", pCur->data);
StackPush(&stack, pCur);
pCur = pCur->pLeft;
}
//整棵树的左边都遍历
//没有遍历的还剩栈里节点的右子树
pTop = StackTop(&stack);
StackPop(&stack);
//遍历Top的右子树,用子问题的办法
pCur = pTop->pRight;
}
}
//中序遍历(递归)
void InOrder(TreeNode* pRoot)
{
if (pRoot == NULL){
return;
}
InOrder(pRoot->pLeft);
printf("%c ", pRoot->data);
InOrder(pRoot->pRight);
}
//中序(非递归)
void InOrderLoop(TreeNode *pRoot)
{
TreeNode *pCur = pRoot;
TreeNode *pTop = NULL;
Stack stack;
StackInit(&stack);
while (pCur != NULL ||! StackIsEmpty(&stack)){
while (pCur != NULL){
StackPush(&stack, pCur);
pCur = pCur->pLeft;
}
pTop = StackTop(&stack);
StackPop(&stack);
printf("%c", pTop->data);
//遍历Top的右子树,用子问题的办法
pCur = pTop->pRight;
}
}
//后序遍历(递归)
void PostOrder(TreeNode* pRoot)
{
if (pRoot == NULL){
return;
}
PostOrder(pRoot->pLeft);
PostOrder(pRoot->pRight);
printf("%c ", pRoot->data);
}
//后序(非递归)
void PostOrderLoop(TreeNode *pRoot)
{
TreeNode *pCur = pRoot;
TreeNode *pTop = NULL;
TreeNode *pLast = NULL;
Stack stack;
StackInit(&stack);
while (pCur != NULL || !StackIsEmpty(&stack)){
while (pCur != NULL){
StackPush(&stack, pCur);
pCur = pCur->pLeft;
}
//没有遍历的还剩栈里节点的右子树和根
pTop = StackTop(&stack);
if ((pTop->pRight == NULL) || (pTop->pRight = pLast)){
//pTop无右子树,所以可以直接处理pTop的根节点
//pTop有右子树,但是pTop的右子树已经遍历完了,所以可以处理pTop的根
StackPop(&stack);
printf("%c", pTop->data);
pLast = pTop;
continue;
}
}
}
//求二叉树节点总数(左节点数+右节点数+1(最后一个根节点))
int GetSize(TreeNode* pRoot)
{
if (pRoot == NULL){
return 0;
}
return GetSize(pRoot->pLeft) + GetSize(pRoot->pRight) + 1;
}
//此处也可以这样写(因为线程问题,所以不推荐)
//int count = 0;
//int GetSize(TreeNode* pRoot)
//{
// if (pRoot == NULL){
// return;
// }
// PreOrder(pRoot->pLeft);
// PreOrder(pRoot->pRight);
//}
//求二叉树中叶子节点的个数
int GetLeafSize(TreeNode* pRoot)
{
if (pRoot == NULL){
return 0;
}
if (pRoot->pLeft == NULL && pRoot->pRight == NULL){
//pRoot是叶子节点
return 1;
}
return GetSize(pRoot->pLeft) + GetSize(pRoot->pRight);
}
//求二叉树的第k层节点个数(k:层数,先有左子树,后产生(k-1)层)
int GetkLevelSize(TreeNode* pRoot, int k)
{
assert(k>= 1);
if (pRoot == NULL){
return 0;//空树
}
if (k== 1){
return 1;
}
return GetkLevelSize(pRoot->pLeft, k - 1) + GetkLevelSize(pRoot->pRight, k - 1);
}
//判断一个节点是否在二叉树中。找到返回节点地址,否则,返回NULL;
TreeNode*Find(TreeNode* pRoot, DataType data)
{
if (pRoot == NULL){
return NULL;
}
if (pRoot->data == data){
return pRoot;
}
TreeNode* pFound = Find(pRoot->pLeft, data);//定义一个指针,保存找到的地址
if (pFound != NULL){
return pFound;
}
return Find(pRoot->pRight, data);//可能找到,可能找不到
}
//求二叉树的高度(深度)
#define MAX(x,y) ((x)>(y) ? (x) :(y))
int GetHeight(TreeNode *pRoot)
{
if (pRoot == NULL){
return 0;
}
//可要可不要
if (pRoot->pLeft == NULL && pRoot->pRight == NULL){
return 1;
}
int left = GetHeight(pRoot->pLeft);
int right = GetHeight(pRoot->pRight);
return MAX(left, right) + 1;
}
//层序遍历二叉树
void LevelOrder(TreeNode *pRoot)
{
if (pRoot == NULL){
printf("\n");
return;
}
Queue queue;
TreeNode *pFront;
QueueInit(&queue);
QueuePush(&queue, pRoot);
while (!QueueIsEmpty(&queue)){
pFront = QueueFront(&queue);
QueuePop(&queue);
printf("%c", pFront->data);
if (pFront->pLeft != NULL){
QueuePush(&queue, pFront->pLeft);
}
if (pFront->pRight != NULL){
QueuePush(&queue, pFront->pRight);
}
}
printf("\n");
}
//判断二叉树是否是完全二叉树。是:返回1;不是:返回0
int IsComplete(TreeNode *pRoot)
{
//空树也是完全二叉树
if (pRoot == NULL){
return 1;
}
Queue queue;
TreeNode *pFront;
QueueInit(&queue);
QueuePush(&queue, pRoot);
while (!QueueIsEmpty(&queue)){
pFront = QueueFront(&queue);
QueuePop(&queue);
if (pFront == NULL){
break;
}
QueuePush(&queue, pFront->pLeft);
QueuePush(&queue, pFront->pRight);
}
while (!QueueIsEmpty(&queue)){
pFront = QueueFront(&queue);
QueuePop(&queue);
if (pFront != NULL){
return 0;
}
}
return 1;
}
void Test()
{
DataType *preOrder = "ABD###CE##F";
//DataType *preOrder = "AB##C";
int Index = 0;
TreeNode* pRoot = CreateTree(preOrder, strlen(preOrder), &Index);
PreOrder(pRoot); printf("前序:\n ");
InOrder(pRoot); printf("中序:\n ");
PostOrder(pRoot); printf("后序:\n ");
printf("叶子节点数:%d\n", GetLeafSize(pRoot));
int k = 2;
printf("第 %d 层节点数: %d\n", k, GetkLevelSize(pRoot,k));
printf("树的高度为:%d\n", GetHeight(pRoot));
LevelOrder(pRoot);//层序遍历
printf("%d\n", IsComplete(pRoot));
}
stack.h:
#pragma once
#include<stdlib.h>
#include<assert.h>
#include<string.h>
typedef struct Position{
int x;
int y;
}Position;
typedef void * SDataType;
#define MAX_SIZE (100)
typedef struct Stack{
SDataType array[MAX_SIZE];
int top;//含义和顺序表的size含义一样(1.表示有效数据个数 2.top下标表示当前可用位置)
}Stack;
//栈的初始化
void StackInit(Stack *pS)
{
assert(pS != NULL);
pS->top = 0;
}
//入栈
void StackPush(Stack *pS, SDataType data)
{
assert(pS != NULL);
assert(pS->top < MAX_SIZE);
pS->array[pS->top++] = data;
}
//出栈
void StackPop(Stack *pS)
{
assert(pS != NULL);
assert(pS->top>0);
pS->top--;
}
SDataType StackTop(Stack *pS)
{
assert(pS != NULL);
assert(pS->top > 0);
return pS->array[pS->top - 1];
}
//判断是否为空:1.空 0.非空
int StackIsEmpty(Stack *pS)
{
return pS->top == 0 ? 1 : 0;
}
//求栈的大小
int StackSize(Stack *pS)
{
return pS->top;
}
//栈的复制
void StackCopy(Stack *pDest, Stack *pSrc)
{
pDest->top = pSrc->top;
memcpy(pDest->array, pSrc->array, sizeof(SDataType)*pSrc->top);
}
void TestStack()
{
Stack stack;
StackInit(&stack);
}
Queue.h:
#pragma once
#include<stdio.h>
#include<assert.h>
#include<string.h>
typedef void *QDataType;
typedef struct QNode{
QDataType data;
struct QNode *pNext;
}QNode;
typedef struct Queue{
QNode *pFront;
QNode *pRear;
int size;
}Queue;
//队列初始化
void QueueInit(Queue *pQ)
{
assert(pQ != NULL);
pQ->pFront = pQ->pRear = NULL;
pQ->size = 0;
}
//入队列
void QueuePush(Queue *pQ, QDataType data)
{
assert(pQ != NULL);
pQ->size++;
QNode *pNewNode = (QNode *)malloc(sizeof(QNode));
assert(pNewNode);
pNewNode->data = data;
pNewNode->pNext = NULL;
if (pQ->pRear == NULL){
pQ->pFront = pQ->pRear = pNewNode;
return;
}
//通常情况
pQ->pRear->pNext = pNewNode;
pQ->pRear = pNewNode;
}
//出队列
void QueuePop(Queue *pQ)
{
assert(pQ != NULL);
assert(pQ->size > 0);
pQ->size--;
//通常情况
QNode *pOldFront = pQ->pFront;
pQ->pFront = pQ->pFront->pNext;
free(pOldFront);
if (pQ->pFront == NULL){
pQ->pRear = NULL;
}
}
//更新队首
QDataType QueueFront(Queue *pQ){
assert(pQ != NULL);
assert(pQ != NULL);
return pQ->pFront->data;
}
//判断队列是否为空: 1 空 ; 0 不空
int QueueIsEmpty(Queue *pQ){
return pQ->size == 0 ? 1 : 0;
}
int QueueSize(Queue *pQ){
return pQ->size;
}
结果显示: