code--二叉树

题目列表:

参考:轻松搞定面试中的二叉树题目

1. 求二叉树的深度->树的最小深度->判断二叉树是不是完全二叉树

2.求二叉树中的节点个数->求二叉树中叶子节点的个数->求二叉树第K层的节点个数

3. 前序遍历,中序遍历,后序遍历

4.分层遍历二叉树(按层次从上往下,从左往右打印二叉树)

5. 求二叉树的镜像->对称二叉树

6. 判断两棵树是否相等->一棵树是否是另一棵树的子树->一棵树是否是另一棵树的子结构(定义空树不是任意树的子)                

7. 将二叉查找树变为有序的双向链表

8. 求二叉树中两个节点的最低公共祖先节点

9. 求二叉树中节点的最大距离

10. 由前序遍历序列和中序遍历序列重建二叉树

11.之字打印

12.二叉排序树(查询、插入、删除)

      算法导论版(搜索、最大最小结点、后继、前驱、插入、删除)


1

#include <iostream>
#include <stdio.h> 
#include <stdlib.h>
#include <queue>
using namespace std;
 定义树 //
struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
};     //要记得写 ;


///  求树的深度 
int depth(TreeNode* pRoot){
        if(!pRoot)
            return 0;
        return 1+max(depth(pRoot->left),depth(pRoot->right));
    }

///  求树的最小深度 
int minDepth(TreeNode *root) {
        // write your code here
        if(root == NULL)
            return false;

        if(root->left == NULL) return minDepth(root->right) + 1;  //单树的情况
        if(root->right == NULL) return minDepth(root->left) + 1;

        int leftDepth = minDepth(root->left);
        int rightDepth = minDepth(root->right);

        return leftDepth < rightDepth ? (leftDepth + 1) : (rightDepth + 1);
    }

  平衡二叉树 一。定义法 /
bool IsBalanced_Solution(TreeNode* pRoot) {
        if(!pRoot)
            return true;
        
        int l_depth=depth(pRoot->left);
        int r_depth=depth(pRoot->right);
        int dif=abs(l_depth-r_depth);
        return IsBalanced_Solution(pRoot->left)&&IsBalanced_Solution(pRoot->right)&&(dif<=1);
    }

  平衡二叉树 二 自底向上 better /
int dfsHeight (TreeNode *root) {
        if (root == NULL) return 0;
        
        int leftHeight = dfsHeight (root -> left);
        if (leftHeight == -1) return -1;
        int rightHeight = dfsHeight (root -> right);
        if (rightHeight == -1) return -1;
        
        if (abs(leftHeight - rightHeight) > 1)  return -1;
        return max (leftHeight, rightHeight) + 1;
    }
bool isBalanced(TreeNode *root) {
        return dfsHeight (root) != -1;
    }


2

#include <iostream>
#include <stdio.h> 
#include <stdlib.h>

using namespace std;

 定义树 //
struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
};     //要记得写 ;

/// 节点的个数 //
int GetNodeNum(TreeNode * pRoot)  
{  
    if(pRoot == NULL) // 递归出口  
        return 0;  
    return GetNodeNum(pRoot->left) + GetNodeNum(pRoot->right) + 1;  
}  

 叶子节点个数 /
int GetLeafNodeNum(TreeNode * pRoot)  
{  
    if(pRoot == NULL)  
        return 0;  
    if(pRoot->left == NULL && pRoot->right == NULL)  
        return 1;  
    int numLeft = GetLeafNodeNum(pRoot->left); // 左子树中叶节点的个数  
    int numRight = GetLeafNodeNum(pRoot->right); // 右子树中叶节点的个数  
    return (numLeft + numRight);  
} 

 第k层节点个数 /
int GetNodeNumKthLevel(TreeNode * pRoot, int k)  
{  
    if(pRoot == NULL || k < 1)  
        return 0;  
    if(k == 1)  
        return 1;  
    int numLeft = GetNodeNumKthLevel(pRoot->left, k-1); // 左子树中k-1层的节点个数  
    int numRight = GetNodeNumKthLevel(pRoot->right, k-1); // 右子树中k-1层的节点个数  
    return (numLeft + numRight);  
}  
3
#include <iostream>
#include <stdio.h> 
#include <stdlib.h>

using namespace std;

 定义树 //
struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
};     //要记得写 ;

// 前序遍历PreOrder  中序遍历InOrder 后序遍历PostOrder
void PreOrder(TreeNode* pRoot){
    if(pRoot==NULL)
        return;
    
    Visit(pRoot); // cout << root->val << " ";
    PreOrder(pRoot->left);
    // 中序 Visit(pRoot);
    PreOrder(pRoot->right);
    // 后序 Visit(pRoot);
}
4
#include <iostream>
#include <stdio.h> 
#include <stdlib.h>
#include <queue>
using namespace std;

 定义树 //
struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
};     //要记得写 ;

//广度优先搜索,使用队列实现
void Level(TreeNode* pRoot){
    if(pRoot==NULL)
        return;
    queue<TreeNode *> q;              //队列初始化
    q.push(pRoot);                    //将根节点压入队列
    while(!q.empty()){
        TreeNode* pNode=q.front();  //pNode指向队列的前端
        q.pop();                    //弹出
        Visit(pNode);               //访问
        if(pNode->left!=NULL)        //若左子节点或右子节点不为空,将其压入队列
            q.push(pNode->left);
        if(pNode->right!=NULL)
            q.push(pNode->right);
    }
    return;
}

5

#include <iostream>
#include <stdio.h> 
#include <stdlib.h>

using namespace std;

 定义树 //
struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
};     //要记得写 ;

/ 镜像 ///
void Mirror(TreeNode *pRoot) {
    if(pRoot==NULL)
        return;
    if((pRoot->left==NULL)&&(pRoot->right==NULL))
        return;
        
    TreeNode *tmp;
    tmp=pRoot->left;
    pRoot->left=pRoot->right;
    pRoot->right=tmp;
        
    Mirror(pRoot->left);
    Mirror(pRoot->right);
}
// 对称 //
bool isSymmetrical(TreeNode* pRoot)
{
        return isSymmetrical(pRoot,pRoot);
}
bool isSymmetrical(TreeNode* pRoot1,TreeNode* pRoot2)
{
        if(pRoot1==nullptr&&pRoot2==nullptr)
            return true;
        if(pRoot1==nullptr||pRoot2==nullptr)
            return false;
        if(pRoot1->val!=pRoot2->val)
            return false;
        return isSymmetrical(pRoot1->left,pRoot2->right)&& isSymmetrical(pRoot1->right,pRoot2->left);
}


6

首先自定义结构,根据考题写相应的子模块

#include <iostream>
#include <stdio.h> 
#include <stdlib.h>
#include <queue>
using namespace std;

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
};     //要记得写 ;

bool isSameTree(TreeNode *p, TreeNode *q) {
    if (p == NULL || q == NULL) return (p == q);
    return (p->val == q->val && isSameTree(p->left, q->left) && isSameTree(p->right, q->right));
}

bool isSubtree(TreeNode* s, TreeNode* t) {  // t是s的子树?
    if(!s) return false;
    if (isSame(s,t)) return true;
    return isSubtree(s->left,t) || isSubtree(s->right,t);
}

bool dfs(TreeNode * r1, TreeNode * r2){
    if(!r2) return true;       // r2 小树遍历完就结束
    if(!r1) return false;
    return ((r1->val == r2->val)&&dfs(r1->left, r2->left) && dfs(r1->right, r2->right));
}
bool isSubstruct(TreeNode* s, TreeNode* t){ // t是s的子结构?
    if(!s) return false;
    if(!t) return false;
    return ( dfs(s,t)) || isSubstruct(s->left, t) || isSubstruct(s->right, t);
}


7

#include <iostream>
#include <stdio.h> 
#include <stdlib.h>

using namespace std;

 定义树 //
struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
};     //要记得写 ;

void Convert(TreeNode * pRoot,TreeNode * & pFirstNode, TreeNode * & pLastNode)  
{  
    TreeNode *pFirstLeft, *pLastLeft, * pFirstRight, *pLastRight;  
    if(pRoot == NULL)   
    {  
        pFirstNode = NULL;  
        pLastNode = NULL;  
        return;  
    }  
  
    if(pRoot->left == NULL)  
    {  
        // 如果左子树为空,对应双向有序链表的第一个节点是根节点  
        pFirstNode = pRoot;  
    }  
    else  
    {  
        Convert(pRoot->left, pFirstLeft, pLastLeft);  
        // 二叉查找树对应双向有序链表的第一个节点就是左子树转换后双向有序链表的第一个节点  
        pFirstNode = pFirstLeft;  
        // 将根节点和左子树转换后的双向有序链表的最后一个节点连接  
        pRoot->left = pLastLeft;  
        pLastLeft->right = pRoot;  
    }  
  
    if(pRoot->right == NULL)  
    {  
        // 对应双向有序链表的最后一个节点是根节点  
        pLastNode = pRoot;  
    }  
    else  
    {  
        Convert(pRoot->right, pFirstRight, pLastRight);  
        // 对应双向有序链表的最后一个节点就是右子树转换后双向有序链表的最后一个节点  
        pLastNode = pLastRight;  
        // 将根节点和右子树转换后的双向有序链表的第一个节点连接  
        pRoot->right = pFirstRight;  
        pFirstRight->left = pRoot;  
    }  
  
    return;  
}  
};

8

递归解法:
(1)如果两个节点分别在根节点的左子树和右子树,则返回根节点
(2)如果两个节点都在左子树,则递归处理左子树;如果两个节点都在右子树,则递归处理右子树

bool FindNode(TreeNode * pRoot, TreeNode * pNode)
{
	if(pRoot == NULL || pNode == NULL)
		return false;

	if(pRoot == pNode)
		return true;

	bool found = FindNode(pRoot->left, pNode);
	if(!found)
		found = FindNode(pRoot->right, pNode);

	return found;
}

BinaryTreeNode * GetLastCommonParent(TreeNode * pRoot, 
                                     TreeNode * pNode1, 
                                     TreeNode * pNode2)
{
	if(FindNode(pRoot->left, pNode1))
	{
		if(FindNode(pRoot->right, pNode2))
			return pRoot;
		else
			return GetLastCommonParent(pRoot->left, pNode1, pNode2);
	}
	else
	{
		if(FindNode(pRoot->left, pNode2))
			return pRoot;
		else
			return GetLastCommonParent(pRoot->right, pNode1, pNode2);
	}
}
9

递归解法:
(1)如果二叉树为空,返回0,同时记录左子树和右子树的深度,都为0
(2)如果二叉树不为空,最大距离要么是左子树中的最大距离,要么是右子树中的最大距离,要么是左子树节点中到根节点的最大距离+右子树节点中到根节点的最大距离,同时记录左子树和右子树节点中到根节点的最大距离。

int GetMaxDistance(TreeNode * pRoot, int & maxLeft, int & maxRight)  
{  
    // maxLeft, 左子树中的节点距离根节点的最远距离  
    // maxRight, 右子树中的节点距离根节点的最远距离  
    if(pRoot == NULL)  
    {  
        maxLeft = 0;  
        maxRight = 0;  
        return 0;  
    }  
    int maxLL, maxLR, maxRL, maxRR;  
    int maxDistLeft, maxDistRight;  
    if(pRoot->m_pLeft != NULL)  
    {  
        maxDistLeft = GetMaxDistance(pRoot->m_pLeft, maxLL, maxLR);  
        maxLeft = max(maxLL, maxLR) + 1;  
    }  
    else  
    {  
        maxDistLeft = 0;  
        maxLeft = 0;  
    }  
    if(pRoot->m_pRight != NULL)  
    {  
        maxDistRight = GetMaxDistance(pRoot->m_pRight, maxRL, maxRR);  
        maxRight = max(maxRL, maxRR) + 1;  
    }  
    else  
    {  
        maxDistRight = 0;  
        maxRight = 0;  
    }  
    return max(max(maxDistLeft, maxDistRight), maxLeft+maxRight);  
}  
//测试用例
#include <stdlib.h>
#include <stdio.h>

typedef struct Node {
    struct Node *pleft;     //左孩子
    struct Node *pright;    //右孩子
    char chValue;           //该节点的值

    int leftMaxValue;       //左子树最长距离
    int rightMaxValue;      //右子树最长距离
}LNode, *BinTree;

void findMaxLen(BinTree root, int *maxLen) {
    //遍历到叶子结点,返回
    if(root == NULL)
        return;

    //如果左子树为空,那么该节点左边最长距离为0
    if(root->pleft == NULL)
        root->leftMaxValue = 0;

    //如果右子树为空,那么该节点右边最长距离为0
    if(root->pright == NULL)
        root->rightMaxValue = 0;

    //如果左子树不为空,递归寻找左子树最长距离
    if(root->pleft != NULL)
        findMaxLen(root->pleft, maxLen);

    //如果右子树不为空,递归寻找右子树最长距离
    if(root->pright != NULL)
        findMaxLen(root->pright, maxLen);

    //计算左子树中距离根节点的最长距离
    if(root->pleft != NULL) {
        if(root->pleft->leftMaxValue > root->pleft->rightMaxValue)
            root->leftMaxValue = root->pleft->leftMaxValue + 1;
        else
            root->leftMaxValue = root->pleft->rightMaxValue + 1;
    }

    //计算右子树中距离根节点的最长距离
    if(root->pright != NULL) {
        if(root->pright->leftMaxValue > root->pright->rightMaxValue)
            root->rightMaxValue = root->pright->leftMaxValue + 1;
        else
            root->rightMaxValue = root->pright->rightMaxValue + 1;
    }

    //更新最长距离
    if(root->leftMaxValue + root->rightMaxValue > *maxLen)
        *maxLen = root->leftMaxValue + root->rightMaxValue;
}

