国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)的構(gòu)建和遍歷】

這篇具有很好參考價(jià)值的文章主要介紹了【數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)的構(gòu)建和遍歷】。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)

前言:
前篇學(xué)習(xí)了 數(shù)據(jù)結(jié)構(gòu)之樹(shù)和二叉樹(shù)的基本概念知識(shí),那么這篇繼續(xù)完善二叉樹(shù)的相關(guān)知識(shí)并完成實(shí)現(xiàn)二叉樹(shù)的構(gòu)建和遍歷的內(nèi)容。

/知識(shí)點(diǎn)匯總/

1、二叉樹(shù)的概念和結(jié)構(gòu)

因?yàn)榍捌呀?jīng)非常詳細(xì)的單獨(dú)學(xué)習(xí)了數(shù)和二叉樹(shù)的基本知識(shí)概念,那么這里就簡(jiǎn)單回顧一下即可。
概念
二叉樹(shù)(Binary Tree)是樹(shù)形結(jié)構(gòu)的一個(gè)重要類型。每個(gè)節(jié)點(diǎn)最多只能有兩棵子樹(shù),且有左右之分。
它的定義可以概括為:一個(gè)n個(gè)有限元素的集合,該集合或者為空、或者由一個(gè)稱為根的元素及兩個(gè)不相交的、被分別稱為左子樹(shù)和右子樹(shù)的二叉樹(shù)組成。
形象一點(diǎn)就是:

(1)空二叉樹(shù)——(a);
(2)只有一個(gè)根結(jié)點(diǎn)的二叉樹(shù)——(b);
(3)只有左子樹(shù)——?;
(4)只有右子樹(shù)——(d);
(5)完全二叉樹(shù)——(e)

1.1、回顧二叉樹(shù)的重要性質(zhì)

1.二叉樹(shù)第i層上的結(jié)點(diǎn)數(shù)目最多為2^(i-1) (i≥1)。
2.深度為k的二叉樹(shù)至多有2^k-1個(gè)結(jié)點(diǎn)(k≥1)。
3.包含n個(gè)結(jié)點(diǎn)的二叉樹(shù)的高度至少為log2(n+1)。
4.在任意一棵二叉樹(shù)中,若終端結(jié)點(diǎn)的個(gè)數(shù)為n0,度為2的結(jié)點(diǎn)數(shù)為n2,則n0=n2+1。
5.如果有一顆n個(gè)結(jié)點(diǎn)的完全二叉樹(shù)(其深度為?log2n?+1)的結(jié)點(diǎn)按層序編號(hào)(從第一層到最后一層,每層從左到右),對(duì)任一結(jié)點(diǎn)i(1≤i≤n):
1)如果i=1,則結(jié)點(diǎn)i是二叉樹(shù)的根,無(wú)雙親;如果i>1,則其雙親是結(jié)點(diǎn)?i/2?。
2)如果2i>n,則結(jié)點(diǎn)i無(wú)左孩子(結(jié)點(diǎn)i為葉子結(jié)點(diǎn));否則其左孩子LCHILD(i)是結(jié)點(diǎn)2i。
3)如果2i+1>n,則結(jié)點(diǎn)i無(wú)右孩子,否則其右孩子RCHILD(i)是結(jié)點(diǎn)2i+1。

1.2、回顧二叉樹(shù)的主要分類

1.滿二叉樹(shù):如果一棵二叉樹(shù)只有度為0的結(jié)點(diǎn)和度為2的結(jié)點(diǎn),并且度為0的結(jié)點(diǎn)在同一層上,那么這棵二叉樹(shù)就被稱為滿二叉樹(shù)。
2.完全二叉樹(shù):除最后一層外,每一層上的結(jié)點(diǎn)數(shù)均達(dá)到最大值;在最后一層上只缺少右邊的若干結(jié)點(diǎn)。每個(gè)結(jié)點(diǎn)最多有兩個(gè)子樹(shù),因此不存在度大于2的結(jié)點(diǎn)。左子樹(shù)和右子樹(shù)是有順序的,次序不能任意顛倒。
3.二叉搜索樹(shù)(二叉排序樹(shù)):可以為空樹(shù),或者是具備如下性質(zhì):若它的左子樹(shù)不空,則左子樹(shù)上的所有結(jié)點(diǎn)的值均小于根節(jié)點(diǎn)的值;若它的右子樹(shù)不空,則右子樹(shù)上的所有結(jié)點(diǎn)的值均大于根節(jié)點(diǎn)的值,左右子樹(shù)分別為二叉排序樹(shù)。
4.平衡二叉樹(shù):這是一種概念,是二叉查找樹(shù)的一個(gè)進(jìn)化體,它有幾種實(shí)現(xiàn)方式:紅黑樹(shù)、AVL樹(shù)。平衡二叉樹(shù)的特點(diǎn)是任意節(jié)點(diǎn)的子樹(shù)的高度差都小于等于1。

