目录 

树的先序、中序、后序、层次遍历代码

求二叉树的宽度 

输出二叉树每一层的最右节点 

二叉排序树转换成有序双向链表

二叉搜索树的查找、插入、删除

二叉树的最大距离(即相距最远的两个叶子节点)


赫夫曼编码

赫夫曼树的一个重要应用是赫夫曼编码。这里的编码是将要传送的文字转换为二进制的字符串(由0和1组成的字符串)。

根据给定字符串权值求赫夫曼编码的过程,实际上就是根据给定权值构造赫夫曼树的过程。以A、B、C、D的权值(或出现频率)分别为0.4,0.3,0.1,0.2为例

                                               

插入、删除、查找的时间复杂度

二叉树的主要性质

性质1:非空二叉树的叶子结点数等于双分支结点数加1。

性质2:

完全二叉树的一些性质

1.高度(或深度)为k的二叉树最多有2^k-1个节点。换句话说,满二叉树中前k层的节点个数为2^k-1。

2.具有n个节点的完全二叉树的高度(或深度)为「log2n」+1,符号是向下取整。

树的先序、中序、后序、层次遍历代码

#include<iostream>
#include<stack>
#include<queue>
using namespace std;
/*
实现二叉树的先序、中序、后序遍历,包括递归方式和非递归
方式
*/
class Node {
public:
	int value;
	Node *left;
	Node *right;
	Node(int data)
	{
		value = data;
		left = right = NULL;
	}
};
/递归版本
void preOrderRecur(Node *head)
{
	if (head == NULL)
		return;
	cout << head->value << "	";
	preOrderRecur(head->left);
	preOrderRecur(head->right);
}
void inOrderRecur(Node *head)
{
	if (head == NULL)
		return;
	preOrderRecur(head->left);
	cout << head->value << "	";
	preOrderRecur(head->right);
}
void posOrderRecur(Node *head)
{
	if (head == NULL)
		return;
	preOrderRecur(head->left);
	preOrderRecur(head->right);
	cout << head->value << "	";
}
/非递归版本/
//先序非递归
void preOrderUnRecur(Node *head)
{
	if (head != NULL)
	{
		stack<Node*> s1;
		s1.push(head);
		while (s1.empty() == 0)
		{
			head = s1.top();
			cout << head->value << "	";
			s1.pop();
			if (head->right != NULL)
				s1.push(head->right);
			if (head->left != NULL)
				s1.push(head->left);
		}
	}
}
//中序非递归
void inOrderUnRecur(Node *head)
{
	if (head != NULL)
	{
		stack<Node*> s1;
		while (s1.empty() == 0 || head != NULL)
		{
			if (head != NULL)
			{
				s1.push(head);
				head = head->left;
			}
			else
			{
				head = s1.top();
				cout << head->value << "	";
				s1.pop();
				head = head->right;
			}
		}
	}
}
//后序非递归
/*
先序是根左右,后序是左右根,所以思想就是按根右左先排好,
然后放入另一个栈中,然后按顺序出栈,就成了左右根
*/
void posOrderUnRecur1(Node *head)
{
	if (head != NULL)
	{
		stack<Node*> s1;
		stack<Node*> s2;
		s1.push(head);
		while (s1.empty() == 0)
		{
			head = s1.top();
			s1.pop();
			s2.push(head);
			if (head->left != NULL)
				s1.push(head->left);
			if (head->right != NULL)
				s1.push(head->right);
		}
		while (s2.empty() == 0)
		{
			cout << s2.top()->value << "	";
			s2.pop();
		}
	}
}
//层次遍历
void LevelOrder(Node *head)
{
	queue<Node *> qNode;
	if (head == NULL)
		return;
	qNode.push(head);
	while(!qNode.empty())
	{
		head = qNode.front();
		cout << head->value << "	";
		qNode.pop();
		if (head->left != NULL)
			qNode.push(head->left);
		if (head->right != NULL)
			qNode.push(head->right);
	}
}

