1 3 3 3 template typename T struct

  • Slides: 109
Download presentation

树的存储 1双亲表示存储(顺序) 3结点=数据+双亲位置 3按层次顺序保存结点 3 第 次 课 树 、 二 叉 树 、

树的存储 1双亲表示存储(顺序) 3结点=数据+双亲位置 3按层次顺序保存结点 3 第 次 课 树 、 二 叉 树 、 图 template <typename T> struct PTNode //结点 { T data; int parent; }; A B E C F K G H L // 双亲位置 struct PTree //树 { PTNode nodes[1000]; D I int n; J // 结点数 }; 0 1 2 3 4 5 6 7 8 9 10 11 data A B C D E F G H I J K L parent -1 0 0 0 1 1 2 3 3 3 5 5 9/109

data firstchild 3 第 次 课 树 、 二 叉 树 、 图 0

data firstchild 3 第 次 课 树 、 二 叉 树 、 图 0 A 1 2 1 B 4 5 2 C 6 3 D 7 8 4 E 5 F 10 11 6 G ^ 7 H ^ 8 I ^ 9 J ^ 10 K ^ 11 L ^ 3 ^ ^ T. n = 12 T. r = 0 ^ 9 ^ ^ ^ A E K B C F G H D I J L 11/109

template <class T> 树 、 二 叉 树 、 图 { private: 3 第

template <class T> 树 、 二 叉 树 、 图 { private: 3 第 次 课 class Binary_Tree Btnode<T> *BT; //二叉链表根结点指针 public: Binary_Tree() {BT=NULL; } //二叉链表初始化 void creat_Binary_Tree(T); //生成二叉链表 void pretrav_Binary_Tree(); //前序遍历二叉链表 void intrav_Binary_Tree(); //中序遍历二叉链表 void postrav_Binary_Tree(); //后序遍历二叉链表 }; 33/109

Template <class T> 3 第 次 课 static void creat(Btnode<T> *p, int k, T

Template <class T> 3 第 次 课 static void creat(Btnode<T> *p, int k, T end) { Btnode<T> *q; T x; 树 、 二 叉 树 、 图 cin>>x; //输入结点值 if ( x!=end) //非结束符值 { q=new Btnode<T>; //申请一个二叉链表结点 q->d=x; q->lchild=q->rchild=NULL; if(k==1) p->lchild=q; //链接到左子树 if(k==2) p->rchild=q; //链接到右子树 creat(q, 1, end); //递归生成左子树 creat(q, 2, end); //递归生成右子树 } } 35/109

//递归遍历 template <class T> intrav (Btnode<T> *p) static void postrav pretrav 树 、 二

//递归遍历 template <class T> intrav (Btnode<T> *p) static void postrav pretrav 树 、 二 叉 树 、 图 { 3 第 次 课 if(p!=NULL) { cout << p->d<<“ ”; //遍历左子树 //输出根结点值 postrav(p->lchild); //遍历左子树 intrav(p->lchild); postrav(p->rchild); //遍历右子树 cout << p->d<<“ ”; //输出根结点值 pretrav(p->lchild); //遍历左子树 cout << p->d<<“ ”; //遍历右子树 //输出根结点值 intrav(p->rchild); pretrav(p->rchild); //遍历右子树 } } 36/109

3 第 次 课 树 、 二 叉 树 、 图 void Level. Traverse

3 第 次 课 树 、 二 叉 树 、 图 void Level. Traverse (Btnode *p) //广度优先遍历 { Init. Queue(Q); //初始化队列(二叉树结点) if ( p != NULL ) { cout<<p->data<<endl; // 输出根结点 En. Queue(Q, p); // 根结点入队 while( !Queue. Empty(Q) ) // 队空则算法结束 { p = De. Queue (Q); // 出队 if ( p->lchild != NULL ) //左孩子非空,访问左孩子并入队 { cout<< p->lchild ->data<<endl; En. Queue(Q, p->lchild ); } if ( p->rchild != NULL ) //右孩子非空,访问右孩子并入队 { cout<<p->rchild->data<<endl; En. Queue(Q, p->rchild ); } } 39/109

3 第 次 课 树 、 二 叉 树 、 图 template <class T>

3 第 次 课 树 、 二 叉 树 、 图 template <class T> void in_threaded_BT<T>: : intrav_threaded_BT() { TTnode<T> *p; if(BT==NULL) return; //二叉链表为空 p=BT; while(p->lflag==0) p=p->lchild; //沿左链找到叶子结点 cout<<p->d<<“ “; //输出中序序列中的第一个结点 while(p->rchild!=NULL) //沿右链扫描后件 { if(p->rflag==1) p=p->rchild; else //沿右子树的左链扫描 { p=p->rchild; while((p->lflag==0)&&(p->lchild!=NULL)) p=p->lchild; } cout<<p->d<<“ “; //输出中序序列中的结点 } cout <<endl; } 46/109

3 第 次 课 树 、 二 叉 树 、 图 typedef enum {DG,

3 第 次 课 树 、 二 叉 树 、 图 typedef enum {DG, DN, AG, AN} Graph. Kind; //图的类型 template <class T> struct Arc. Cell //边 { int adj; //顶点间的关系,无向图: 0, 1,有向图:数值, 无穷大 T *info; //顶点的信息 }; template <class T 1, class T 2> class Matrix_GP {private: T 2 *vexs; //顶点 Arc. Cell<T 1> **arcs; //边 int vexnum, arcnum; //顶点和边的数目 Graph. Kind kind; // 图的类型 public: Matrix_GP(){ }; Matrix_GP(int, int , Graph. Kind ) { }; //带参数的构造函数 ~Matrix_GP(){ }; void inti_GP() { }; //初始化图 void out_GP() { }; //输出图的权值 }; 60/109

3 第 次 课 树 、 二 叉 树 、 图 图邻接表的结构定义 //头结点(顺序存储) //表结点

3 第 次 课 树 、 二 叉 树 、 图 图邻接表的结构定义 //头结点(顺序存储) //表结点 template <class T 1, class T 2> struct gpnode { T 2 data; node<T 1> * link; }; template <class T 1> struct node { int num; T 1 val; node *next; }; 65/109

开始 3 第 次 课 template <class T 1, class T 2> 标志数组初始化 树

开始 3 第 次 课 template <class T 1, class T 2> 标志数组初始化 树 、 二 叉 树 、 图 void Link_GP<T 1, T 2>: : dfs_Link_GP() { int k, *mark; k=0 mark=new int[nn]; V[k]访问过 Y for(k=0; k<nn; k++) //初始化标识 N mark[k]=0; DFS for(k=0; k<nn; k++) if(mark[k]==0) dfs(gp, k, mark); k=k+1 N //访问标识 cout<<endl; delete mark; k==Vexnums-1 Y 结束 } 71/109

3 第 次 课 树 、 二 叉 树 、 图 开始 访问v, 置标志

3 第 次 课 树 、 二 叉 树 、 图 开始 访问v, 置标志 找v邻接点 有邻接点w N Y 返回 w访问过 N w=v Y 求下一邻接点 template <class T 1, class T 2> void dfs(gpnode<T 1, T 2> *q, int k, int *mark) { node<T 1> *p; cout<<(q+k)->data<<“ ”; //访问 mark[k]=1; p=(q+k)->link; while(p!=NULL) //至链尾结束 { if(mark[p->num]==0) dfs(q, p->num, mark); p=p->next; } } DFS 72/109

第 次 课 3 开始 标志数组初始化 树 、 二 叉 树 、 图 k=0

第 次 课 3 开始 标志数组初始化 树 、 二 叉 树 、 图 k=0 V[k]访问过 Y k=k+1 N k==Vexnums-1 Y 结束 N BFS template <class T 1, class T 2> void Link_GP<T 1, T 2>: : bfs_Link_GP() { int k, *mark; mark=new int[nn]; for(k=0; k<nn; k++) mark[k]=0; //标志初始化 for(k=0; k<nn; k++) if(mark[k]==0) bfs(gp, k, mark); cout<<endl; delete mark; } 74/109

开始 3 第 次 课 树 、 二 叉 树 、 图 template <class

开始 3 第 次 课 树 、 二 叉 树 、 图 template <class T 1, class T 2> void bfs(gpnode<T 1, T 2> *gp, int k, int *mark) { node<T 1> *p; sq_Queue<int> q(200); mark[k]=1; cout<<(gp+k)->data<<“ ”; q. ins_sq_Queue(k); //入队 while(q. flag_sq_Queue()) //队空结束 { k=q. del_sq_Queue(); //出队 p=(gp+k)->link; //后件结点指针 while(p!=NULL) { k=p->num-1; if(mark[k]==0) //结点未被访问 { mark[k]=1; cout<<(gp+k)->data<<“ ”; q. ins_sq_Queue(k); //入队 } p=p->next; //取下一结点 } } } 访问v[k]置标志 BFS 初始化队列 v[k]入队 队列空吗 结束 Y 访问w, 置标志 N 队头v出队 w入队 求v邻接点w N v下一邻接点 w w存在吗 Y w访问过 Y N 75/109

哈夫曼树编码的应用举例 3 第 次 课 例 将百分制转换成五分制 树 、 二 叉 树 、 图

哈夫曼树编码的应用举例 3 第 次 课 例 将百分制转换成五分制 树 、 二 叉 树 、 图 分数 0~59 60~69 70~79 80~89 90~100 比例 0. 05 0. 15 0. 40 0. 30 0. 10 等级 E D C B A if (score>=90) level=A; else if(score>=80 && score<90) level=B; else if(score>=70 && score<80) level=C; else if(score>=60 && score<69) level=D; else level=E; Y A ? >90 N 80=<? <90 Y B N 70=<? <80 Y C WPL=3. 15 N 60=<? <70 Y D N E 88/109

利用哈夫曼编码 3 第 次 课 70=<? <80 树 、 二 叉 树 、 图

利用哈夫曼编码 3 第 次 课 70=<? <80 树 、 二 叉 树 、 图 N 80=<? <90 N 60=<? <70 N N E 0. 05 ? >90 Y A 0. 10 Y D 0. 15 Y B 0. 30 Y C 0. 40 WPL=0. 4*1+0. 3*2+0. 15*3+0. 1*4+0. 05*4=2. 05 89/109

例子中部分数据形式 3 第 次 课 树 、 二 叉 树 、 图 COST[EV[k]. p

例子中部分数据形式 3 第 次 课 树 、 二 叉 树 、 图 COST[EV[k]. p 1, EV[k]. p 2] 17. 5 28. 5 30. 4 34. 5 44. 2 45. 6 55. 2 60. 4 64. 5 71. 5 75. 0 82. 5 k EV[k]. p 1 0 1 2 3 4 5 6 7 8 9 10 11 EV[k]. p 2 3 4 7 2 8 3 5 4 1 6 7 2 0 2 2 1 4 3 0 3 6 0 struct EVS { int p 1; int p 2; } 97/109

算法的具体实现——核心部分 void minspanningtree( int cost[, ], EVS ev[], int EN, int N) 3 第

算法的具体实现——核心部分 void minspanningtree( int cost[, ], EVS ev[], int EN, int N) 3 第 次 课 { int tag[N]; Initial (tag); int Enumb=0; int SM=0; int k=1; //tag数组初始化 //k-边数累计 while ((Enumb<=N-1) && ( k<=EN)) 树 、 二 叉 树 、 图 { u=EV[k]. P 1; v=EV[k]. P 2; //选一对顶点(u, v) if ( tag[u]!=tag[v] ) //u, v不属于同一集合 { cout<<(u, v); Enumb=Enumb+1; //最小生成树增加一条边 SM=SM+cost[u, v]; Modify. Tag(); //合并, 修改tag } k=k+1; //找下一条边 } if (Enumb< n-1) out<<“ There is not a minspanning tree” else out<<SM; } 98/109

邻接表的拓扑排序示例 3 第 次 课 树 、 二 叉 树 、 图 V 2

邻接表的拓扑排序示例 3 第 次 课 树 、 二 叉 树 、 图 V 2 V 1 栈变化 V 6 V 3 V 4 V V 7 V 5 V 1 V 2 V 3 V 4 V 5 V 6 V 7 V 4 V 5 V 3 V 7 V 1 V 2 V 6 id Link 0 10 01 2 0 1 0 3012 2 3 6 7 ∧ 5 7 ∧ 3 ∧ ∧ 拓扑序列: V 4, V 5, V 1, V 3, V 2, V 7, V 6, 107/109