1.1、如何實(shí)現(xiàn)二叉樹(shù)?

二叉樹(shù)的存儲(chǔ)結(jié)構(gòu)分類
1.二叉樹(shù)的數(shù)組存儲(chǔ)結(jié)構(gòu)
一般使用數(shù)組只適合表示完全二叉樹(shù),因?yàn)椴皇峭耆鏄?shù)會(huì)有空間的浪費(fèi)等問(wèn)題。
并且實(shí)際應(yīng)用中,也只有堆會(huì)用數(shù)組的形式存儲(chǔ)。因?yàn)槎褲M足完全二叉樹(shù)。

typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}HP;

2、二叉樹(shù)的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)
常用鏈表來(lái)指示元素的邏輯關(guān)系。
通常,以鏈表中的每一個(gè)結(jié)點(diǎn),三個(gè)域組成,分別是數(shù)據(jù)域、左指針域和右指針域,左指針指向左孩子,右指針指向右孩子。
鏈?zhǔn)浇Y(jié)構(gòu)也分為二叉鏈和三叉鏈,一般是二叉鏈。高階數(shù)據(jù)結(jié)構(gòu)涉及三叉鏈。

typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}TreeNode;

2、二叉樹(shù)的實(shí)現(xiàn)

2.1、二叉樹(shù)的BinaryTree.h

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>

typedef char BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType Val;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

// 通過(guò)前序遍歷的數(shù)組"ABD##E#H##CF##G##"構(gòu)建二叉樹(shù)
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi);

// 二叉樹(shù)銷(xiāo)毀
void BinaryTreeDestory(BTNode** root);

// 二叉樹(shù)節(jié)點(diǎn)個(gè)數(shù)
int BinaryTreeSize(BTNode* root);

// 二叉樹(shù)葉子節(jié)點(diǎn)個(gè)數(shù)
int BinaryTreeLeafSize(BTNode* root);

// 二叉樹(shù)的高度/深度
int BinaryTreeHeight(BTNode* root);

// 二叉樹(shù)第k層節(jié)點(diǎn)個(gè)數(shù)
int BinaryTreeLevelKSize(BTNode* root, int k);

// 二叉樹(shù)查找值為x的節(jié)點(diǎn)
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);

// 二叉樹(shù)前序遍歷 
void BinaryTreePrevOrder(BTNode* root);

// 二叉樹(shù)中序遍歷
void BinaryTreeInOrder(BTNode* root);

// 二叉樹(shù)后序遍歷
void BinaryTreePostOrder(BTNode* root);


//創(chuàng)建隊(duì)列結(jié)構(gòu)體成員與變量
typedef struct BinaryTreeNode* QDatetype;//注意這里的返回類型和參數(shù)與二叉樹(shù)的接口類型要對(duì)應(yīng)

typedef struct QueueNode
{
	QDatetype val;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

//隊(duì)列初始化
void QueueInit(Queue* pq);

//隊(duì)列銷(xiāo)毀
void QueueDestory(Queue* pq);

//元素入隊(duì)
void QueuePush(Queue* pq, QDatetype x);

//元素出隊(duì)
void QueuePop(Queue* pq);

//獲取隊(duì)頭元素
QDatetype QueueFront(Queue* pq);

//獲取隊(duì)尾元素
QDatetype QueueBack(Queue* pq);

//獲取隊(duì)列元素個(gè)數(shù)或隊(duì)列大小
int QueueSize(Queue* pq);

//隊(duì)列判斷空
bool QueueEmpty(Queue* pq);

// 層序遍歷
void BinaryTreeLevelOrder(BTNode* root);

// 判斷二叉樹(shù)是否是完全二叉樹(shù)
bool BinaryTreeComplete(BTNode* root);

//寫(xiě)法2:
//int BinaryTreeComplete2(BTNode* root);

2.2、二叉樹(shù)的BinaryTree.c

2.2.1、二叉樹(shù)的構(gòu)建
// 通過(guò)前序遍歷的數(shù)組"ABD##E#H##CF##G##"構(gòu)建二叉樹(shù)
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi)
{
	assert(a);
	if (a[*pi] == '#' || *pi >= n)
	{
		++(*pi);
		return NULL;
	}
	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	if (root == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	root->Val = a[*pi];
	++(*pi);
	root->left = BinaryTreeCreate(a, n, pi);
	root->right = BinaryTreeCreate(a, n, pi);
	return root;
}
2.2.2、二叉樹(shù)銷(xiāo)毀
// 二叉樹(shù)銷(xiāo)毀
void BinaryTreeDestory(BTNode** root)
{
	if (*root == NULL)
	{
		return;
	}
	BinaryTreeDestory(&(*root)->left);
	BinaryTreeDestory(&(*root)->right);
	free(*root);
	*root = NULL;
}
2.2.3、二叉樹(shù)前序、中序、后序遍歷操作
// 二叉樹(shù)前序遍歷 
void BinaryTreePrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		//printf("# ");
		return;
	}
	printf("%c ", root->Val);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);
}

