数据结构与算法-二叉树快速入门

简介

二叉树是一种非常重要的非线性结构,比较适合用于计算机处理,而且任何树和森林都可以转换为二叉树。



定义

一棵二叉树 T 是 n ( n ≥ 0 ) T是n(n≥0) Tn(n0)个结点的有限集合。当 n = 0 n=0 n=0时,它是一棵空二叉树;当 n > 0 n>0 n>0时,它由一个根节点和两棵分别称为左子树和右子树且互不相交的二叉树组成。
二叉树的递归定义如下:
T = { ∅ , n = 0 { r o o t , T L , T R } , n > 0 T=\left\{\begin{array}{cc} ∅, & n=0\\ \{root,T_L,T_R\}, & n>0 \end{array}\right. T={,{root,TL,TR},n=0n>0
其中root表示T的根, T L T_L TL表示T的左子树, T R T_R TR表示T的右子树, T L T_L TL T R T_R TR仍是二叉树。
>二叉树中即使只有一棵子树也要进行区分,说明它是左子树,还是右子树,这时二叉树与树的最主要的区别。二叉树就是结点度为2的树是错误的!


五种基本形态

(a):空树 ∅ ∅
(b):只有根节点(b)
©:只有左子树(c)
(d):只有右子树(d)
(e):既有左子树,又有右子树(e)


性质

  1. 在二叉树的第 i ( i ≥ 1 ) i(i≥1) i(i1)层上之多有 2 i − 1 2^{i-1} 2i1个结点。
  2. 深度为 k ( k ≥ 1 ) k(k≥1) k(k1)的二叉树之多有 2 k − 1 2^k-1 2k1个结点。
  3. 对任何一棵非空二叉树,如果其叶子结点数为 n 0 n_0 n0,度为 2 2 2的节点数为 n 2 n_2 n2,则 n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1
  4. 具有 n ( n > 0 ) n(n>0) n(n>0)个结点的***完全二叉树***的深度为 ⌊ l o g 2 n + 1 ⌋ ⌊log_2n+1⌋ log2n+1
  5. 如果将一棵有 n n n个结点的完全二叉树按照自顶向下,同一层自左向右**的顺序连续给结点编号 1 , 2 , 3 , . . . , n 1,2,3,...,n 1,2,3,...,n,然后按此结点编号将树中各结点顺序地存放于一个一维数组中, 并简称编号为 i i i的结点为结点 i ( 1 ≤ i ≤ n ) i (1≤i≤n) i(1in)。则有以下关系:

(1)若 i = 1 i=1 i=1,则结点 i i i为根,无双亲结点;若 i > 1 i>1 i>1, 则 i i i的双亲结点为结点 └ i / 2 ┘ └i/2┘ i/2
(2)若 2 i ≤ n 2i≤n 2in, 则结点 i i i的左孩子为结点 2 i 2i 2i;否则结点 i i i无左孩子。
(3)若 2 i + 1 ≤ n 2i+1≤n 2i+1n, 则结点 i i i的右孩子为结点 2 i + 1 2i+1 2i+1,否则,结点 i i i无右孩子。


#遍历方式

  • 遍历二叉树:指遵从某种顺序,顺着某一条搜索路径访问二叉树中的各个结点,使得每个结点均被访问一次,而且仅被访问一次。
  • 访问:输出结点的信息、修改结点的数据值等,但一般要求这种访问不破坏原来数据之间的逻辑结构。

先序遍历

也称为前序遍历,按照“根-左子树-右子树”的次序遍历二叉树。(递归
如果二叉树为空,则遍历结束;否则:

  1. 访问根节点( D );
  2. 先序遍历左子树( L );
  3. 先序遍历右子树( R )。
void preTraverse(BiTree T) {
	if (T) {
		cout << T->data << " ";
		preTraverse(T->lchild);
		preTraverse(T->rchild);
	}
}

中序遍历

按照“左子树-根-右子树”的次序遍历二叉树。(递归
如果二叉树为空,则遍历结束;否则:

  1. 中序遍历左子树( L );
  2. 访问根节点( D );
  3. 中序遍历右子树( R )。
void midTraverse(BiTree T) {
	if (T) {
		midTraverse(T->lchild);
		cout << T->data << " ";
		midTraverse(T->rchild);
	}
}

后序遍历

按照“左子树-右子树-根”的次序遍历二叉树。(递归
如果二叉树为空,则遍历结束;否则:

  1. 后序遍历左子树( L );
  2. 后序遍历右子树( R )。
  3. 访问根节点( D );
void postTraverse(BiTree T) {
	if (T) {
		postTraverse(T->lchild);
		postTraverse(T->rchild);
		cout << T->data << " ";
	}
}

层次遍历

按照二叉树的层次,从上到下、从左到右的次序访问各节点。(队列
层次遍历从二叉树的根节点开始,首先将根结点指针入队,然后从队头取出一个数据元素执行以下操作:

  1. 访问该指针所指结点;
  2. 若该指针所指结点的左、右孩子结点不空,则将其左孩子指针和右孩子指针入队;
  3. 重复上述1、2两个步骤,直至队列为空。
void levelTraverse(BiTree T) {
	BiTree bt;
	LinkQuene q;
	if (T) {
		q.EnQuene(T);
		while (q.QueneEmpty()) {
			bt = q.DeQuene();
			if (bt)
				cout << bt->data << " ";
			if (bt->lchild)
				q.EnQuene(bt->lchild);
			if (bt->rchild)
				q.EnQuene(bt->rchild);
		}
	}
}

整体实现

#include "pch.h"
#include <iostream>
#include <stdlib.h>
#define ElemType BiTree 
#define ERROR -1
#define OK 0
using namespace std;

//二叉树结点
typedef struct node {
	struct node *lchild;
	struct node *rchild;
	char data;
} BiTreeNode, *BiTree;

struct Node {
	ElemType data;
	Node* next;
};

class LinkQuene {
private:
	Node* front;
	Node* rear;
public:
	LinkQuene();
	~LinkQuene();
	int EnQuene(ElemType);
	ElemType DeQuene();
	int QueneEmpty();
};

LinkQuene::LinkQuene() {
	front = new Node;
	front->next = NULL;
	rear = front;
	//rear->next=NULL; 
}

LinkQuene::~LinkQuene() {
	Node *p;
	while (front) {
		p = front;
		front = front->next;
		delete p;
	}
}

int LinkQuene::EnQuene(ElemType c) {
	Node *p;
	p = new Node;
	p->data = c;
	p->next = NULL;
	rear->next = p;
	rear = p;
	if (front->next == NULL)
		front->next = p;
	return OK;
}

ElemType LinkQuene::DeQuene() {
	Node *p;
	ElemType c;
	if (rear == front) {
		cout << "?????";
		return NULL;
	}
	p = front->next;
	c = p->data;
	front->next = p->next;
	if (p->next = NULL)
		front = rear;
	delete p;
	return c;
}


int LinkQuene::QueneEmpty() {
	int i = 0;
	if (front->next != NULL)
		i = 1;
	return i;
}

//前序遍历
void preTraverse(BiTree T) {
	if (T) {
		cout << T->data << " ";
		preTraverse(T->lchild);
		preTraverse(T->rchild);
	}
}
//中序遍历
void midTraverse(BiTree T) {
	if (T) {
		midTraverse(T->lchild);
		cout << T->data << " ";
		midTraverse(T->rchild);
	}
}
//后序遍历
void postTraverse(BiTree T) {
	if (T) {
		postTraverse(T->lchild);
		postTraverse(T->rchild);
		cout << T->data << " ";
	}
}

//层次遍历
void levelTraverse(BiTree T) {
	BiTree bt;
	LinkQuene q;
	if (T) {
		q.EnQuene(T);
		while (q.QueneEmpty()) {
			bt = q.DeQuene();
			if (bt)
				cout << bt->data << " ";
			if (bt->lchild)
				q.EnQuene(bt->lchild);
			if (bt->rchild)
				q.EnQuene(bt->rchild);
		}
	}
}

int maxDepth(BiTree T) {
	if (T == nullptr)
		return 0;
	int leftDepth, rightDepth;
	//分别计算左子树和右子树的深度
	leftDepth = maxDepth(T->lchild) + 1;
	rightDepth = maxDepth(T->rchild) + 1;

	return leftDepth > rightDepth ? leftDepth : rightDepth;
}

void createBiTree(BiTree &T) {
	char c;
	cin >> c;
	if ('#' == c)
		T = NULL;
	else {
		T = new BiTreeNode;
		T->data = c;
		createBiTree(T->lchild);
		createBiTree(T->rchild);
	}
}

int main() {
	BiTree T;
	createBiTree(T);
	cout << "创建完成!" << endl;
	cout << "前序遍历:" << endl;
	preTraverse(T);
	cout << endl;
	cout << "中序遍历:" << endl;
	midTraverse(T);
	cout << endl;
	cout << "后序遍历:" << endl;
	postTraverse(T);
	cout << endl;
	cout << "层次遍历:" << endl;
	levelTraverse(T);
	cout << endl << "共有" << MaxDepth(T) << "层";
	return 0;
}


现有一棵二叉树,如图所示:
二叉树


输入:ABC##DE#G##F###
输出:
创建完成!
前序遍历:
A B C D E G F
这里写图片描述
中序遍历:
C B E G D F A
这里写图片描述
后序遍历:
C G E F D B A
这里写图片描述
层次遍历:
A B C D E F G
这里写图片描述
共有:5层

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值