From 6856bf3de88bbfa0cee364a1b9e3d9efee5b747d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=8F=E9=A2=96?= <3471849694@qq.com> Date: Tue, 2 Jan 2024 06:01:08 +0000 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC=E4=B8=83=E7=AB=A0=EF=BC=88=E4=B8=8A?= =?UTF-8?q?=E6=9C=BA=E5=AE=9E=E9=AA=8C=E6=8C=87=E5=AF=BC=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2224020127/chapter_7/abc.txt | 29 +++++ 2224020127/chapter_7/btree.cpp | 97 ++++++++++++++++ 2224020127/chapter_7/exp7-1.cpp | 27 +++++ 2224020127/chapter_7/exp7-10.cpp | 193 +++++++++++++++++++++++++++++++ 2224020127/chapter_7/exp7-5.cpp | 103 +++++++++++++++++ 2224020127/chapter_7/exp7-7.cpp | 144 +++++++++++++++++++++++ 6 files changed, 593 insertions(+) create mode 100644 2224020127/chapter_7/abc.txt create mode 100644 2224020127/chapter_7/btree.cpp create mode 100644 2224020127/chapter_7/exp7-1.cpp create mode 100644 2224020127/chapter_7/exp7-10.cpp create mode 100644 2224020127/chapter_7/exp7-5.cpp create mode 100644 2224020127/chapter_7/exp7-7.cpp diff --git a/2224020127/chapter_7/abc.txt b/2224020127/chapter_7/abc.txt new file mode 100644 index 00000000..fe0493c6 --- /dev/null +++ b/2224020127/chapter_7/abc.txt @@ -0,0 +1,29 @@ +中华大学 计算机学院 +中华大学 电信学院 +计算机学院 计算机科学 +计算机学院 信息安全 +计算机学院 物联网 +计算机科学 计科1班 +计算机科学 计科2班 +计算机科学 计科3班 +计科1班 32 +计科2班 35 +计科3班 33 +信息安全 信安1班 +信息安全 信安2班 +信安1班 36 +信安2班 38 +物联网 物联班 +物联班 38 +电信学院 电子信息类 +电信学院 信息工程 +电子信息类 电信1班 +电子信息类 电信2班 +电子信息类 电信3班 +电信1班 40 +电信2班 38 +电信3班 42 +信息工程 信息1班 +信息工程 信息2班 +信息1班 38 +信息2班 35 \ No newline at end of file diff --git a/2224020127/chapter_7/btree.cpp b/2224020127/chapter_7/btree.cpp new file mode 100644 index 00000000..917835ed --- /dev/null +++ b/2224020127/chapter_7/btree.cpp @@ -0,0 +1,97 @@ +//二叉树的基本运算算法 +#include +#include +#define MaxSize 100 +typedef char ElemType; +typedef struct node +{ + ElemType data; //数据元素 + struct node *lchild; //指向左孩子结点 + struct node *rchild; //指向右孩子结点 +} BTNode; +void CreateBTree(BTNode * &b,char *str) //创建二叉树 +{ + BTNode *St[MaxSize],*p=NULL; + int top=-1,k,j=0; + char ch; + b=NULL; //建立的二叉树初始时为空 + ch=str[j]; + while (ch!='\0') //str未扫描完时循环 + { + switch(ch) + { + case '(':top++;St[top]=p;k=1; break; //为左孩子结点 + case ')':top--;break; + case ',':k=2; break; //为孩子结点右结点 + default:p=(BTNode *)malloc(sizeof(BTNode)); + p->data=ch;p->lchild=p->rchild=NULL; + if (b==NULL) //*p为二叉树的根结点 + b=p; + else //已建立二叉树根结点 + { + switch(k) + { + case 1:St[top]->lchild=p;break; + case 2:St[top]->rchild=p;break; + } + } + } + j++; + ch=str[j]; + } +} +void DestroyBTree(BTNode *&b) //销毁二叉树 +{ if (b!=NULL) + { DestroyBTree(b->lchild); + DestroyBTree(b->rchild); + free(b); + } +} +BTNode *FindNode(BTNode *b,ElemType x) //查找值为x的结点 +{ + BTNode *p; + if (b==NULL) + return NULL; + else if (b->data==x) + return b; + else + { + p=FindNode(b->lchild,x); + if (p!=NULL) + return p; + else + return FindNode(b->rchild,x); + } +} +BTNode *LchildNode(BTNode *p) +{ + return p->lchild; +} +BTNode *RchildNode(BTNode *p) +{ + return p->rchild; +} +int BTHeight(BTNode *b) //求二叉树b的高度 +{ + int lchildh,rchildh; + if (b==NULL) return(0); //空树的高度为0 + else + { + lchildh=BTHeight(b->lchild); //求左子树的高度为lchildh + rchildh=BTHeight(b->rchild); //求右子树的高度为rchildh + return (lchildh>rchildh)? (lchildh+1):(rchildh+1); + } +} +void DispBTree(BTNode *b) //以括号表示法输出二叉树 +{ + if (b!=NULL) + { printf("%c",b->data); + if (b->lchild!=NULL || b->rchild!=NULL) + { printf("("); //有孩子结点时才输出( + DispBTree(b->lchild); //递归处理左子树 + if (b->rchild!=NULL) printf(","); //有右孩子结点时才输出, + DispBTree(b->rchild); //递归处理右子树 + printf(")"); //有孩子结点时才输出) + } + } +} \ No newline at end of file diff --git a/2224020127/chapter_7/exp7-1.cpp b/2224020127/chapter_7/exp7-1.cpp new file mode 100644 index 00000000..018476e4 --- /dev/null +++ b/2224020127/chapter_7/exp7-1.cpp @@ -0,0 +1,27 @@ +#include "btree.cpp" //包含二叉树的基本运算算法 +int main() +{ BTNode *b,*p,*lp,*rp;; + printf("二叉树的基本运算如下:\n"); + printf(" (1)创建二叉树\n"); + CreateBTree(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))"); + printf(" (2)输出二叉树:");DispBTree(b);printf("\n"); + printf(" (3)H结点:"); + p=FindNode(b,'H'); + if (p!=NULL) + { lp=LchildNode(p); + if (lp!=NULL) + printf("左孩子为%c ",lp->data); + else + printf("无左孩子 "); + rp=RchildNode(p); + if (rp!=NULL) + printf("右孩子为%c",rp->data); + else + printf("无右孩子 "); + } + printf("\n"); + printf(" (4)二叉树b的高度:%d\n",BTHeight(b)); + printf(" (5)释放二叉树b\n"); + DestroyBTree(b); + return 1; +} \ No newline at end of file diff --git a/2224020127/chapter_7/exp7-10.cpp b/2224020127/chapter_7/exp7-10.cpp new file mode 100644 index 00000000..6757648b --- /dev/null +++ b/2224020127/chapter_7/exp7-10.cpp @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#define MaxSize 100 //最多记录个数 +#define MaxSons 10 //最多下级单位数 +typedef struct +{ + char fname[20]; //单位名称 + char sname[20]; //下级单位名称或者人数 +} RecType; + +typedef struct node +{ char data[20]; //结点的值:单位名称或者人数 + struct node *sons[MaxSons]; //指向孩子结点 +} TSonNode; //声明孩子链存储结构结点类型 + +void ReadFile(RecType R[],int &n) //读abc.txt文件存入R数组中 +{ + FILE *fp; + n=0; + if ((fp=fopen("/workspace/data_structure/2224020127/chapter_7/abc.txt","r"))==NULL) + { + printf("不能打开文件abc.txt"); + return; + } + while (!feof(fp)) + { + fscanf(fp,"%s",&R[n].fname); //读fname域数据 + fscanf(fp,"%s",&R[n].sname); //读sname域数据 + n++; + } + fclose(fp); +} +TSonNode *CreateTree(char root[],RecType R[],int n) //创建一棵树 +{ + int i,j,k; + TSonNode *t; + t=(TSonNode *)malloc(sizeof(TSonNode)); //创建根结点 + strcpy(t->data,root); + for (k=0;ksons[k]=NULL; + i=0; j=0; + while (isons[j]=CreateTree(R[i].sname,R,n); + j++; + } + i++; + } + return t; +} + +void DispTree(TSonNode *t) //输出孩子链存储结构 +{ + int i; + if (t!=NULL) + { printf("%s",t->data); + if (t->sons[0]!=NULL) //t结点至少有一个孩子 + { printf("("); //输出一个左括号 + for (i=0;isons[i]); + if (t->sons[i+1]!=NULL) //如果有下一个孩子 + printf(","); //输出一个',' + else //如果没有下一个孩子 + break; //退出循环 + } + printf(")"); //输出一个右括号 + } + } +} +void DestroyTree(TSonNode *&t) //销毁树t +{ + int i; + if (t!=NULL) + { for (i=0;isons[i]!=NULL) //有子树 + DestroyTree(t->sons[i]); //销毁该子树 + else //再没有子树 + break; //退出循环 + } + free(t); //释放根结点 + } +} +TSonNode *FindNode(TSonNode *t,char x[]) //求x结点的指针 +{ int i; + TSonNode *p; + if (t==NULL) + return NULL; + else if (strcmp(t->data,x)==0) //找到值为x的结点 + return t; + else + { for (i=0;isons[i]!=NULL) + { p=FindNode(t->sons[i],x); + if (p!=NULL) return p; + } + else break; + return NULL; + } +} +int ChildCount(TSonNode *p) //求p所指结点的孩子个数 +{ int i,num=0; + for (i=0;isons[i]!=NULL) + num++; + else + break; + return num; +} +int Sonnum(TSonNode *t,char x[]) //求x单位的下一级单位数 +{ + TSonNode *p; + p=FindNode(t,x); + if (p==NULL) + return 0; + else + return ChildCount(p); +} +int LeafCount(TSonNode *t) //求树中叶子结点个数 +{ + int i,num=0; + if (t==NULL) + return 0; + else + { if (t->sons[0]==NULL) //t为叶子结点 + num++; + else //t不为叶子结点 + { for (i=0;isons[i]!=NULL) + num+=LeafCount(t->sons[i]); + else break; + } + return num; + } +} +int Classnum(TSonNode *t,char x[]) //求x单位的班数 +{ + TSonNode *p; + p=FindNode(t,x); + if (p==NULL) + return 0; + else + return LeafCount(p); +} +int LeafSum(TSonNode *t) //求树中叶子结点的数值和 +{ + int i,sum=0; + if (t==NULL) + return 0; + else + { + if (t->sons[0]==NULL) //t为叶子结点 + return atoi(t->data); + else //t不为叶子结点 + { for (i=0;isons[i]!=NULL) + sum+=LeafSum(t->sons[i]); + else break; + } + return sum; + } +} +int Studnum(TSonNode *t,char x[]) //求x单位的总学生人数 +{ + TSonNode *p; + p=FindNode(t,x); + if (p==NULL) + return 0; + else + return LeafSum(p); +} +int main() +{ + TSonNode *t; + RecType R[MaxSize]; + int n; + printf("(1)从abc.txt文件读数据到R数组中\n"); + ReadFile(R,n); + if (n==0) return 1; //记录个数为0时直接返回 + printf("(2)由数组R创建树t的孩子链存储结构\n"); + t=CreateTree(R[0].fname,R,n); //创建一棵树 + printf("(3)输出树t:"); DispTree(t); printf("\n"); + printf("(4)计算机学院的专业数:%d\n",Sonnum(t,"计算机学院")); + printf("(5)计算机学院的班数:%d\n",Classnum(t,"计算机学院")); + printf("(6)电信学院的学生数:%d\n",Studnum(t,"电信学院")); + printf("(7)销毁树t\n"); + DestroyTree(t); + + return 1; +} \ No newline at end of file diff --git a/2224020127/chapter_7/exp7-5.cpp b/2224020127/chapter_7/exp7-5.cpp new file mode 100644 index 00000000..4c9c09e9 --- /dev/null +++ b/2224020127/chapter_7/exp7-5.cpp @@ -0,0 +1,103 @@ +#include +#include +#define N 50 //叶子结点数 +#define M 2*N-1 //树中结点总数 +typedef struct +{ + char data[5]; //结点值 + int weight; //权重 + int parent; //双亲结点 + int lchild; //左孩子结点 + int rchild; //右孩子结点 +} HTNode; +typedef struct +{ + char cd[N]; //存放哈夫曼码 + int start; +} HCode; +void CreateHT(HTNode ht[],int n) //由ht的叶子结点构造完整的哈夫曼树 +{ + int i,k,lnode,rnode; + int min1,min2; + for (i=0;i<2*n-1;i++) //所有结点的相关域置初值-1 + ht[i].parent=ht[i].lchild=ht[i].rchild=-1; + for (i=n;i<2*n-1;i++) //构造哈夫曼树的分支结点 + { + min1=min2=32767; //lnode和rnode为最小权重的两个结点位置 + lnode=rnode=-1; + for (k=0;k<=i-1;k++) //查找最小和次小的结点 + if (ht[k].parent==-1) //只在尚未构造二叉树的结点中查找 + { + if (ht[k].weightlchild==NULL && b->rchild==NULL) //b为叶子结点 + { + printf(" %c到根结点逆路径: %c->",b->data,b->data); + for (int i=pathlen-1;i>0;i--) + printf("%c->",path[i]); + printf("%c\n",path[0]); + } + else + { + path[pathlen]=b->data; //将当前结点放入路径中 + pathlen++; //路径长度增1 + AllPath1(b->lchild,path,pathlen); //递归扫描左子树 + AllPath1(b->rchild,path,pathlen); //递归扫描右子树 + } + } +} +void LongPath1(BTNode *b,ElemType path[],int pathlen,ElemType longpath[],int &longpathlen) +//采用先序遍历方法输出第一条最长的逆路径 +{ + if (b==NULL) + { + if (pathlen>longpathlen) //若当前路径更长,将路径保存在longpath中 + { + for (int i=pathlen-1;i>=0;i--) + longpath[i]=path[i]; + longpathlen=pathlen; + } + } + else + { + path[pathlen]=b->data; //将当前结点放入路径中 + pathlen++; //路径长度增1 + LongPath1(b->lchild,path,pathlen,longpath,longpathlen); //递归扫描左子树 + LongPath1(b->rchild,path,pathlen,longpath,longpathlen); //递归扫描右子树 + } +} +void AllPath2(BTNode *b) //采用后序非递归遍历方法输出所有从叶子结点到根结点的逆路径 +{ + BTNode *st[MaxSize]; //定义一个顺序栈st + int top=-1; //栈顶指针初始化 + BTNode *p,*r; + bool flag; + p=b; + do + { + while (p!=NULL) //扫描结点p的所有左下结点并进栈 + { + top++; + st[top]=p; //结点p进栈 + p=p->lchild; //移动到左孩子 + } + r=NULL; //r指向刚刚访问的结点,初始时为空 + flag=true; //flag为真表示正在处理栈顶结点 + while (top>-1 && flag) //栈不空且flag为真时循环 + { + p=st[top]; //取出当前的栈顶结点p + if (p->rchild==r) //若结点p的右孩子为空或者为刚刚访问过的结点 + { + if (p->lchild==NULL && p->rchild==NULL) //若为叶子结点 + { //输出栈中所有结点值 + printf(" %c到根结点逆路径:",p->data); + for (int i=top;i>0;i--) + printf("%c->",st[i]->data); + printf("%c\n",st[0]->data); + } + top--; //退栈 + r=p; //r指向刚访问过的结点 + } + else + { p=p->rchild; //转向处理其右子树 + flag=false; //表示当前不是处理栈顶结点 + } + } + } while (top>-1); //栈不空循环 +} + +void AllPath3(BTNode *b) +//采用层次遍历方法输出所有从叶子结点到根结点的逆路径 +{ + struct snode + { + BTNode *node; //存放当前结点指针 + int parent; //存放双亲结点在队列中的位置 + } Qu[MaxSize]; //定义顺序队列 + int front,rear,p; //定义队头和队尾指针 + front=rear=-1; //置队列为空队列 + rear++; + Qu[rear].node=b; //根结点指针进入队列 + Qu[rear].parent=-1; //根结点没有双亲结点 + while (frontlchild==NULL && b->rchild==NULL) //*b为叶子结点 + { + printf(" %c到根结点逆路径:",b->data); + p=front; + while (Qu[p].parent!=-1) + { + printf("%c->",Qu[p].node->data); + p=Qu[p].parent; + } + printf("%c\n",Qu[p].node->data); + } + if (b->lchild!=NULL) //左孩子入队列 + { + rear++; + Qu[rear].node=b->lchild; + Qu[rear].parent=front; + } + if (b->rchild!=NULL) //右孩子入队列 + { + rear++; + Qu[rear].node=b->rchild; + Qu[rear].parent=front; + } + } +} + +int main() +{ + BTNode *b; + ElemType path[MaxSize],longpath[MaxSize]; + int i,longpathlen=0; + CreateBTree(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))"); + printf("二叉树b:");DispBTree(b);printf("\n"); + printf("先序遍历方法:\n");AllPath1(b,path,0); + LongPath1(b,path,0,longpath,longpathlen); + printf(" 第一条最长逆路径长度:%d\n",longpathlen); + printf(" 第一条最长逆路径:"); + for (i=longpathlen-1;i>=0;i--) + printf("%c ",longpath[i]); + printf("\n"); + printf("后序非递归遍历方法:\n");AllPath2(b); + printf("层次遍历方法:\n");AllPath3(b); + DestroyBTree(b); + return 1; +} \ No newline at end of file -- Gitee