// 二叉樹(shù)中序遍歷
void BinaryTreeInOrder(BTNode* root)
{
	if (root == NULL)
	{
		//printf("# ");
		return;
	}
	BinaryTreeInOrder(root->left);
	printf("%c ", root->Val);
	BinaryTreeInOrder(root->right);
}

// 二叉樹(shù)后序遍歷
void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		//printf("# ");
		return;
	}
	BinaryTreePostOrder(root->left);
	BinaryTreePostOrder(root->right);
	printf("%c ", root->Val);
}

2.2.4、二叉樹(shù)取結(jié)點(diǎn)個(gè)數(shù)操作
// 二叉樹(shù)節(jié)點(diǎn)個(gè)數(shù)
int BinaryTreeSize(BTNode* root)
{
	return root == NULL ? 0 : BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
2.2.5、二叉樹(shù)取葉子結(jié)點(diǎn)個(gè)數(shù)操作
// 二叉樹(shù)葉子節(jié)點(diǎn)個(gè)數(shù)
int BinaryTreeLeafSize(BTNode* root)
{
	//為空返回0,不能assert,否則遞歸走不動(dòng)
	if (root == NULL)
	{
		return 0;
	}
	//只有根節(jié)點(diǎn)或葉子節(jié)點(diǎn),則返回1
	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	//其余情況的葉子節(jié)點(diǎn)=左子樹(shù)葉子節(jié)點(diǎn)+右子樹(shù)葉子節(jié)點(diǎn)
	return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}
2.2.6、取二叉樹(shù)的高度/深度操作
int BinaryTreeHeight(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	return fmax(BinaryTreeHeight(root->left), BinaryTreeHeight(root->right)) + 1;
}
2.2.7、二叉樹(shù)取第k層結(jié)點(diǎn)個(gè)數(shù)操作
// 二叉樹(shù)第k層節(jié)點(diǎn)個(gè)數(shù)
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	assert(k > 0);
	//為空
	if (root == NULL)
		return 0;
	//根節(jié)點(diǎn)
	if (k == 1)
		return 1;
	//其余層,遞歸k-1
	return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}
2.2.8、二叉樹(shù)取查找值為x的節(jié)點(diǎn)操作
// 二叉樹(shù)查找值為x的節(jié)點(diǎn)
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	//參數(shù)為空
	if (root == NULL)
	{
		return NULL;
	}
	//根節(jié)點(diǎn)匹配,則返回空節(jié)點(diǎn)
	if (root->Val == x)
	{
		return root;
	}
	//遍歷左右子樹(shù),找匹配值
	BTNode* ret1 = BinaryTreeFind(root->left, x);
	if (ret1)
	{
		return ret1;
	}
	BTNode* ret2 = BinaryTreeFind(root->right, x);
	if (ret2)
	{
		return ret2;
	}
	//遍歷結(jié)束都沒(méi)有匹配,則返回空
	return NULL;
}
2.2.9、二叉樹(shù)層序遍歷操作
//隊(duì)列初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

//隊(duì)列銷(xiāo)毀
void QueueDestory(Queue* pq)
{
	assert(pq);
	//工作指針,遍歷銷(xiāo)毀
	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

//元素入隊(duì)
void QueuePush(Queue* pq, QDatetype x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->next = NULL;
	newnode->val = x;
	//空隊(duì)列的處理
	if (pq->ptail == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		//尾指針后移
		pq->ptail = newnode;
	}
	pq->size++;
}

//元素出隊(duì)
void QueuePop(Queue* pq)
{
	assert(pq);
	//判空,空隊(duì)列不能出隊(duì)
	assert(pq->phead);
	//兼容只有一個(gè)節(jié)點(diǎn)的情況
	//delfront保存當(dāng)前頭指針地址,以便free掉,并防止內(nèi)存泄漏
	QNode* delfront = pq->phead;
	//首元素出隊(duì),頭指針直接后移即可
	pq->phead = pq->phead->next;
	free(delfront);
	delfront = NULL;
	//只有一個(gè)節(jié)點(diǎn)時(shí),出隊(duì)后,為空,那么尾指針也得置空
	if (pq->phead == NULL)
	{
		pq->ptail = NULL;
	}
	pq->size--;
}

//獲取隊(duì)頭元素
QDatetype QueueFront(Queue* pq)
{
	assert(pq);
	//判空,為空沒(méi)有元素取
	assert(pq->phead);
	return pq->phead->val;
}

//獲取隊(duì)尾元素
QDatetype QueueBack(Queue* pq)
{
	assert(pq);
	//判空,為空沒(méi)有元素取
	assert(pq->phead);
	return pq->ptail->val;
}

//獲取隊(duì)列元素個(gè)數(shù)或隊(duì)列大小
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

//隊(duì)列判斷空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL;
}

