数据结构实验3

1.    求节点的哈夫曼的带权路径长度
【问题描述】
 已知输入一串正整数,正整数之间用空格键分开,请建立一个哈夫曼树,以输入的数字为叶节点,求这棵哈夫曼树的带权路径长度。

【输入形式】
 首先输入正整数的个数,然后接下来为接下来的正整数,正整数个数不超过10个

【输出形式】
 输出相应的权值

【样例输入】
 5 4 5 6 7 8

【样例输出】
 69

【样例说明】

【评分标准】

参考代码:

#include<iostream>
using namespace std;
typedef  struct HTNode {
	unsigned int weight;
	unsigned int parent, lchild, rchild;
}HTNode, * HuffmanTree;//动态分配数组存储哈夫曼树
void Select(HuffmanTree HT, int n, int& s1, int& s2)
{	//从这m个数里边选择最小的2个//把第一个进行标记就ok 
	int i;//从下标为1的位置开始计数 
	//int min=HT[1].weight;这里直接赋值不合理,假如第一次那个1就是最小被选中,那么第2次还是被选中 
	int min1 = 1000000;
	int min2 = 1000000;//规定一个特别大的数 
	for (i = 1; i <= n; i++)
	{
		if (HT[i].parent == 0 && min1 > HT[i].weight)
		{
			min1 = HT[i].weight;
			s1 = i;
		}
	}
	for (i = 1; i <= n; i++)
	{
		if (i != s1 && HT[i].parent == 0)//注意这个i!=s1标记min,即s1 s2不能是同一个结点,还保证了s1的权重<=s2的权重
			if (HT[i].weight < min2)
			{
				min2 = HT[i].weight;
				s2 = i;
			}
	}
}
int WPLHuffmanTree(HuffmanTree& HT, unsigned int* w, int n) {
	int sum = 0;
	if (n <= 1)
		return 0;
	int m = 2 * n - 1;
	int i;
	HuffmanTree p;
	HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode));
	for (p = HT+1, i = 1; i <= n; ++i, ++p, ++w)//0号单元没用
		*p = { *w,0,0,0 };//等价于p->weight = *w;p->parent = 0;p->lchild = 0;p->rchild = 0;
	for (; i <= m; ++i, ++p)//m-n个非叶子结点(从n+1到m),给权重赋值为空
		*p = { 0,0,0,0 };//等价于p->weight = 0;p->parent = 0;p->lchild = 0;p->rchild = 0;
	for (i = n + 1; i <= m; ++i) {
		//在HT[1...i-1]选择parent为0且weight最小的两个结点,其序号分别为s1和s2
		int s1, s2;
		Select(HT, i - 1, s1, s2);
		HT[s1].parent = i; HT[s2].parent = i;
		HT[i].lchild = s1; HT[i].rchild = s2;//左边小右边大
		HT[i].weight = HT[s1].weight + HT[s2].weight;
		sum += HT[i].weight;
	}
	return sum;
}
int main() {
	int n;
	cin >> n;
	char c = getchar();
	unsigned int* w = new unsigned int[n];
	for (int i = 0; i < n; i++) {
		cin >> w[i];
	}
	HuffmanTree t;
	cout<<WPLHuffmanTree(t, w, n);
}

2.    二叉排序树的构建及其遍历
【问题描述】
 对一组输入数据构建相应的二叉排序树,并利用其中序遍历对数据进行升序排序。(此题人工批改,必须使用二叉树进行排序,其它算法不得分)

【输入形式】
 数据个数,数据。(以空格分割)

【输出形式】
 排序之后的数据。(以空格分割)

【样例输入】
 5 22 -15 4 89 30

【样例输出】
 -15 4 22 30 89

【样例说明】

【评分标准】(此题人工批改,必须使用二叉树进行排序,其它算法不得分)

参考代码:

#include<iostream>
using namespace std;
//数值型
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)<(b))
#define LQ(a,b) ((a)<=(b))
//字符串型
#define SEQ(a,b) (!strcmp((a),(b)))
#define SLT(a,b) (strcmp((a),(b))<0)
#define SLQ(a,b) (strcmp((a),(b))<=0)
typedef int TElemType;
typedef struct BiTNode {
	TElemType data;
	struct BiTNode* lchild,* rchild;
}BiTNode,*BiTree;
void  CreatBiTree(BiTree& T)
{
    T = (BiTNode*)malloc(sizeof(BiTNode));
    if (T == NULL) exit(-1);
    T->rchild = NULL;
    T->lchild = NULL;
}
void InsertBST(BiTree& T,TElemType e)
{
    if (!T) {
        CreatBiTree(T);
        T->data = e;
    }
    else if LT(e, T->data)
        InsertBST(T->lchild,e);//小于往左走
    else
        InsertBST(T->rchild, e);//大于往右走
}
void PrintElement(TElemType e)
   { 
    cout<<e<<" ";
}
void InOrder(BiTree T, void(*Visit)(TElemType)) {//中序遍历
    if (T) {
        InOrder(T->lchild, Visit);
        Visit(T->data);
        InOrder(T->rchild, Visit);
    }
}
int main() {
    int n;
    cin >> n;
    BiTree t=NULL;
    TElemType e;
    for (int i = 0; i < n; i++) {
        cin >> e;
        InsertBST(t, e);
    }
    InOrder(t, PrintElement);
}

3.    从下至上按层遍历二叉树
【问题描述】
 给定一颗二叉树,要求从下至上按层遍历二叉树,每层的访问顺序是从左到右,每一层单独输出一行。

【输入形式】
 广义表表示的二叉树,结点元素类型为整型,且都大于0,例如:1( 2( 3 ( 4, 5 ) ), 6( 7, 8( 9, 10 ) ) )

【输出形式】
 从下至上,打印每一层的结点元素值,元素间以空格隔开。每层的访问顺序是从左到右,每一层单独输出一行。

【样例输入】
 1(2(3(4,5)),6(7,8(9,10))),字符串内没有空格

【样例输出】
 4 5 9 10
 3 7 8
 2 6
 1

【样例说明】

【评分标准】
 本题目主要考察两个知识点:
 1.创建二叉树存储结构
 2.按层次遍历二叉树的算法

参考代码:

#include<iostream>
using namespace std;
#define MAXSIZE 100
#define RESIZE 10
typedef struct BiTNode
{
    int data;
    int depth;
    struct BiTNode* lchild,*rchild;
}BiTNode, * BiTree;
typedef BiTree SElemType;
typedef struct {
    SElemType* base;
    SElemType* top;
    int size;
}Stack;
void InitStack(Stack& s) {
    s.base = (SElemType*)malloc(MAXSIZE * sizeof(SElemType));
    if (!s.base)
        exit(-2);
    s.top = s.base;
    s.size = MAXSIZE;
}
void Push(Stack& s, SElemType e) {
    if (s.top - s.base >= s.size) {
        s.base = (SElemType*)realloc(s.base, (MAXSIZE + RESIZE) * sizeof(SElemType));
        if (!s.base)
            exit(-2);
        s.top = s.base + s.size;
        s.size += MAXSIZE;
    }
    *s.top++ = e;
}
void Pop(Stack& s, SElemType& e) {
    if (s.top == s.base)
        return;
    e = *--s.top;
}
SElemType gettop(Stack s, SElemType& e) {
    if (s.top != s.base)
        e = *(s.top - 1);
    return e;
}
//用栈建立二叉树
void InitBiTree(BiTree* T)
{
    Stack s;
    InitStack(s);
    char a[2*MAXSIZE];
    cin >> a;
    int n= 0;
    int t = 0;
    int e[MAXSIZE];
    int flag = 0;
    int i = 0;
    //由于可能是多位数,所以将字符全部代换成整数形式
    while (a[i] != '\0')
    {
        flag = 0;
        if (a[i] == ',')
        {
            t = 0;
            e[n] = -1;
        }
        else if (a[i] == '(')
        {
            t = 0;
            e[n] = -2;
        }
        else if (a[i] == ')')
        {
            t= 0;
            e[n] = -3;
        }
        else if ((a[i] >= '0') && (a[i] <= '9'))
        {

            while ((a[i] >= '0') && (a[i] <= '9'))//注意多位数
            {
                t = t * 10 + (a[i] - '0');
                flag = 1;
                i = i + 1;
            }
            e[n] = t;
        }
        n = n + 1;
        if (flag == 0)//如果flag为1,则不需要读下一个字符
        {
            i++;
        }
    }
    int flag1 = 0;//flag1为1代表左子树,为2代表右子树
    BiTree Bt = NULL;
    SElemType el;
    for (int j = 0; j < n; j++)
    {
        switch (e[j])
        {
        case -1:
            flag1 = 2;
            Bt = NULL;
            break;
        case -2://左子树压栈
            s.top++;
            flag1 = 1;
            Bt = NULL;
            break;
        case -3://')'出栈
            Pop(s,el);
            Bt = NULL;
            break;
        default://如果都不是,则创建现结点
            Bt = (BiTree)malloc(sizeof(BiTNode));
            Bt->data = e[j];
            Bt->lchild = NULL;
            Bt->rchild = NULL;
        }
        if (flag1 == 1 && Bt)
        {
            (*(s.top - 1))->lchild = Bt;
            *s.top= Bt;
            if (e[j] > 0)//为数字时,深度加1,便于后续从下至上输出
            {
                Bt->depth = (*(s.top - 1))->depth + 1;
            }
        }
        else if (flag1 == 2 && Bt)
        {
            (*(s.top - 1))->rchild = Bt;
            *s.top = Bt;
            if (e[j] > 0)
            {
                Bt->depth = (*(s.top - 1))->depth + 1;
            }
        }
        else if (flag1 == 0)//为根结点时,注意将第一个创建的结点赋给树根结点
        {
            *T = Bt;
            *s.top = Bt;
            Bt->depth = 1;//根节点深度为1
        }
    }
}
typedef BiTree QElemType;
typedef struct SQueue {
    QElemType* base;
    int front;
    int rear;
}SQueue;
void InitQueue(SQueue& q) {
    q.base = (QElemType*)malloc(MAXSIZE * sizeof(QElemType));
    if (!q.base)
        exit(-2);
    q.front = q.rear = 0;
}
void EnQueue(SQueue& q, QElemType e) {//循环队列入队
    if ((q.rear + 1) % MAXSIZE == q.front)//队满
        return;
    q.base[q.rear] = e;
    q.rear = (q.rear + 1) % MAXSIZE;
}
int QueueLength(SQueue& q) {
    return (q.rear - q.front + MAXSIZE) % MAXSIZE;
}
void DeQueue(SQueue& q, QElemType& e) {
    if (q.front == q.rear)//队空
        return;
    e = q.base[q.front];
    q.front = (q.front + 1) % MAXSIZE;
}
bool IsEmpty(SQueue& q) {
    if (q.front == q.rear)
        return true;
    else
        return false;
}
int temp[MAXSIZE][2];//设置二维数组,分别记录结点值和深度
//按层遍历
int LevelOrder(QElemType T)
{   
    SQueue q;
    InitQueue(q);
    BiTree p = (BiTNode*)malloc(sizeof(BiTNode));
    int i = 0;
    if (T)
    {
        EnQueue(q, T);
    }
    while (!IsEmpty(q))//如果非空
    {
        DeQueue(q, p);//出队
        temp[i][0] = p->data;//0为结点值
        temp[i][1] = p->depth;//1为深度
        i = i + 1;
        if (p->rchild)//由于要从下至上输出,所以按层遍历时从右至左遍历
        {
            EnQueue(q, p->rchild);
        }
        if (p->lchild)
        {
            EnQueue(q, p->lchild);
        }
    }
    return i - 1;//返回结点个数下标最大值
}
int main()
{
    BiTree T;
    InitBiTree(&T);
    int level = LevelOrder(T);
    int d = temp[level][1];//最后一个结点的深度为树的深度
    for (; level >= 0; level--)
    {
        if (d != temp[level][1])//如果深度不同,证明应输出上一个深度的结点了
        {
            cout << endl;
            d = d - 1;
        }
        cout<<temp[level][0]<<" ";
    }
    return 0;
}

4.    已知一个二叉树的中序遍历序列和后序遍历序列,求这棵树的前序遍历序列
【问题描述】
 已知一个二叉树的中序遍历序列和后序遍历序列,求这棵树的前序遍历序列。

【输入形式】
 一个树的中序遍历序列 该树后序遍历序列,中间用空格分开。输入序列中仅含有小写字母,且没有重复的字母

【输出形式】
 一个树的前序遍历序列

【样例输入】
 dbeafcg debfgca

【样例输出】
 abdecfg

参考代码:

#include<iostream>
#include<cstdio>
using namespace std;
typedef char TElemType;
typedef struct BiTNode {
    TElemType data;
    struct BiTNode* lchild, * rchild;
}BiTNode, * BiTree;
int Search(string a, char b, int l) {
    for (int i = 0; i < l; i++)
        if (a[i] == b)
            return i;
}
int length(string s) {
    int sum = 0;
    for (int i = 0; s[i] != '\0'; i++)
        sum++;
    return sum;
}
void PrintElement(TElemType e)
{
    cout << e;
}
void PreOrder(BiTree T, void(*Visit)(TElemType)) {//先序遍历
    if (T) {
        Visit(T->data);
        PreOrder(T->lchild, Visit);
        PreOrder(T->rchild, Visit);
    }
}
BiTree Inittree(string s1,string s2)//s1后序遍历序列,s2中序遍历序列
{
    BiTree t = NULL;
    int l=length(s1);
    if (l > 0)
    {
        t = (BiTree)malloc(sizeof(BiTNode));
        t->data = s1[l - 1];//根节点是后序遍历的最后一个
        t->lchild = NULL;
        t->rchild = NULL;
        string s3, s4,s5,s6;
        int i= Search(s2, s1[l - 1], l);//找到根结点在中序遍历中的位置
        s3 = s2.substr(0, i);//在中序序列取出左子树 
        s4 = s2.substr(i + 1, length(s2)- i - 1);//在中序序列取出右子树
        s5 = s1.substr(0, i);// 在后序序列取出左子树
        s6 = s1.substr(i, length(s1) - i - 1);// 在后序序列取出右子树
        t->lchild = Inittree(s5, s3);
        t->rchild = Inittree(s6, s4);
    }
    return t;
}
int main() {
    string s, s0;
    cin >> s0;
    char c = getchar();//存储空格
    cin >> s;
    BiTree t = Inittree(s, s0);
    PreOrder(t, PrintElement);
}

5.    二叉查找树的后序遍历
【问题描述】输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。如果是返回true,否则返回false。
【输入形式】输入任意长度的数组,数字之间空格分开
【输出形式】true 或者 false
【样例输入】输入5 7 6 9 11 10 8
【样例输出】true
【样例说明】由于这一整数序列是如下树的后序遍历结果:

         8
       /  \
      6    10
    / \    / \
   5   7   9  11

因此返回true。

【评分标准】暴力求解法不得分。

参考代码:

#include<iostream>
using namespace std;
//数值型
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)<(b))
#define LQ(a,b) ((a)<=(b))
//字符串型
#define SEQ(a,b) (!strcmp((a),(b)))
#define SLT(a,b) (strcmp((a),(b))<0)
#define SLQ(a,b) (strcmp((a),(b))<=0)
typedef int TElemType;
typedef struct BiTNode {
    TElemType data;
    struct BiTNode* lchild, * rchild;
}BiTNode, * BiTree;
static int i = 0;
TElemType b[100];
void  CreatBiTree(BiTree& T)
{
    T = (BiTNode*)malloc(sizeof(BiTNode));
    if (T == NULL) exit(-1);
    T->rchild = NULL;
    T->lchild = NULL;
}
void InsertBST(BiTree& T, TElemType e)
{
    if (!T) {
        CreatBiTree(T);
        T->data = e;
    }
    else if LT(e, T->data)
        InsertBST(T->lchild, e);//小于往左走
    else
        InsertBST(T->rchild, e);//大于往右走
}
void reserve(TElemType a[],int n) {//二叉排序树后序遍历递归放到数组后是逆序的(单叉是正确的),所以需要逆转数组
    int  i = 0, j = n - 1;
    int t;
    for (; i < n / 2; i++, j--)
    {
        t = b[i];
        b[i] = b[j];
        b[j] = t;
    }
}
void PrintElement(TElemType e)
{
    b[i++] = e;
}
bool IsSingal(BiTree T) {//判断是否为单叉树
    int flag = 1;
    while (T) {
        if (T->lchild && T->rchild) {
            flag = 0;
            break;
        }
        else {
            T = T->lchild ? T->lchild : T->rchild;//哪边不空走哪边
        }
    }
    if (flag == 0)
        return false;
    return true;
}
void compare(TElemType a[], TElemType b[], int n) {
    int flag=1;
    for (int i = 0; i < n; i++) {
        if (a[i] != b[i]) {
            flag = 0;
            cout << "false";
            break;
        }
    }
    if (flag == 1)
        cout << "true" ;
}
void PostOrder(BiTree T, void(*Visit)(TElemType)) {//后序遍历
    if (T) {
        PostOrder(T->lchild,Visit);
        PostOrder(T->rchild,Visit);
        Visit(T->data);
    }
}
int main() {
    int count=0,i=0;
    TElemType a[100];
    BiTree t = NULL;
    TElemType e;
     while(cin >> e){
        a[count++] = e;
        InsertBST(t, e);
    }
    PostOrder(t, PrintElement);
    if (IsSingal(t))//如果为单叉树,则不需要逆转数组
        compare(a, b, count);
    else{
            reserve(b, count);
            compare(a, b, count);
    }
}

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值