这次作业打数量战,难度不算太难。
///*题目:二叉树的基本运算
///*作者:仲舟
///*难度:★★★
///*完成时间: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);//处理右孩子(注:这两个函数之间或者与交换整个部分互换位置都没问题)*/
}
}
仲舟原创,未经允许禁止转载!