// 層序遍歷
void BinaryTreeLevelOrder(BTNode* root)
{
	assert(root);
	//創(chuàng)建隊(duì)列
	Queue q;
	QueueInit(&q);
	if (root)
	{
		QueuePush(&q, root);
	}
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		printf("%c ", front->Val);
		if (front->left)
		{
			QueuePush(&q, front->left);
		}
		if (front->right)
		{
			QueuePush(&q, front->right);
		}
		QueuePop(&q);
	}
	printf("\n");
	QueueDestory(&q);
}

2.2.10、二叉樹(shù)判斷是否為完全二叉樹(shù)操作

判斷完全二叉樹(shù)的思路1;
1.如果樹(shù)為空,直接返回錯(cuò)誤;
2.如果樹(shù)非空,層序遍歷二叉樹(shù);
3.如果一個(gè)結(jié)點(diǎn)左右孩子均Not NULL時(shí),則pop該結(jié)點(diǎn),將其左右孩子入隊(duì)列;
4.如果遇到一個(gè)結(jié)點(diǎn),左孩子為空,而右孩子非空,則一定不為完全二叉樹(shù);
5.如果遇到一個(gè)結(jié)點(diǎn),左孩子不為空,而右孩子為空;或者是左右孩子均為空,則結(jié)點(diǎn)之后的隊(duì)列的結(jié)點(diǎn)都為葉子結(jié)點(diǎn);
滿足以上條件則為完全二叉樹(shù),否則不是完全二叉樹(shù)。
核心思想:類似于層序一層層的節(jié)點(diǎn)構(gòu)造而成,即最后一層的節(jié)點(diǎn)上面的層節(jié)點(diǎn)都是滿的。前提是最后一層不是根節(jié)點(diǎn),即第一層.
所以遍歷不連續(xù)就不是完全二叉樹(shù),并且隊(duì)列比棧適用于判斷的重要原因之一就是,第一個(gè)NULL出隊(duì)列時(shí),所有的非空節(jié)點(diǎn)一定會(huì)進(jìn)隊(duì)列。

// 判斷二叉樹(shù)是否是完全二叉樹(shù)
bool BinaryTreeComplete(BTNode* root)
{
	assert(root);
	Queue q;
	QueueInit(&q);
	if (root)
	{
		QueuePush(&q, root);
	}
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		//遇見(jiàn)空就結(jié)束
		if (front == NULL)
		{
			break;
		}
		QueuePush(&q, front->left);
		QueuePush(&q, front->right);
	}
	//因?yàn)槌龅娇眨顺鲅h(huán)后,再寫(xiě)一個(gè)循環(huán)判斷隊(duì)列里是否還有非空
	//若有非空,則false,若沒(méi)有非空或不進(jìn)入循環(huán),則true
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		//遇見(jiàn)空就結(jié)束
		if (front)
		{
			QueueDestory(&q);
			return false;
		}
	}
	QueueDestory(&q);
	return true;
}

2.2.11、二叉樹(shù)的判空
//二叉樹(shù)判空
bool BinaryTreeEmpty(BTNode* root)
{
	return root == NULL;
}

2.3、二叉樹(shù)的main.c

#include "BinaryTree.h"