求二叉树的宽度 

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
class BiTree {
public:
	int value;
	BiTree *left;
	BiTree *right;
	BiTree(int v) :value(v), left(nullptr), right(nullptr) {}
};
int WidthOfBiTree(BiTree *root)
{
	if (root == nullptr)
		return 0;
	int maxValue = 0;
	queue<BiTree *> q;
	q.push(root);
	while (!q.empty())
	{
		//每一层的结点总数
		int len = q.size();
		if (len > maxValue)
			maxValue = len;
		while (len)
		{
			BiTree *node = q.front();
			q.pop();
			--len;
			if (node->left != nullptr)
				q.push(node->left);
			if (node->right != nullptr)
				q.push(node->right);
		}
		
	}
	return maxValue;
}

输出二叉树每一层的最右节点 

思想同样可以解决非递归求解二叉树的深度

#include<queue>
using namespace std;
class BiTree {
public:
	int value;
	BiTree *left;
	BiTree *right;
	BiTree(int v) :value(v), left(nullptr), right(nullptr) {}
};
void findRightNode(BiTree *root)
{
	if (root == nullptr)
		return;
	int maxValue = 0;
	queue<BiTree *> q;
	q.push(root);
	while (!q.empty())
	{
		//每一层的结点总数
		int len = q.size();
		while (len)
		{
			BiTree *node = q.front();
			if (len == 1)
				cout << node->value << endl;
			q.pop();
			--len;
			if (node->left != nullptr)
				q.push(node->left);
			if (node->right != nullptr)
				q.push(node->right);
		}	
	}
	return;
}

二叉排序树转换成有序双向链表

//结点的结构
struct BSTNode{
    int data;
    BSTNode *left;
    BSTNode *right;
};

//主函数
BSTNode* Convert2DoubleLinkList(BSTNode *root)
{
    if(root == NULL)    
        return NULL;

    BSTNode *last = NULL;

    //二叉排序树转换成排序双向链表
    Convert(root, &last);

    //取得双向链表的头指针
    while(root->left != NULL)
        root = root->left;

    return root;
}

//二叉排序树转换成双向链表
void Convert(BSTNode *root, BSTNode** last)
{
    if(root == NULL)
        return;

    //遍历左子树
    Convert(root->left, last);

    //处理根节点
    root->left = *last;
    if((*last) != NULL)
        (*last)->right = root;
    *last = root;

    //遍历右子树
    Convert(root->right, last);
}

二叉搜索树的查找、插入、删除