//创建二叉树
void buildBinTree(BinTree *root)
{
    char ch;
    scanf("%c", &ch);    //输入一个元素
    fpurge(stdin);
    if(ch == ' ')        //若输入的是空格符,表明二叉树为空,置*root为NULL
        *root = NULL;
    else {               //若输入的不是空格符,则将该值赋值给根节点的chValue, 递归建立左子树和右子树
        *root = (BinTree)malloc(sizeof(LNode));
        (*root)->chValue = ch;
        (*root)->leftMaxValue = 0;
        (*root)->rightMaxValue = 0;

        buildBinTree(&(*root)->pleft);
        buildBinTree(&(*root)->pright);
    }
}

//销毁二叉树,释放内存
void destroyBinTree(BinTree *root)
{
    if(*root != NULL) {
        destroyBinTree(&(*root)->pleft);
        destroyBinTree(&(*root)->pright);

        free(*root);
        *root = NULL;
    }
}

//前序遍历二叉树
void preOrderTraverse(BinTree root)
{
    if(root != NULL) {
        preOrderTraverse(root->pleft);
        printf("%c", root->chValue);
        preOrderTraverse(root->pright);
    }
}

int main() {
    BinTree root;
    buildBinTree(&root);
    preOrderTraverse(root);
    printf("\n");
    int maxLen = 0;
    findMaxLen(root, &maxLen);
    printf("maxLen = %d\n", maxLen);
    destroyBinTree(&root);
}

10

 struct TreeNode {
     int val;
     TreeNode *left;
     TreeNode *right;
  };


 TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        TreeNode* root=reConstructBinaryTree(pre,0,pre.size()-1,vin,0,vin.size()-1);
        return root;
    }

 TreeNode* reConstructBinaryTree(vector<int> pre,int startPre,int endPre,vector<int> vin,int startIn,int endIn) {
        if(startPre>endPre||startIn>endIn)
            return NULL;
        TreeNode* root=new TreeNode(pre[startPre]);
         
        for(int i=startIn;i<=endIn;i++)
            if(vin[i]==pre[startPre]){
                root->left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,vin,startIn,i-1);
                //更新左子树的前序[startPre+1,startPre+i-startIn],l_len=i-startIn;中序[startIn,i-1];
                root->right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,vin,i+1,endIn);
                //更新右子树的前序[startPre+i-startIn+1,endPre];中序[i+1,endIn];
                //更新前序的首末要找准
                      break;
            }
                 
        return root;
    }
         

11

    vector<vector<int> > Print(TreeNode* pRoot) {

        // 存储结果
        vector<vector<int> > results;
        vector<int> rlt_temp;

        // 边界条件
        if(pRoot == nullptr)
            return results;

        // 辅助容器
        stack<TreeNode*> stk[2]; // stk[0]是奇数层,stk[1]是偶数层
        int now = 0;
        int next = 1;
        TreeNode* temp=pRoot;

        // 根节点入栈
        stk[now].push(temp);

        // 遍历两个栈,当两个栈均为空时,跳出循环
        while(!stk[now].empty() || !stk[next].empty()){
            // 存储遍历结果
            temp = stk[now].top();
            rlt_temp.push_back(temp->val);
            stk[now].pop();

            // 当前层是奇数或偶数
            if(now==0)
            {
                // 当前层是奇数时,左子树先入栈,右子树后入栈
                if(temp->left!=nullptr)
                    stk[next].push(temp->left);
                if(temp->right!=nullptr)
                    stk[next].push(temp->right);
            }
            else
            {
                // 当前层是偶数时,右子树先入栈,左子树后入栈
                if(temp->right!=nullptr)
                    stk[next].push(temp->right);
                if(temp->left!=nullptr)
                    stk[next].push(temp->left);
            }

            // 当前层为空时,打印下一层
            if(stk[now].empty())
            {
                results.push_back(rlt_temp);
                rlt_temp.clear();
                now=1-now;
                next = 1-next;
            }
        }
        return results;
    }





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: DS二叉树,也称赫夫曼树,是一种用于数据压缩的树形结构。它的构建过程是将一组权值作为叶子节点,通过不断合并权值最小的两个节点,最终形成一棵树,使得每个叶子节点到根节点的路径上的权值之和最小。 赫夫曼树的编码过程是将每个叶子节点的权值编码为一串二进制数,使得编码后的长度最短,从而实现数据压缩的目的。 以下是赫夫曼树的构建与编码的代码框架: ```python class Node: def __init__(self, value, weight): self.value = value self.weight = weight self.left = None self.right = None def build_huffman_tree(data): # 构建赫夫曼树 nodes = [Node(value, weight) for value, weight in data] while len(nodes) > 1: nodes.sort(key=lambda x: x.weight) left = nodes.pop(0) right = nodes.pop(0) parent = Node(None, left.weight + right.weight) parent.left = left parent.right = right nodes.append(parent) return nodes[0] def encode_huffman_tree(root): # 编码赫夫曼树 codes = {} def dfs(node, code): if node is None: return if node.value is not None: codes[node.value] = code return dfs(node.left, code + '0') dfs(node.right, code + '1') dfs(root, '') return codes # 示例 data = [('a', 5), ('b', 9), ('c', 12), ('d', 13), ('e', 16), ('f', 45)] root = build_huffman_tree(data) codes = encode_huffman_tree(root) print(codes) # 输出:{'a': '1100', 'b': '1101', 'c': '100', 'd': '101', 'e': '111', 'f': '0'} ``` 以上代码中,`Node` 类表示赫夫曼树的节点,包含值、权值、左子节点和右子节点四个属性。`build_huffman_tree` 函数接受一个列表 `data`,其中每个元素是一个二元组,表示一个叶子节点的值和权值。该函数返回构建好的赫夫曼树的根节点。 `encode_huffman_tree` 函数接受赫夫曼树的根节点,返回一个字典,表示每个叶子节点的编码。该函数使用深度优先搜索遍历赫夫曼树,对于每个叶子节点,记录其值和编码。 在示例中,我们使用了一个包含 6 个叶子节点的数据集,构建了一棵赫夫曼树,并对每个叶子节点进行了编码。最终输出了每个叶子节点的编码结果。 ### 回答2: 1. DS二叉树简介 DS二叉树是一种常见的数据结构,也是二叉树数据结构的一种变种。其特点是每个节点只有两个分支,即左子节点和右子节点。DS二叉树在计算机科学中有着重要的应用,例如在文件压缩、加密等领域中,常用DS二叉树来构建赫夫曼树,实现数据的压缩和加密。 2. 赫夫曼树简介 赫夫曼树(Huffman Tree)是一种用于数据压缩和加密的方法。它是一棵带权路径最短的树,即树中所有叶子节点到根节点的路径长度乘以该叶子节点的权值之和最小。赫夫曼树的构建可以通过DS二叉树来实现,是DS二叉树的一种典型应用。 3. 赫夫曼树的构建与编码 赫夫曼树的构建通过以下步骤实现: 1)将所有的数据项按照权值大小从小到大排序; 2)选取权值最小的两个节点作为新的父节点,将这两个节点从序列中删除,再将新的父节点添加到序列中; 3)重复执行第2步,直到序列中只剩下一个节点,即构建出了一棵赫夫曼树。 在构建赫夫曼树的过程中,可以通过DS二叉树来表示和存储树节点。具体来说,可以定义一个叫做HuffmanNode的结构体,用来存储树节点的权值、左右子节点和父节点等信息。同时,可以定义一个HuffmanTree类,用来实现赫夫曼树的构建和编码。 HuffmanNode结构体定义如下: ``` struct HuffmanNode { int weight; // 权值 HuffmanNode* parent; // 父节点 HuffmanNode* left; // 左子节点 HuffmanNode* right; // 右子节点 }; ``` HuffmanTree类的成员函数包括: 1)createTree:用来构建赫夫曼树; 2)encode:用来对数据进行编码。 createTree函数的实现如下: ``` void HuffmanTree::createTree() { // 将所有数据项节点插入到序列中 for (int i = 0; i < data.size(); i++) { HuffmanNode* node = new HuffmanNode; node->weight = data[i].weight; node->parent = nullptr; node->left = nullptr; node->right = nullptr; nodes.push(node); } // 不断从序列中选取权值最小的两个节点,构建一颗新的赫夫曼树 while (nodes.size() > 1) { HuffmanNode* node1 = nodes.top(); nodes.pop(); HuffmanNode* node2 = nodes.top(); nodes.pop(); HuffmanNode *parent = new HuffmanNode; parent->weight = node1->weight + node2->weight; parent->parent = nullptr; parent->left = node1; parent->right = node2; node1->parent = parent; node2->parent = parent; nodes.push(parent); } // 保存赫夫曼树的根节点 root = nodes.top(); } ``` encode函数的实现如下: ``` string HuffmanTree::encode(const string& s) { // 构建字符到编码的映射表 buildEncodingTable(root, ""); // 对输入的数据进行编码 string result; for (char c : s) { result += encodingTable[c]; } return result; } void HuffmanTree::buildEncodingTable(HuffmanNode* node, string code) { if (node == nullptr) { return; } if (node->left == nullptr && node->right == nullptr) { // 将字符和对应的编码加入到映射表中 encodingTable[node->ch] = code; } buildEncodingTable(node->left, code + "0"); buildEncodingTable(node->right, code + "1"); } ``` 在encode函数中,首先调用buildEncodingTable函数构建字符到编码的映射表,然后对输入的数据进行编码并返回。而buildEncodingTable函数则是通过递归的方式构建映射表的。在编码时,只需要将每个字符对应的编码拼接起来即可。 以上就是DS二叉树--赫夫曼树的构建与编码的基本框架,可以根据需要进行调整和优化。 ### 回答3: ds二叉树,也叫赫夫曼树,是一种特殊的二叉树,用于编码和解码数据。在大数据时代,赫夫曼树被广泛应用于数据压缩,因为它可以用最小的比特位编码代表最频繁的字符,从而大大降低文件大小,加速数据的传输和存储。下面我们来看一下赫夫曼树的构建和编码过程。 赫夫曼树的构建 赫夫曼树的构建需要按照以下步骤: 1.统计每个字符的出现频率,把每个字符看作一个结点,并按照频率从小到大排序。 2.取出两个频率最小的结点作为左右子结点,生成一棵新的树,其权值为左右子结点权值之和。 3.把新的树的权值插入有序队列中。 4.重复步骤2和3,直到队列中只剩下一个树,即为赫夫曼树。 下面是赫夫曼树构建的代码框架: ``` struct Node{ char val; //字符值 int freq; //字符频率 Node *left; //左子结点 Node *right; //右子结点 }; struct cmp { bool operator()(Node *a, Node *b) { return a->freq > b->freq; } }; Node* buildHuffmanTree(string s){ unordered_map<char,int> mp; for(int i=0;i<s.size();i++){ mp[s[i]]++; } priority_queue<Node*, vector<Node*>, cmp> pq; for(const auto &ele:mp){ Node *tmp = new Node; tmp->val = ele.first; tmp->freq = ele.second; tmp->left = nullptr; tmp->right = nullptr; pq.push(tmp); } while(pq.size()>1){ Node *a = pq.top(); pq.pop(); Node *b = pq.top(); pq.pop(); Node *c = new Node; c->freq = a->freq + b->freq; c->left = a; c->right = b; pq.push(c); } return pq.top(); } ``` 赫夫曼编码 在赫夫曼树中,从根节点一直到每个叶子结点的路径构成了该叶子结点字符的编码,左分支为0,右分支为1。赫夫曼的编码方式称为前缀编码,即任何一个字符的编码序列都不是另一个字符代码的前缀,这种编码方式保证了解码的唯一性。因为赫夫曼编码是以树为基础构建的,所以我们可以使用深度优先遍历来得到每个字符的编码。 下面是赫夫曼编码的代码框架: ``` void dfs(Node* root, string path, unordered_map<char,string> &mp) { if(root->left==nullptr && root->right==nullptr){ mp[root->val] = path; return; } if(root->left){ dfs(root->left,path+"0",mp); } if(root->right){ dfs(root->right,path+"1",mp); } } unordered_map<char,string> buildHuffmanCode(Node* root) { unordered_map<char,string> mp; if(root==nullptr){ return mp; } dfs(root,"",mp); return mp; } ``` 总结 赫夫曼树是一种高效的数据压缩方式,在实际应用中广泛应用于图像、音频、视频等大型文件的传输和存储。它的构建和编码过程相对简单,只需要按照一定的规则统计字符频率,然后生成二叉树并得到字符的编码,就可以将文件压缩成更小的大小。希望大家能够掌握赫夫曼树的原理和实现,提高数据处理的效率和精度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值