实验三

给定广义表表示的情况下实现二叉树的生成

#include <bits/stdc++.h>
#define MAXSIZE 200

using namespace std;

typedef char DataType;
typedef struct BiTnode { //结构
	DataType data;
	struct BiTnode *lchild, *rchild;
}*BiTree, BitNode;

int CreateBiTree(BiTree *T, DataType *str);//生成二叉树

void PreOrderTraverse(BiTree T); //先序遍历

int BTNodeDepth(BiTree b);  //求二叉树b的深度

int Nodes(BiTree T); //叶子结点的个数

int TreeWidth(BiTree T);//树的宽度


int main() { //主函数
	int n, len = 0;
	char ch, str[MAXSIZE];
	BiTree T;
	cout << "请输入广义表,以‘@’结束:" << endl;

	while ((ch = getchar()) != '\n') {
		str[len++] = ch;
	}

	n = CreateBiTree(&T, str);
	if (n == 1) {
		cout << "创建成功!" << endl;
	} else {
		cout << "创建失败!" << endl;
	}

	puts("先序遍历:");
	PreOrderTraverse(T);
	puts("");
	puts("树的深度:");
	cout << BTNodeDepth(T) << endl;
	puts("树的叶子节点数:");
	cout << Nodes(T) << endl;
	puts("树的宽度:");
	cout << TreeWidth(T) << endl;

	return 0;
}

int CreateBiTree(BiTree *T, DataType *str) {
	BiTree S[MAXSIZE], p = NULL;
	int top = 0, k = 0, j = 0;
	char ch;
	*T = NULL;
	ch = str[j];
	while (ch != '@') {
		switch (ch) {
			case '(':
				S[top++] = p;
				k = 1;
				break;
			case ')':
				top--;
				break;
			case ',':
				k = 2;
				break;

			default:
				p = (BiTree)malloc(sizeof(BitNode));
				p->data = ch;
				p->lchild = p->rchild = NULL;
				if (*T == NULL) {
					*T = p;
				} else {
					switch (k) {
						case 1:
							S[top - 1]->lchild = p;
							break;
						case 2:
							S[top - 1]->rchild = p;
							break;
					}
				}
				break;
		}
		ch = str[++j];
	}

	return 1;
}

void PreOrderTraverse(BiTree T) { //先序遍历
	if (T == NULL) return ; //空二叉树
	else {
		printf("%c", T->data); //访问根结点
		PreOrderTraverse(T->lchild); //递归遍历左子树
		PreOrderTraverse(T->rchild); //递归遍历右子树
	}
}

int BTNodeDepth(BiTree T) { //求二叉树b的深度
	int lchilddep, rchilddep;
	if (T == NULL)
		return 0;                          //空树的高度为0
	else {
		lchilddep = BTNodeDepth(T->lchild); //求左子树的高度为lchilddep
		rchilddep = BTNodeDepth(T->rchild); //求右子树的高度为rchilddep
		return (lchilddep > rchilddep) ? (lchilddep + 1) : (rchilddep + 1);
	}
}

int Nodes(BiTree T) {  //叶子结点的个数
	int num1, num2;
	if (T == NULL)
		return 0;
	else if (T->lchild == NULL && T->rchild == NULL)
		return 1;
	else {
		num1 = Nodes(T->lchild);
		num2 = Nodes(T->rchild);
		return (num1 + num2);
	}
}

int TreeWidth(BiTree T) { //树的宽度
	if (!T) return 0;
	queue<BiTree> myQueue;
	myQueue.push(T);		// 将根结点入队列
	int nWidth = 1;				// 二叉树的宽度
	int nCurLevelWidth = 1;		// 记录当前层的宽度
	BiTree pCur = NULL;

	while (!myQueue.empty()) {// 队列不为空
		while (nCurLevelWidth != 0) {
			pCur = myQueue.front();	// 取出队首元素
			myQueue.pop();			// 队首元素出队列
			if (pCur->lchild != NULL) myQueue.push(pCur->lchild);
			if (pCur->rchild != NULL) myQueue.push(pCur->rchild);
			nCurLevelWidth--;
		}
		nCurLevelWidth = myQueue.size();
		nWidth = nCurLevelWidth > nWidth ? nCurLevelWidth : nWidth;
	}
	return nWidth;
}

哈夫曼树

#include <bits/stdc++.h>

using namespace std;
const int N = 200;
const int MX = 0x3f3f3f3f;

typedef struct {
	int weight;
	int parent, lch, rch;
} HTNode, *HuffmanTree;

void Select(HuffmanTree HT, int n, int &s1, int &s2); //在HT[k](1≤k≤i-1)中选择两个其双亲域为0,且权值最小的结点,并返回它们在HT中的序号s1和s2

void CreatHuffmanTree (HuffmanTree &HT, int n); //建树

void CreatHuffmanCode(HuffmanTree HT, char *HC[], int n); //找其序列


int main() {

	HuffmanTree ht;
	int n;
	cout << "input n: ";
	cin >> n;
	CreatHuffmanTree(ht, n);
	char *hc[n + 1];
	CreatHuffmanCode(ht, hc, n);
	for (int i = 1; i <= n; i ++ ) {
		cout << i << " : hfm: " << hc[i] << '\n';
	}

	return 0;
}

void Select(HuffmanTree HT, int n, int &s1, int &s2) {
	int mx = MX;
	for (int i = 1; i <= n; i ++ ) {
		if (!HT[i].parent && HT[i].weight < mx) {
			mx = HT[i].weight;
			s1 = i;
		}
	}

	mx = MX;
	for (int i = 1; i <= n; i ++ ) {
		if (i != s1 && !HT[i].parent && HT[i].weight < mx) {
			mx = HT[i].weight;
			s2 = i;
		}
	}
}

void CreatHuffmanTree (HuffmanTree &HT, int n) {
	if (n <= 1)return;
	int m = 2 * n - 1;
	HT = new HTNode[m + 1]; //0号单元未用,HT[m]表示根结点
	for (int i = 1; i <= m; ++i) {
		HT[i].lch = 0;
		HT[i].rch = 0;
		HT[i].parent = 0;
	}
	for (int i = 1; i <= n; ++i) {
		cout << "input " << i << " valuse : ";
		cin >> HT[i].weight;
	}
	for (int i = n + 1; i <= m; ++i) {
		int s1, s2;
		Select(HT, i - 1, s1, s2);
		HT[i].lch = s1;
		HT[i].rch = s2 ; //s1,s2分别作为i的左右孩子
		HT[s1].parent = i;
		HT[s2] .parent = i;
		HT[i].weight = HT[s1].weight + HT[s2] .weight;
		//i 的权值为左右孩子权值之和
	}
}

void CreatHuffmanCode(HuffmanTree HT, char *HC[], int n) {
//从叶子到根逆向求每个字符的赫夫曼编码,存储在编码表HC中分配n个字符编码的头指针矢量
	char *cd = new char[n]; 	//分配临时存放编码的动态数组空间
	cd[n - 1] = '\0'; 	//编码结束符
	for (int i = 1; i <= n; ++i) {	//逐个字符求赫夫曼编码
		int start = n - 1;
		int c = i;
		int f = HT[i].parent;
		while (f != 0) {	//从叶子结点开始向上回溯,直到根结点
			--start;                          			//回溯一次start向前指一个位置
			if (HT[f].lch == c)  cd[start] = '0';	//结点c是f的左孩子,则生成代码0
			else cd[start] = '1';               		//结点c是f的右孩子,则生成代码1
			c = f;
			f = HT[f].parent;             		//继续向上回溯
		}                                  		//求出第i个字符的编码
		HC[i] = new char [n - start];       	// 为第i 个字符编码分配空间
		strcpy(HC[i], &cd[start]); //将求得的编码从临时空间cd复制到HC的当前行中
	}
	delete cd;                            	//释放临时空间
}

 

posted @ 2022-12-05 21:35  Luli&  阅读(25)  评论(0)    收藏  举报