#include<iostream>
using namespace std;
struct BSTNode {
	int value;
	BSTNode *left;
	BSTNode *right;
	BSTNode(int v) :value(v), left(nullptr), right(nullptr) {}
};
//二叉搜索树查找算法
BSTNode* bst_search(BSTNode* node, int value)
{
	while (node != nullptr)
	{
		if (value == node->value)//找到
			return node;
		else if (value < node->value)//向左
			node = node->left;
		else//向右
			node = node->right;
	}
	return nullptr;
}
//二叉搜索树插入算法
bool bst_insert(BSTNode** root, int value)
{
	BSTNode *cur = *root;
	BSTNode *pre = nullptr;//记录待插入元素的父节点
	while (cur != nullptr)
	{
		if (value == cur->value)//树中原本存在,插入失败
			return false;
		else if (value < cur->value)//向左
		{
			pre = cur;
			cur = cur->left;
		}
		else//向右
		{
			pre = cur;
			cur = cur->right;
		}
	}
	cur = new BSTNode(value);
	if (pre == nullptr)
		*root = cur;
	else
		cur->value < pre->value ? pre->left = cur : pre->right = cur;
	return true;
}
//二叉搜索树删除算法
bool bst_delete(BSTNode** root, int value)
{
	BSTNode *parent = nullptr;
	BSTNode *node = *root;
	BSTNode *temp = nullptr;
	while (node != nullptr)
	{
		if (value < node->value)//向左
		{
			parent = node;
			node = node->left;
		}
		else if (value>node->value)//向右
		{
			parent = node;
			node = node->right;
		}
		else//找到了待删除的节点
		{
			if (node->left == nullptr && node->right == nullptr)//待删除的节点是叶子节点
			{
				if (parent == nullptr)//根节点
				{
					delete node;
					root = nullptr;
				}
				else//非根节点
				{
					(parent->left == node) ? parent->left = nullptr : parent->right = nullptr;
					delete node;
					node = nullptr;
				}
			}
			else if (node->left != nullptr && node->right == nullptr)//待删除的节点只有左孩子
			{
				if (parent == nullptr)//根节点
				{
					temp = node;
					root = &(node->left);//根节点发生了变化
					delete temp;
					temp = nullptr;
				}
				else//非根节点
				{
					(parent->left == node) ? parent->left = node->left : parent->right = node->left;
					delete node;
					node = nullptr;
				}
			}
			else if (node->right != nullptr && node->left == nullptr)//待删除的节点只有右孩子
			{
				if (parent == nullptr)//根节点
				{
					temp = node;
					root = &(node->right);//根节点发生了变化
					delete temp;
					temp = nullptr;
				}
				else//非根节点
				{
					(parent->left == node) ? parent->left = node->right : parent->right = node->right;
					delete node;
					node = nullptr;
				}
			}
			else//待删除的节点既有左孩子又有右孩子
			{
				BSTNode *leftNode = node->left;
				parent = node;
				//找到左子树的最右节点,转移成为删除这个节点
				while (leftNode->right != nullptr)
				{
					parent = leftNode;
					leftNode = leftNode->right;
				}
				// 交换leftNode与node
				int swapValue = leftNode->value;
				leftNode->value = node->value;
				node->value = swapValue;
				//删除leftNode
				(parent->left == leftNode) ? (parent->left = leftNode->left) : (parent->right = leftNode->left);
				delete leftNode;
				leftNode = nullptr;
			}
			return true;
		}
	}
	return false;
}

二叉树的最大距离(即相距最远的两个叶子节点)

要求的二叉树的最大距离其实就是求:肯定是某个节点左子树的高度加上右子树的高度加2,所以求出每个节点左子树和右子树的高度,取左右子树高度之和加2的最大值即可,假设空节点的高度为-1,也就是说叶结点的高度为1。

函数的返回值是当前树的高度,nMaxDistance是最大距离。

int HeightOfBinaryTree(BinaryTreeNode*pNode, int&nMaxDistance){
	if (pNode == NULL)
		return -1;   //空节点的高度为-1
	//递归
	int nHeightOfLeftTree = HeightOfBinaryTree(pNode->m_pLeft, nMaxDistance) + 1;   //左子树的的高度加1
	int nHeightOfRightTree = HeightOfBinaryTree(pNode->m_pRight, nMaxDistance) + 1;   //右子树的高度加1
	int nDistance = nHeightOfLeftTree + nHeightOfRightTree;    //距离等于左子树的高度加上右子树的高度+2
	nMaxDistance = nMaxDistance > nDistance ? nMaxDistance : nDistance;            //得到距离的最大值
	return nHeightOfLeftTree > nHeightOfRightTree ? nHeightOfLeftTree : nHeightOfRightTree;
}

二叉树的最大路径和

给定一个非空二叉树,返回其最大路径和。

本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。

struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
int maxPathSum(TreeNode* root)
{
	int value = INT_MIN;
	int *max_sum = &value;
	dfs(root, max_sum);
	return *max_sum;
}
//dfs的返回值是给父亲用的,所以不可能出现左中右这种,
//只能是左中或者中右
int dfs(TreeNode* root, int *max_sum)
{
	if (root == nullptr)
		return 0;
	int l = dfs(root->left, max_sum);
	int r = dfs(root->right, max_sum);
	int sum = root->val;
	if (l > 0)
		sum += l;
	if (r > 0)
		sum += r;
	//记录最大值
	*max_sum = max(*max_sum, sum);
	//给父亲节点返回时,必须包含此节点,否则不就连不起来了
	return max(r, l) > 0 ? max(r, l) + root->val : root->val;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值