int main()
{
	char str[] = "ABC##DE#G##F###";// ABC##DE#G##F###
	//char str2[] = "ABCDEGF";
	int len = strlen(str);
	int NodeNum = 0;
	BTNode* tree = BinaryTreeCreate(str, len, &NodeNum);

	printf("前序遍歷:");
	// 二叉樹(shù)前序遍歷 
	BinaryTreePrevOrder(tree);
	printf("\n");

	printf("中序遍歷:");
	// 二叉樹(shù)中序遍歷
	BinaryTreeInOrder(tree);
	printf("\n");

	printf("后序遍歷:");
	// 二叉樹(shù)后序遍歷
	BinaryTreePostOrder(tree);
	printf("\n");

	// 二叉樹(shù)節(jié)點(diǎn)個(gè)數(shù)
	printf("節(jié)點(diǎn)個(gè)數(shù):%d\n", BinaryTreeSize(tree));

	printf("層序遍歷:");
	// 層序遍歷
	BinaryTreeLevelOrder(tree);
	printf("\n");

	//二叉樹(shù)判空
	if (BinaryTreeEmpty(tree))
	{
		printf("空樹(shù)\n");
	}
	else
	{
		printf("非空樹(shù)\n");
	}

	// 判斷二叉樹(shù)是否是完全二叉樹(shù)
	if (BinaryTreeComplete(tree))
	{
		printf("是完全二叉樹(shù)\n");
	}
	else
	{
		printf("非完全二叉樹(shù)\n");
	}

	// 二叉樹(shù)葉子節(jié)點(diǎn)個(gè)數(shù)
	printf("葉子節(jié)點(diǎn):%d\n", BinaryTreeLeafSize(tree));

    //計(jì)算二叉樹(shù)的高度
	printf("二叉樹(shù)的高度:%d\n", BinaryTreeHeight(tree));

	// 二叉樹(shù)第k層節(jié)點(diǎn)個(gè)數(shù)
	printf("第k層葉子節(jié)點(diǎn):%d\n", BinaryTreeLevelKSize(tree, 3));

	// 二叉樹(shù)查找值為x的節(jié)點(diǎn)
	printf("第k層葉子節(jié)點(diǎn):%c\n", BinaryTreeFind(tree, 'E')->Val);

	// 二叉樹(shù)銷(xiāo)毀
	BinaryTreeDestory(&tree);
	return 0;
}

運(yùn)行結(jié)果,如圖所示
【數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)的構(gòu)建和遍歷】,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),筆記,二叉樹(shù)的遍歷,單值二叉樹(shù),層序遍歷,判斷完全二叉樹(shù),左葉子節(jié)點(diǎn)個(gè)數(shù)

3、二叉樹(shù)OJ鞏固練習(xí)

3.1、練習(xí)題1:二叉樹(shù)的深度

核心思想就是取左右子樹(shù)葉子節(jié)點(diǎn)的高度,將比較大的值+根節(jié)點(diǎn)的第一層即可。因?yàn)橛?jì)算是以0計(jì)算所以需要把第一層加回來(lái)。或者+1也可以理解為(考慮只有根節(jié)點(diǎn)),加自己本身這層,就像數(shù)數(shù)需要加上自己。
方法1:fmax調(diào)用庫(kù)函數(shù)更方便,fmax用于比較出較大值并返回較大值。頭文件:<math.h>
方法2:通過(guò)變量保存,遞歸的值,最后比較大小之后加回第一層。

//方法1:fmax函數(shù)
/**/
int calculateDepth(struct TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	return fmax(calculateDepth(root->left), calculateDepth(root->right)) + 1;
}


//方法2:保存變量
/**/
int calculateDepth(struct TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	int left = calculateDepth(root->left);
	int right = calculateDepth(root->right);
	return left > right ? left + 1 : right + 1;
}

3.2、練習(xí)題2:?jiǎn)沃刀鏄?shù)

單值二叉樹(shù)(每個(gè)節(jié)點(diǎn)都具有相同的值) — 給定的二叉樹(shù)是單值二叉樹(shù)就返回true,否則就返回false
思路:排除法和分治法,檢查每個(gè)節(jié)點(diǎn)和他的孩子的值是否匹配。

bool isUnivaTree(struct TreeNode* root)
{
	if (root == NULL)
	{
		return true;
	}
	//排除法,排除左孩子值與其父節(jié)點(diǎn)值不等
	if (root->left && root->lefd->val != root->val)
	{
		return false;
	}
	//排除法,排除右孩子值與其父節(jié)點(diǎn)值不等
	if (root->right && root->right->val != root->val)
	{
		return false;
	}
	//執(zhí)行遞歸,返回結(jié)果,若是不滿足上述排除的情況,說(shuō)明滿足單值二叉樹(shù)
	return isUnivaTree(root->left) && isUnivaTree(root->right);
}

3.3、練習(xí)題3:相同的樹(shù)

相同的樹(shù) — 給你兩棵二叉樹(shù)的根節(jié)點(diǎn)p和q,編寫(xiě)一個(gè)函數(shù)來(lái)檢驗(yàn)這兩棵樹(shù)是否相同(如果這兩棵樹(shù)的結(jié)構(gòu)和節(jié)點(diǎn)值相同,則認(rèn)為是相同的)
思路:排除法和分治法,自己比,左子樹(shù)比,右子樹(shù)比

bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
	//都為空
	if (p == NULL && q == NULL)
		return true;
	//其中一個(gè)為空
	if (p == NULL || q == NULL)
		return false;
	//都不為空且不相等
	if (p->val != q->val)
		return false;
	//遞歸遍歷完,都不滿足上述排除的情況,則滿足相同的樹(shù)。
	return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}

3.4、練習(xí)題4:二叉樹(shù)的前序遍歷 存入數(shù)組

這道題的關(guān)鍵在于獲取結(jié)點(diǎn)個(gè)數(shù)開(kāi)辟數(shù)組,并涉及前序遍歷的參數(shù)設(shè)計(jì)細(xì)節(jié)問(wèn)題。
方法1:遞歸法
方法2:全局變量法(不推薦)
方法3:指針?lè)?/p>

int TreeSize(struct TreeNode* root)
{
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

void preorder(struct TreeNode* root, int* a, int i)
{
	if (root == NULL)
		return;
	a[i++] = root->val;
	preorder(root->left,a,i);
	preorder(root->right,a,i);
}
//全局變量法
//int i = 0;
//void preorder(struct TreeNode* root, int* a)
//{
//	if (root == NULL)
//		return;
//	a[i++] = root->val;
//	preorder(root->left, a);
//	preorder(root->right, a);
//}

//指針?lè)?/span>
void preorder(struct TreeNode* root, int* a, int* pi)
{
	if (root == NULL)
		return;
	a[(*pi)++] = root->val;
	preorder(root->left, a, pi);
	preorder(root->right, a, pi);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
	int n = TreeSize(root);
	int* a = (int*)malloc(sizeof(int) * n);
	*returnSize = n;
	
    //方法1:遞歸法
	preorder(root, a, 0);
    
    //方法2:全局變量法(不推薦)
	//i= 0; --- 必須置0
	//preorder(root, a); -- 全局變量法,但盡量不用
    
    //方法3:指針?lè)?/span>
	//int i = 0;
	//preorder(root, a, &i);
	return a;
}

3.5、練習(xí)題5:對(duì)稱二叉樹(shù)

對(duì)稱(鏡像)二叉樹(shù) — 給你一個(gè)二叉樹(shù)的根結(jié)點(diǎn)root,檢查它是否軸對(duì)稱。
思路:設(shè)計(jì)一個(gè)復(fù)用函數(shù),繼續(xù)利用排除法和遞歸遍歷,排除不成立的結(jié)果,能成功返回的對(duì)稱二叉樹(shù)。

bool _isSymmetric(struct TreeNode* root1, struct TreeNode* root2)
{
	if (root1 == NULL && root2 == NULL)
	{
		return true;
	}
	//一個(gè)為空,另一個(gè)不為空
	if (root1 == NULL || root2 == NULL)
	{
		return false;
	}
	//都不為空
	if (root1->val != root2->val)
	{
		return false;
	}
	return _isSymmetric(root1->left, root2->right) && _isSymmetric(root1->right, root2->left);
}
bool isSymmetric(struct TreeNode* root)
{
	return _isSymmetric(root->left, root->right);
}

3.6、練習(xí)題6:另一棵樹(shù)的子樹(shù)

另一棵樹(shù)的子樹(shù):給兩顆二叉樹(shù),檢驗(yàn)一棵樹(shù)是否包含另一棵樹(shù)的子樹(shù)。
思路:結(jié)合上面相同的樹(shù)的方法,去匹配子樹(shù)

//相同的樹(shù)
bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
	//都為空
	if (p == NULL && q == NULL)
		return true;
	//其中一個(gè)為空
	if (p == NULL || q == NULL)
		return false;
	//都不為空且不相等
	if (p->val != q->val)
		return false;
	return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
//另一棵樹(shù)的子樹(shù)
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
    //為空沒(méi)有子樹(shù),匹配失敗
	if (root == NULL)
		return false;
	//根節(jié)點(diǎn)匹配,調(diào)用相同的樹(shù)方法,去匹配
	if (root->val == subRoot->val)
		return isSameTree(root, subRoot);
	//遞歸前序遍歷匹配
	return isSameTree(root, subRoot) || 
	isSameTree(root->left, subRoot) || 
	isSameTree(root->right, subRoot);
}

3.7、練習(xí)題7:計(jì)算左葉子節(jié)點(diǎn)個(gè)數(shù)

計(jì)算二叉樹(shù)中左葉子節(jié)點(diǎn)的個(gè)數(shù)。
思路:遞歸遍歷左右子樹(shù),累計(jì)左葉子節(jié)點(diǎn)個(gè)數(shù)即可。
1.判斷是否為空
2.判斷是否為左葉子節(jié)點(diǎn)
3.遞歸累加。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-832574.html

// 二叉樹(shù)左葉子節(jié)點(diǎn)個(gè)數(shù)
int BinaryTreeLeftLeafSize(BTNode* root)
{
	//為空返回0
	if (root == NULL)
	{
		return 0;
	}
	//判斷有左孩子,并是左葉子節(jié)點(diǎn)
	if (root->left && root->left->left == NULL && root->left->right == NULL)
	{
		return 1;
	}
	//其余情況的左葉子節(jié)點(diǎn)=左子樹(shù)葉子節(jié)點(diǎn)+右子樹(shù)葉子節(jié)點(diǎn)
	return BinaryTreeLeftLeafSize(root->left) + BinaryTreeLeftLeafSize(root->right);
}

到了這里,關(guān)于【數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)的構(gòu)建和遍歷】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu)與算法之二叉樹(shù): Leetcode 111. 二叉樹(shù)的最小深度 (Typescript版)

    二叉樹(shù)的最小深度 https://leetcode.cn/problems/minimum-depth-of-binary-tree/ 描述 就 給定一個(gè)二叉樹(shù),找出其最小深度。 最小深度是從根節(jié)點(diǎn)到最近葉子節(jié)點(diǎn)的最短路徑上的節(jié)點(diǎn)數(shù)量。 說(shuō)明:葉子節(jié)點(diǎn)是指沒(méi)有子節(jié)點(diǎn)的節(jié)點(diǎn)。 示例 1 示例 2 提示 樹(shù)中節(jié)點(diǎn)數(shù)的范圍在 [0, 1 0 5 10^5 1 0 5 ] 內(nèi)

    2024年02月06日
    瀏覽(29)
  • 數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)構(gòu)建、廣度/深度優(yōu)先(前序、中序、后序)遍歷

    數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)構(gòu)建、廣度/深度優(yōu)先(前序、中序、后序)遍歷

    說(shuō)到樹(shù),我們暫時(shí)忘記學(xué)習(xí),來(lái)看一下大自然的樹(shù): 哈哈 以上照片是自己拍的,大家湊合看看 回歸正題,那么在數(shù)據(jù)結(jié)構(gòu)中,樹(shù)是什么呢,通過(guò)上面的圖片大家也可以理解 樹(shù)是一種非線性的數(shù)據(jù)結(jié)構(gòu) 像這樣 ,有多個(gè)節(jié)點(diǎn)組成的有一定層次關(guān)系的結(jié)構(gòu),像是一顆相對(duì)于天空

    2024年02月03日
    瀏覽(21)
  • 【數(shù)據(jù)結(jié)構(gòu)】二叉樹(shù)的構(gòu)建與基本操作實(shí)現(xiàn)

    【數(shù)據(jù)結(jié)構(gòu)】二叉樹(shù)的構(gòu)建與基本操作實(shí)現(xiàn)

    ?? 樊梓慕: 個(gè)人主頁(yè) ? ?? 個(gè)人專欄: 《C語(yǔ)言》《數(shù)據(jù)結(jié)構(gòu)》《藍(lán)橋杯試題》《LeetCode刷題筆記》《實(shí)訓(xùn)項(xiàng)目》 ?? 每一個(gè)不曾起舞的日子,都是對(duì)生命的辜負(fù) 目錄 前言 1.前序建立二叉樹(shù) 2.銷(xiāo)毀二叉樹(shù) 3.統(tǒng)計(jì) 4.查找值為x的節(jié)點(diǎn) 5.前中后序遍歷 6.層序遍歷 7.判斷二叉樹(shù)是否

    2024年02月07日
    瀏覽(25)
  • 初階數(shù)據(jù)結(jié)構(gòu)之---二叉樹(shù)鏈?zhǔn)浇Y(jié)構(gòu)(二叉樹(shù)的構(gòu)建,二叉樹(shù)的前序,中序,后序和層序遍歷,計(jì)算二叉樹(shù)結(jié)點(diǎn)個(gè)數(shù),第k層結(jié)點(diǎn)個(gè)數(shù),葉子結(jié)點(diǎn)個(gè)數(shù),判斷是否為完全二叉樹(shù))

    初階數(shù)據(jù)結(jié)構(gòu)之---二叉樹(shù)鏈?zhǔn)浇Y(jié)構(gòu)(二叉樹(shù)的構(gòu)建,二叉樹(shù)的前序,中序,后序和層序遍歷,計(jì)算二叉樹(shù)結(jié)點(diǎn)個(gè)數(shù),第k層結(jié)點(diǎn)個(gè)數(shù),葉子結(jié)點(diǎn)個(gè)數(shù),判斷是否為完全二叉樹(shù))

    本篇博客是初階數(shù)據(jù)結(jié)構(gòu)樹(shù)的收尾,將會(huì)講掉 基本二叉樹(shù)鏈?zhǔn)浇Y(jié)構(gòu)的具體內(nèi)容和實(shí)現(xiàn),包括二叉樹(shù)的構(gòu)建,前序遍歷,中序遍歷,后序遍歷和層序遍歷,計(jì)算二叉樹(shù)結(jié)點(diǎn)個(gè)數(shù),第k層結(jié)點(diǎn)個(gè)數(shù),二叉樹(shù)葉子結(jié)點(diǎn)個(gè)數(shù),以及判斷一個(gè)二叉樹(shù)是否為完全二叉樹(shù) 。話不多說(shuō),開(kāi)始我

    2024年03月24日
    瀏覽(28)
  • 數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)

    數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)

    前言:我們前面已經(jīng)學(xué)習(xí)了數(shù)據(jù)結(jié)構(gòu)的棧和隊(duì)列,今天我們就來(lái)學(xué)習(xí)一下數(shù)據(jù)結(jié)構(gòu)中的二叉樹(shù),那么作為二叉樹(shù)我們就得先了解樹(shù)的一些概念,還有二叉樹(shù)一些特點(diǎn)。 樹(shù)是一種非線性的數(shù)據(jù)結(jié)構(gòu),它是由n(n=0)個(gè)有限結(jié)點(diǎn)組成一個(gè)具有層次關(guān)系的集合。把它叫做樹(shù)是因 為它

    2024年02月05日
    瀏覽(32)
  • 數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)和平衡二叉樹(shù)

    1、二叉樹(shù): 2、平衡二叉樹(shù):

    2024年04月17日
    瀏覽(36)
  • 11. 數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)

    11. 數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)

    上一節(jié),簡(jiǎn)單概述了樹(shù)這種數(shù)據(jù)結(jié)構(gòu),以及樹(shù)結(jié)構(gòu)向下,具有某些一些特征的樹(shù),比如二叉樹(shù),B樹(shù),B+樹(shù),堆等。其中,二叉樹(shù)是一個(gè)很重要的模塊。也是在一些技術(shù)面試中,可能會(huì)問(wèn)到的問(wèn)題。本節(jié),我們就二叉樹(shù),做詳細(xì)介紹。 二叉樹(shù)是一個(gè) 邏輯結(jié)構(gòu) , 底層可以用數(shù)組

    2024年02月07日
    瀏覽(19)
  • 數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)(詳細(xì)版)

    數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)(詳細(xì)版)

    ? ? ? ? 二叉樹(shù)作為數(shù)據(jù)結(jié)構(gòu)的一種,尤為重要,下面是對(duì)二叉樹(shù)的詳細(xì)講解。想要了解二叉樹(shù),首先要了解 二叉樹(shù)的基本概念,以及創(chuàng)建二叉樹(shù)的結(jié)構(gòu),再深層點(diǎn),遍歷二叉樹(shù)的前序中序和后續(xù),其次是層序,后面將會(huì)講解如何計(jì)算二叉樹(shù)的高和葉結(jié)點(diǎn) 等等。 ???????

    2024年02月03日
    瀏覽(26)
  • 數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)簡(jiǎn)介

    二叉樹(shù)是一種非線性數(shù)據(jù)結(jié)構(gòu),代表“祖先”與“后代”之間的派生關(guān)系,體現(xiàn)了“一分為二”的分治邏輯。與鏈表相似,二叉樹(shù)的基本單元是節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)包含值,左子節(jié)點(diǎn)的索引,右子節(jié)點(diǎn)的索引 當(dāng)給定一個(gè)二叉樹(shù)的節(jié)點(diǎn)時(shí),我們將該節(jié)點(diǎn)的左子節(jié)點(diǎn)及其以下節(jié)點(diǎn)形成

    2024年02月01日
    瀏覽(34)
  • 數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)(Java)

    數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)(Java)

    在這里先說(shuō)明一下,結(jié)點(diǎn)和節(jié)點(diǎn)其實(shí)一樣的,無(wú)須關(guān)注這個(gè)。 1. 概念:樹(shù)是一種非線性的數(shù)據(jù)結(jié)構(gòu),它是由n個(gè)有限節(jié)點(diǎn)組成一個(gè)具有層次關(guān)系的集合。 如上圖所示,把此種數(shù)據(jù)結(jié)構(gòu)稱作樹(shù)是因?yàn)樗雌饋?lái)像一個(gè)倒掛的樹(shù)。 ?2. 特點(diǎn) 有一個(gè)特殊的節(jié)點(diǎn),稱為根節(jié)點(diǎn),它是唯一

    2024年02月07日
    瀏覽(18)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包