構建哈夫曼樹和權值計算


前言:哈夫曼樹(最優二叉樹)的筆記

到這里樹的基本相關的數據結構都擼了一遍,接下來一個星期繼續來擼圖的結構,之前沒有時間,現在有時間都來寫一遍,為什么要寫呢,我自己感覺其實還是跟逆向相關,因為有些東西數據結構會占比多,所以對經典的數據結構的了解,同樣對逆向的水平會有長進!

哈夫曼樹的構建比較簡單,不過我查了相關的資料都是涉及到什么二叉堆的,我沒有學過,按照自己的理解來創建了一棵哈夫曼樹,同樣能實現構建哈夫曼樹和權值的計算

思路:

1、在兩個節點每次創建父節點的時候,都事先先進行排序一次,然后再進行闖將

2、創建完的父節點重新插入到節點數組中,然后一次進行這兩步即可

對於權值的計算,其實主要需要知道路徑的條數(其實也就是樹的高度),並且權值的計算都是針對於葉子節點的,所以我的想法就是遞歸把計算計算出來即可,然后通過標志來區分是否是葉子節點即可進行相關樹的權值

代碼實現如下

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define OK 1
#define ERROR 0
/*
@author zpchcbd
@time 2022.4.07
實現哈夫曼樹
*/
typedef int ElemType;
typedef int Status;
typedef struct _TreeNode{
	struct _TreeNode* pLeftTreeNode;
	struct _TreeNode* pRightTreeNode;
	ElemType weightValue;
	ElemType flag;
	struct _TreeNode* parent;
}TreeNode, *PTreeNode;

// 排序
void sortNodeArray(TreeNode* iArray[], int m)
{
	int i = 0, j = 0;
	TreeNode* tmp = 0;
	for (i = 0;i<m-1;i++)
	{
		for (j = 0; j<m-i-1; j++)
		{
			if (iArray[j]->weightValue < iArray[j+1]->weightValue)
			{
				tmp = iArray[j];
				iArray[j] = iArray[j + 1];
				iArray[j + 1] = tmp;
			}
		}
	}
	
	for (i = 0; i< m; i++)
		printf("%d ", iArray[i]->weightValue);
	printf("\n");
}

// 計算樹中的帶權路徑長度
ElemType getAllWeight(TreeNode* pTreeNode, ElemType iHeight)
{
	int iLength = 0;
	if (pTreeNode!=NULL)
	{
		printf("%d ", pTreeNode->weightValue);
		iLength += getLength(pTreeNode->pLeftTreeNode, iHeight + 1);
		iLength += getLength(pTreeNode->pRightTreeNode, iHeight + 1);
		if (pTreeNode->flag == 1 || pTreeNode->flag == 0)
		{
			iLength += pTreeNode->weightValue*iHeight;
		}
	}
	return iLength;
}

TreeNode* createHuffmanTreeNode(TreeNode* pT1, TreeNode* pT2)
{
	TreeNode* pTreeNode = NULL;
	if (pTreeNode == NULL)
	{
		pTreeNode = malloc(sizeof(TreeNode));
		pTreeNode->pLeftTreeNode = NULL;
		pTreeNode->pRightTreeNode = NULL;
		pTreeNode->weightValue = 0;
		pTreeNode->flag = -1;
		if (pTreeNode == NULL)
			return NULL;
	}
	if (pT1->weightValue < pT2->weightValue)
	{
		pTreeNode->pLeftTreeNode = pT1;
		pTreeNode->pRightTreeNode = pT2;
		if (pT1->flag == 2)
			pT1->flag = 0;
		if (pT2->flag == 2)
			pT2->flag = 1;
	}
	else
	{
		pTreeNode->pRightTreeNode = pT2;
		pTreeNode->pLeftTreeNode = pT1;
		if (pT2->flag == 2)
			pT2->flag = 0;
		if (pT1->flag == 2)
			pT1->flag = 1;
	}
	pT1->parent = pTreeNode;
	pT2->parent = pTreeNode;
	// 新建的節點的value是左節點右節點的value之和
	pTreeNode->weightValue = pT1->weightValue + pT2->weightValue;
	return pTreeNode;
}

int main()
{
	TreeNode* pTreeNode = NULL;
	TreeNode* pTreeNodeArray[7] = { 0 };
	ElemType pNodeValue[5] = { 1,2,3,4,5 };
	int i, j;
	// 初始化完降序排列的棧,該棧中保存的都是TreeNode節點
	for (i = 0;i<5;i++)
	{
		pTreeNodeArray[i] = malloc(sizeof(TreeNode));
		pTreeNodeArray[i]->weightValue = pNodeValue[i];
		pTreeNodeArray[i]->pLeftTreeNode = NULL;
		pTreeNodeArray[i]->pRightTreeNode = NULL;
		pTreeNodeArray[i]->flag = 2;
	}
	
	sortNodeArray(pTreeNodeArray, i);
	for (j = 4; j >= 0; j--)
	{
		pTreeNode = createHuffmanTreeNode(pTreeNodeArray[j], pTreeNodeArray[j - 1]);
		pTreeNodeArray[j] = pTreeNodeArray[j - 1] = NULL;
		pTreeNodeArray[j - 1] = pTreeNode;
		sortNodeArray(pTreeNodeArray, j);
		if (pTreeNodeArray[1] == NULL)
			break;
	}
	printf("=======preOrer=======\n");
	//preOrder(pTreeNodeArray[0]);
	printf("--%d--", getAllWeight(pTreeNodeArray[0], 0));
	return 0;
}

測試數據:ElemType pNodeValue[5] = { 1,2,3,4,5 };


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM