仲舟のMOOC第八周编程作业

这次作业打数量战,难度不算太难。

///*题目:二叉树的基本运算
///*作者:仲舟                                       
///*难度:★★★
///*完成时间:2021.05.10
#include <stdio.h>
#include <stdlib.h>
typedef struct node { /*二叉树结构定义*/
    char data;
    struct node *lchild,*rchild;
} binnode;
typedef binnode *bintree;

bintree  CreateBinTree();/*按前序遍历顺序建立一棵二叉树,返回树根地址	*/
void PreOrder(bintree t);    /* t为指向树根结点的指针,树的前序遍历*/
void InOrder(bintree t); /* t为指向树根结点的指针,树的中序遍历*/
void PostOrder(bintree t); /* t为指向树根结点的指针,树的后序遍历*/
bintree PreLast(bintree t); /* t为指向树根结点的指针,返回先序遍历的最后一个结点地址,如果树为空,返回NULL*/
bintree PostFirst(bintree t);/* t为指向树根结点的指针,返回后序遍历的第一个结点地址,如果树为空,返回NULL*/
int main() {
    bintree t,p;
    t=CreateBinTree();   /*建立二叉树t的存储结构*/
    printf("\nthe PreOrder is:");
    PreOrder(t);
    printf("\nthe InOrder is:");
    InOrder(t);
    printf("\nthe PostOrder is:");
    PostOrder(t);
    printf("\nthe PreLast is:");
    p=PreLast(t);
    if (p==NULL) printf("null");
    else printf("%c",p->data);
    printf("\nthe PostFirst is:");
    p=PostFirst(t);
    if (p==NULL) printf("null");
    else printf("%c",p->data);
    return 0;
}

bintree  CreateBinTree() {
    char ch;
    bintree t;
    if ((ch=getchar())=='#')  t=NULL;
    else {
        t=(bintree)malloc(sizeof(binnode));
        t->data=ch;
        t->lchild=CreateBinTree();
        t->rchild=CreateBinTree();
    }
    return t;
}
//你的代码放在这里,注意提交完整源程序

void PreOrder(bintree t) {
    if(t) {
        printf("%c",t->data);
        PreOrder(t->lchild);
        PreOrder(t->rchild);
    }
}

void InOrder(bintree t) {
    if(t) {
        InOrder(t->lchild);
        printf("%c",t->data);
        InOrder(t->rchild);
    }
}

void PostOrder(bintree t) {
    if(t) {
        PostOrder(t->lchild);
        PostOrder(t->rchild);
        printf("%c",t->data);
    }
}

bintree PreLast(bintree t) {
    /*仲舟提示:先序遍历的最后一个往往是树最右下边的一个结点,所以当二叉树有左右两子树的时候,优先找右子树,如果没有右再考虑左子树,如果两孩子都没那就是叶子结点,这个结点就是最右下的结点,也就是先序遍历最后一个,返回结点就行*/
    if(!t)//如果t为空,返回NULL
        return NULL;
    if(t->rchild)//向右下寻找
        t=PreLast(t->rchild);
    else if(t->lchild)//如果没有右,向左下寻找
        t=PreLast(t->lchild);
    else//都没有即叶子结点,说明找到了,返回t
        return t;
}

bintree PostFirst(bintree t) {
    /*仲舟提示:与前一个函数相反,此处不再理解*/
    if(!t)//如果t为空,返回NULL
        return NULL;
    if(t->lchild)
        t=PostFirst(t->lchild);
    else if(t->rchild)
        t=PostFirst(t->rchild);
    else
        return t;
}

在通过遍历转树中,很多同学不知道怎么转,这个方法很难想的到,只要想到了方法就好转,为了便于理解我画了个图。
在这里插入图片描述

///*题目:根据遍历序列构建二叉树,分别实现根据前序和中序序列,中序和后序序列构建二叉树。
///*作者:仲舟                                       
///*难度:★★★★
///*完成时间:2021.05.11
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 100
typedef struct node /*二叉树结构定义*/
{
    char data;
    struct node *lchild,*rchild;
}binnode;
typedef binnode *bintree;

bintree  CreateBinTreebyPreIn(char *pre,char *in,int n);/*由前序序列pre和中序序列in构造二叉树,并返回树根结点指针,如果树为空返回NULL	*/
bintree  CreateBinTreebyPostIn(char *in,char *post,int n);/*由中序序列in和后序序列post构造二叉树,并返回树根结点指针,如果树为空返回NULL	*/
void DispBinTree(bintree t);/* 以括号表示法输出二叉树*/


int main()
{   bintree T;
    char pre[MaxSize],in[MaxSize],post[MaxSize];
    int n;

    scanf("%d",&n);getchar();
    scanf("%s",pre);
    scanf("%s",in);
    scanf("%s",post);
    T=CreateBinTreebyPreIn(pre,in,n);
    printf("\nthe result is:");
    if (T==NULL)
        printf("\nnull");
    else
        DispBinTree(T);
    T=CreateBinTreebyPostIn(in,post,n);
    printf("\nthe result is:");
    if (T==NULL)
        printf("\nnull");
    else
        DispBinTree(T);
    return 0;
}
void DispBinTree(bintree t){
    if (t!=NULL)
    {
        printf("%c",t->data);
        if (t->lchild || t->rchild)
        {
            printf("(");
            DispBinTree(t->lchild);
            if (t->rchild) printf(",");
            DispBinTree(t->rchild);
             printf(")");
        }
    }
}
//你的函数放在这里,提交时请提交完成的程序
bintree  CreateBinTreebyPreIn(char *pre,char *in,int n)
{
    /*仲舟提示:有两种遍历,那么就可以以其中一个遍历为头结点,另一个遍历就可以判断子树的位置
    为了方便,我们以前序遍历顺序建头结点,以中序遍历判断子树位置,原理如上图所示*/
    if(n==0)//长度为0,也就是之后没了
        return NULL;
    bintree head;//该子树的头节点
    head=(bintree)malloc(sizeof(binnode));
    head->data=pre[0];//先序遍历第一个必是头节点
    int k=0;//头节点在中序遍历的下标
    for(;pre[0]!=in[k];k++);//在中序遍历找到第k个位置和头节点一样,将这个位置的前序和中序分为左子树和右子树
    head->lchild=CreateBinTreebyPreIn(pre+1,in,k);//连接左子树的头节点(左子树:前序的第一个用完了,从第二个开始,pre+1,中序遍历依然是从最左边in开始,但是in的长度是k的左边部分长度)
    head->rchild=CreateBinTreebyPreIn(pre+1+k,in+1+k,n-k-1);//连接右子树的头节点(右子树:中序遍历是从A的左边开始,in的长度是k的右边部分长度,前序恰巧也是下标为k的的右边部分开始)
    return head;
}

bintree  CreateBinTreebyPostIn(char *in,char *post,int n)
{
    /*原理同上,不做解释*/
    if(n==0)
        return NULL;
    bintree head;
    head=(bintree)malloc(sizeof(binnode));
    head->data=post[n-1];
    int k=0;
    for(;post[n-1]!=in[k];k++);
    head->lchild=CreateBinTreebyPostIn(in,post,k);
    head->rchild=CreateBinTreebyPostIn(in+1+k,post+k,n-k-1);
    return head;
}

下面一题巨脑残

///*题目:按照先序遍历的顺序输出给定二叉树的叶结点
///*作者:仲舟                                       
///*难度:NULL
///*完成时间:2021.05.11
#include <stdio.h>
#include <stdlib.h>
typedef struct node { /*二叉树结构定义*/
    char data;
    struct node *lchild,*rchild;
} binnode;
typedef binnode *bintree;

bintree  CreateBinTree();/*按前序遍历顺序建立一棵二叉树,返回树根地址	*/
void PreorderPrintLeaves(bintree t);    /* 按照先序遍历的顺序输出给定二叉树t的叶结点,格式为一个空格跟着一个字符。*/

int main() {
    bintree t;
    t=CreateBinTree();   /*建立二叉树t的存储结构*/
    printf("\nthe PreOrder Leaf nodes are:");
    PreorderPrintLeaves(t);
    return 0;
}

bintree  CreateBinTree() {
    char ch;
    bintree t;
    if ((ch=getchar())=='#')  t=NULL;
    else {
        t=(bintree)malloc(sizeof(binnode));
        t->data=ch;
        t->lchild=CreateBinTree();
        t->rchild=CreateBinTree();
    }
    return t;
}

void PreorderPrintLeaves(bintree t) {
    if(t) {
        if(!t->lchild&&!t->rchild)
            printf(" %c",t->data);
        PreorderPrintLeaves(t->lchild);
        PreorderPrintLeaves(t->rchild);
    }
}

这一题有点阴间,读不懂题目,压根看不懂他想干什么,他就是把子结点的权重列出来,然后找两个最小值合并再放进去,返回两个最小值,上面解释的什么up,father根本没有这个东西,不知道出题人在哪抄的题目。

///*题目:哈夫曼树的建立,请完成select函数的编写列构建二叉树。
///*作者:仲舟                                       
///*难度:★★★
///*完成时间:2021.05.11
#include <stdio.h>
#include <stdlib.h>

typedef struct hnode {
    int weight;
    int lchild;
    int rchild;
    int parent;
} huffNode;
void select(huffNode huffmanTree[ ], int k, int *s1, int *s2);
//从huffmanTree数组的0到up-1中找出father为-1的且权重最小的结点赋给s1,s2,(为了保证答案唯一,请让s1的结点编号小于s2)
void CreateHuffTree(huffNode huffmanTree[ ], int W[ ], int N );
//创建哈夫曼树,W为权重数组,N为叶子结点个数

int main() {

    huffNode *ht;

    int i,N,*W;
    scanf("%d", &N);

    W = (int *) malloc (N * sizeof(int));
    ht=(huffNode *)malloc((2*N-1)*sizeof(huffNode));

    for(i = 0; i < N; i++)
        scanf("%d", &W[i]);

    CreateHuffTree(ht,W,N);

    for (i = 0; i < 2 * N - 1; i++) {
        printf("%d   %d   %d   %d   %d\n",i,ht[i].weight, ht[i].parent, ht[i].lchild, ht[i].rchild);
    }

    free(W);
    free(ht);
    return 0;
}

void CreateHuffTree(huffNode huffmanTree[ ], int W[ ], int N ) {
    int i,i1,i2,k;
    for (i = 0; i < N; i++) {   //叶子结点初始化
        huffmanTree[i].parent = -1;
        huffmanTree[i].lchild = -1;
        huffmanTree[i].rchild = -1;
        huffmanTree[i].weight = W[i];
    }
    for (k = N; k < 2*N-1; k++) {
        select(huffmanTree,k, &i1, &i2);
        huffmanTree[k].weight = huffmanTree[i1].weight+huffmanTree[i2].weight;
        huffmanTree[k].lchild = i1;
        huffmanTree[k].rchild = i2;
        huffmanTree[k].parent=-1;
        huffmanTree[i1].parent = k;
        huffmanTree[i2].parent = k;

    }
}

void select(huffNode huffmanTree[ ], int k, int *s1, int *s2) {
    /*仲舟提示:此算法说明白就是找huffmanTree[].weight(权值)最小的两树的下标返回,
    但是要注意一点:每次合并了以后数组的值要改变,要删除数组的最小两个并且在数组后新
    建一个位置放他们两个的和,而函数外部还需要调用.weight这个值,如果不能删除,那么
    每次都要查找这个值是否以前合并过(合并过的就不能再合并了),可以通过找他是否有父
    母来判断是否合并过*/
    int min=100000;//设置一个大数
    /*找第一小的数*/
    for(int i=0; i<=k-1; i++)//只有下标为k的建立了结点,所以遍历[0,k-1]
        if(huffmanTree[i].parent==-1&&huffmanTree[i].weight<min) { //如果这个结点没妈,并且小于最小的,那就是当前最小的数
            min=huffmanTree[i].weight;//最小值等于哈夫曼权重;
            *s1=i;//下标传递
        }
    min=100000;//大数重置
    /*找第二小的数*/
    for(int i=0; i<=k-1; i++)
        if(huffmanTree[i].parent==-1&&huffmanTree[i].weight<min&&i!=*s1) { //如果这个结点没妈,并且小于最小的,并且不是s1下标,那就是第二小的数
            min=huffmanTree[i].weight;//最小值等于哈夫曼权重;
            *s2=i;//下标传递
        }
}

这题用递归就行,亲测有效。

///*题目:将一棵给定二叉树中所有结点的左、右子女互换。
///*作者:仲舟                                       
///*难度:★★
///*完成时间:2021.05.11
#include <stdio.h>
#include <stdlib.h>
typedef struct node { /*二叉树结构定义*/
    char data;
    struct node *lchild,*rchild;
} binnode;
typedef binnode *bintree;

bintree  CreateBinTree();/*按前序遍历顺序建立一棵二叉树,返回树根地址	*/
void Change(bintree t);    /* 将一棵给定二叉树中所有结点的左、右子女互换。*/
void DispBinTree(bintree t);/* 以括号表示法输出二叉树*/

int main() {
    bintree t,p;
    t=CreateBinTree();   /*建立二叉树t的存储结构*/
    DispBinTree(t);
    printf("\n");
    Change(t);
    DispBinTree(t);
    return 0;
}

bintree  CreateBinTree() {
    char ch;
    bintree t;
    if ((ch=getchar())=='#')  t=NULL;
    else {
        t=(bintree)malloc(sizeof(binnode));
        t->data=ch;
        t->lchild=CreateBinTree();
        t->rchild=CreateBinTree();
    }
    return t;
}

void DispBinTree(bintree t) {
    if (t!=NULL) {
        printf("%c",t->data);
        if (t->lchild || t->rchild) {
            printf("(");
            DispBinTree(t->lchild);
            if (t->rchild) printf(",");
            DispBinTree(t->rchild);
            printf(")");
        }
    }
}
//你的函数写在这里,注意提交完整代码

void Change(bintree t) {
    /*仲舟提示:由于结点通过指针连接,只要我们把一个结点指向左孩子变成指向右孩子,右孩子指向左孩子就欧了*/
    if(t) { //如果t存在,开始循环
        bintree temp;//新建中间指针
        /*两孩子指针交换*/
        temp=t->lchild;
        t->lchild=t->rchild;
        t->rchild=temp;
        Change(t->lchild);//处理左孩子
        Change(t->rchild);//处理右孩子(注:这两个函数之间或者与交换整个部分互换位置都没问题)*/
    }
}

仲舟原创,未经允许禁止转载!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值