趣学数据结构---->第六章:树

  • 二叉树
  • 线索二叉树
  • 树的应用
    • 二叉树的深度
    • 二叉树的叶子数
    • 二叉树的结点数
    • 三元组创建二叉树
    • 遍历序列还原树
    • 哈夫曼树

二叉树

二叉树的创建(询问创建以及补空创建),遍历(前序,中序,后序,层序)

#include <iostream>
#include <queue>  // 层序遍历,需要创建队列
using namespace std;typedef struct Bnode
{char data;struct Bnode* lchild, * rchild;
}Bnode,*Btree;// 创建二叉树
// 询问法
void CreateTree(Btree& T)
{char check;  // 判断是否创建左右孩子T = new Bnode;cout << "请输入结点信息:" << endl;cin >> T->data;cout << "是否添加 " << T->data << "的左孩子?(Y/N)" << endl;cin >> check;if (check == 'Y')CreateTree(T->lchild);elseT->lchild = NULL;cout << "是否添加 " << T->data << "的右孩子?(Y/N)" << endl;cin >> check;if (check == 'Y')CreateTree(T->rchild);elseT->rchild = NULL;
}//创建二叉树
// 补空法
// 二叉树补空后,按先序遍历输入字符,创建二叉树
void CreateTree2(Btree& T)
{char ch;cin >> ch;if (ch == '#')T = NULL;else{T = new Bnode;T->data = ch;  // 生成根结点CreateTree2(T->lchild);  // 递归创建左子树CreateTree2(T->rchild);  // 递归创建右子树}
}// 先序遍历
void preOrder(Btree T)
{if (T){cout << T->data << "  ";preOrder(T->lchild);preOrder(T->rchild);}
}// 中序遍历
void inOrder(Btree T)
{if (T){inOrder(T->lchild);cout << T->data << "  ";inOrder(T->rchild);}
}// 后序遍历
void posOrder(Btree T)
{if (T){posOrder(T->lchild);posOrder(T->rchild);cout << T->data << "  ";}
}//层序遍历
bool LevelTraverse(Btree T)
{Btree p;if (!T)return false;queue<Btree>Q; // 创建队列,里面存放指针类型Q.push(T);  // 根指针入队while (!Q.empty()){p = Q.front();  // 取出队头元素作为当前结点Q.pop();  // 队头元素出队cout << p->data << "  ";if (p->lchild)Q.push(p->lchild);  // 左孩子指针入队if (p->rchild)Q.push(p->rchild);  }return true;
}int main()
{Btree mytree;cout << "按先序次序输入二叉树中结点的值(孩子为空时输入#),创建一棵二叉树" << endl;CreateTree(mytree);cout << endl;cout << "二叉树的先序遍历结果:" << endl;preOrder(mytree);cout << endl;cout << "二叉树的中序遍历结果:" << endl;inOrder(mytree);cout << endl;cout << "二叉树的后序遍历结果:" << endl;posOrder(mytree);cout << endl;cout << "二叉树的层序遍历结果:" << endl;LevelTraverse(mytree);return 0;
}

线索二叉树

中序线索化,创建中序线索二叉树,遍历中序线索二叉树

#include <iostream>
using namespace std;typedef struct BTnode
{char data;struct BTnode* lchild, * rchild;int ltag, rtag;
}BTnode,*BTtree;BTtree pre;// 补空法 创建二叉树
void CreateBitree(BTtree& T)
{char ch;cin >> ch;if (ch == '#') T = NULL;else{T = new BTnode;T->data = ch;CreateBitree(T->lchild);CreateBitree(T->rchild);}
}// 中序遍历二叉树
void InOrder(BTtree T)
{if (T){InOrder(T->lchild);cout << T->data << "  ";InOrder(T->rchild);}
}// 中序线索化
void InThread(BTtree& p)
{if (p){InThread(p->lchild);  // 递归线索化左子树if (!p->lchild)  // p 的左子树为空{p->ltag = 1;  //给p加上左线索p->lchild = pre;//p的左孩子指针指向pre(前驱)}elsep->ltag = 0;if (pre){if (!pre->rchild)  //pre的右孩子为空{pre->rtag = 1;  //给pre加上右线索pre->rchild = p;  //pre的右孩子指针指向p(后继)}elsepre->rtag = 0;}pre = p;InThread(p->rchild);}
}// 创建中序线索二叉树
void CreateInThread(BTtree& T)
{pre = NULL;if (T){InThread(T);  // 中序线索化pre->rchild = NULL;  // 处理遍历的最后一个结点,其后继为空pre->rtag = 1;}
}//遍历中序线索二叉树
void InorderThread(BTtree T)
{BTtree p;p = T;while (p){while (p->ltag == 0) p = p->lchild;// 找到最左结点 开始遍历cout << p->data << "  ";  while (p->rtag == 1 && p->rchild){p = p->rchild;cout << p->data << "  ";}p = p->rchild;  //转向p的右子树}
}int main()
{BTtree tree;cout << "请输入先序创建二叉树的序列(补空法):\n";  //例如ABD##E##CF#G###CreateBitree(tree);cout << "二叉树的中序遍历结果为:" << endl;InOrder(tree);cout << endl;CreateInThread(tree);  // 创建中序线索二叉树cout << "中序线索二叉树的遍历结果:" << endl;InorderThread(tree); return 0;
}

树的应用

二叉树的深度

递归求二叉树的深度

#include <iostream>
using namespace std;typedef struct Bnode
{char data;struct Bnode* lchild, *rchild;
}Bnode,*Btree;//创建二叉树
void Createtree(Btree& T)
{char  ch;cin >> ch;if (ch == '#') T = NULL;else{T = new Bnode;T->data = ch;Createtree(T->lchild);Createtree(T->rchild);}
}//求二叉树的深度
int Depth(Btree T)
{int m, n;if (T == NULL)  //如果为空树,深度为0return 0;else{m = Depth(T->lchild);  //递归计算左子树深度n = Depth(T->rchild);  //递归计算左子树深度if (m > n)return m + 1;  //返回左右子树最大值加1elsereturn n + 1;}
}int main()
{Btree mytree;cout << "按先序次序输入二叉树中结点的值(孩子为空时输入#),创建一棵二叉树" << endl;//ABD##E##CF#G###Createtree(mytree);cout << endl;cout << "二叉树的深度为:" << Depth(mytree) << endl;return 0;
}

二叉树的叶子数

二叉树的结点数

递归求二叉树的叶子数和结点数

#include <iostream>
using namespace std;typedef struct Bnode
{char data;struct Bnode* lchild, *rchild;
}Bnode,*Btree;//创建二叉树
void Createtree(Btree& T)
{char  ch;cin >> ch;if (ch == '#') T = NULL;else{T = new Bnode;T->data = ch;Createtree(T->lchild);Createtree(T->rchild);}
}// 求二叉树的叶子数
int LeafCount(Btree T)
{if (T == NULL)return 0;elseif (T->lchild == NULL && T->rchild == NULL)  //左右子树均为空,则叶子数为1return 1;elsereturn LeafCount(T->lchild) + LeafCount(T->rchild); //递归计算左子树和右子树的叶子数之和
}// 求二叉树的结点数
int NodeCount(Btree T)
{if (T == NULL)return 0;elsereturn NodeCount(T->lchild) + NodeCount(T->rchild) + 1;  //递归计算左子树和右子树的结点数之和加1
}int main()
{Btree mytree;cout << "按先序次序输入二叉树中结点的值(孩子为空时输入#),创建一棵二叉树" << endl;//ABD##E##CF#G###Createtree(mytree);//创建二叉树cout << endl;cout << "二叉树的结点数为:" << NodeCount(mytree) << endl;cout << "二叉树的叶子数为:" << LeafCount(mytree) << endl;return 0;
}

三元组创建二叉树

按层次序列输入,利用队列实现

#include <iostream>
#include <queue>
using namespace std;/*测试数据
NULL A L
A B L
A C R
B D R
C E L
C F R
D G L
F H L
NULL NULL L
*/struct biTnode
{string data;biTnode* lChild, * rChild;
};
biTnode* T = NULL;void CreatebiTree(biTnode*& T)
{string a, b, c;biTnode* node,* p;queue<biTnode*>q;cin >> a >> b >> c;if (a == "NULL" && b != "NULL") // 创建根结点{node = new biTnode;node->data = b;node->lChild = node->rChild = NULL;T = node;q.push(T);}cin >> a >> b >> c;while (!q.empty() && a != "NULL" && b != "NULL"){p = q.front();q.pop();while (a == p->data){node = new biTnode;node->data = b;node->lChild = node->rChild = NULL;if (c == "L"){p->lChild = node;cout << p->data << "`s lchild is " << node->data << endl;}else{p->rChild = node;cout << p->data << "`s rchild is " << node->data << endl;}q.push(node);cin >> a >> b >> c;}}
}void preorder(biTnode*& T)
{if (T){cout << T->data << "  ";preorder(T->lChild);preorder(T->rChild);}
}void inorder(biTnode*& T)
{if (T){inorder(T->lChild);cout << T->data << "  ";inorder(T->rChild);}
}void posorder(biTnode*& T)
{if (T){posorder(T->lChild);posorder(T->rChild);cout << T->data << "  ";}
}int main()
{cout << "输入结点数据a,b,c(a为父亲,b为结点字符,c为‘L’左孩子或‘R’右孩子)" << endl;CreatebiTree(T);cout << "创建树成功!" << endl;cout << "先序遍历:" << endl;preorder(T);cout << endl << "中序遍历:" << endl;inorder(T);cout << endl << "后序遍历:" << endl;posorder(T);return 0;
}

遍历序列还原树

先序中序还原二叉树
后序中序还原二叉树

#include <iostream>
using namespace std;typedef struct node
{char data;struct node* lchild, * rchild;
}BiTNode,*BiTree;//前序中序还原建立二叉树
// pre mid为指针类型,指前序和中序的首地址
//len 为序列的长度
BiTree pre_mid_createBiTree(char* pre, char* mid,int len)
{if (len == 0)return NULL;char ch = pre[0];  // 找到先序的第一个结点int index = 0;while (mid[index] != ch){index++;}BiTree T = new BiTNode;  //创建根结点T->data = ch;T->lchild = pre_mid_createBiTree(pre + 1, mid, index);  //建立左子树T->rchild = pre_mid_createBiTree(pre + index + 1, mid + index + 1, len - index - 1); // 建立右子树return T;
}// 后序中序还原建立二叉树
// 后序序列最后一个字符为根
BiTree pro_mid_createBiTree(char* last, char *mid, int len)
{if (len == 0)return NULL;char ch = last[len - 1]; //取得后序遍历顺序中最后一个结点int index = 0;while (mid[index]!=ch){index++;}BiTree T = new BiTNode;T->data = ch;T->lchild = pro_mid_createBiTree(last, mid, index);T->rchild = pro_mid_createBiTree(last + index, mid + index + 1, len - index - 1);return T;
}//前序递归遍历二叉树
void pre_order(BiTree T)
{if (T){cout << T->data;pre_order(T->lchild);pre_order(T->rchild);}
}//后序递归遍历二叉树
void pro_order(BiTree T)
{if (T){pro_order(T->lchild);pro_order(T->rchild);cout << T->data;}
}int main()
{BiTree T;int n;char pre[100], last[100], mid[100];cout << "1. 前序中序还原二叉树\n";cout << "2. 后序中序还原二叉树\n";cout << "0. 退出\n";int choose = -1;while (choose != 0){cout << "请选择:";cin >> choose;switch (choose){case 1:  //前序中序还原二叉树cout << "请输入结点个数:" << endl;cin >> n;cout << "请输入前序序列:" << endl;for (int i = 0; i < n; i++)cin >> pre[i];cout << "请输入中序序列:" << endl;for (int i = 0; i < n; i++)cin >> mid[i];T = pre_mid_createBiTree(pre, mid, n);cout << endl;cout << "二叉树还原成功,输出其后序序列:" << endl;pro_order(T);cout << endl << endl;break;case 2:  //后序中序还原二叉树cout << "请输入结点的个数:" << endl;cin >> n;cout << "请输入后序序列:" << endl;for (int i = 0; i < n; i++)cin >> last[i];cout << "请输入中序序列:" << endl;for (int i = 0; i < n; i++)cin >> mid[i];T = pro_mid_createBiTree(last, mid, n);cout << endl;cout << "二叉树还原成功,输出其先序序列:" << endl;pre_order(T);cout << endl << endl;break;}}return 0;
}

哈夫曼树

哈夫曼算法采取的贪心策略是每次从树的集合中取出没有双亲且权值最小的两棵树作为左右子树,构造一棵新树,新树根结点的权值为其左右孩子结点权值之和,并将新树插入到树的集合中

#include <iostream>
#include<algorithm>
using namespace std;#define MAXBIT   100
#define MAXVALUE 10000
#define MAXLEAF  30
#define MAXNODE  MAXLEAF*2 -1/* 结点结构体 */
typedef struct
{double weight;int parent;int lchild;int rchild;char value;
}HNodeType;       /* 编码结构体 */
typedef struct
{int bit[MAXBIT];int start;
}HCodeType;    HNodeType HuffNode[MAXNODE]; /* 定义一个结点结构体数组 */
HCodeType HuffCode[MAXLEAF];/* 定义一个编码结构体数组*//* 构造哈夫曼树 */
/* i、j:循环变量,m1、m2:构造哈夫曼树不同过程中两个最小权值结点的权值,x1、x2:构造哈夫曼树不同过程中两个最小权值结点在数组中的序号*/
void HuffmanTree(HNodeType HuffNode[MAXNODE], int n)
{int i, j, x1, x2;double m1, m2;/*初始化存放哈夫曼树数组HuffNode[]中的结点 */for (i = 0; i < 2 * n - 1; i++){HuffNode[i].weight = 0;//权值HuffNode[i].parent = -1;HuffNode[i].lchild = -1;HuffNode[i].rchild = -1;}/*输 入 n 个 叶 子 结 点 的 权 值*/for (int i = 0; i < n; i++){cout << "Please input value and weight of leaf node " << i + 1 << endl;cin >> HuffNode[i].value >> HuffNode[i].weight;}/* 构造 Huffman 树 *///执行n-1次合并for (int i = 0; i < n - 1; i++){m1 = m2 = MAXVALUE;x1 = x2 = 0;/* 找出所有结点中权值最小、无父结点的两个结点,并合并之为一棵二叉树 */for (int j = 0; j < n + i; j++){if (HuffNode[j].weight < m1 && HuffNode[j].parent == -1){m2 = m1;x2 = x1;m1 = HuffNode[j].weight;x1 = j;}else if (HuffNode[j].weight < m2 && HuffNode[j].parent == -1){m2 = HuffNode[j].weight;x2 = j;}}/* 设置找到的两个子结点 x1、x2 的父结点信息 */HuffNode[x1].parent = n + i;HuffNode[x2].parent = n + i;HuffNode[n + i].lchild = x1;HuffNode[n + i].rchild = x2;HuffNode[n + i].weight = m1 + m2;/* 用于测试 */cout << "x1.weight and x2.weight in round " << i + 1 << "\t" << HuffNode[x1].weight << "\t" << HuffNode[x2].weight << endl;}
}/* 哈夫曼树编码 */
void HuffmanCode(HCodeType HuffCode[MAXLEAF], int n)
{HCodeType cd;   /* 定义一个临时变量来存放求解编码时的信息 */int i, j, c, p;for (int i = 0; i < n; i++){cd.start = n - 1;c = i; // i 为叶子结点的编号p = HuffNode[c].parent;while (p != -1){if (HuffNode[p].lchild == c)cd.bit[cd.start] = 0;elsecd.bit[cd.start] = 1;cd.start--;  // start 向前一位c = p; // c p 变量上移,准备下一次循环p = HuffNode[c].parent;                     }for (j = cd.start + 1; j < n; j++){HuffCode[i].bit[j] = cd.bit[j];}HuffCode[i].start = cd.start;}
}int main()
{int n;cout << "Please input n:" << endl;cin >> n;HuffmanTree(HuffNode, n);  //构造哈夫曼树HuffmanCode(HuffCode, n);  // 哈夫曼树编码//输出已保存好的所有存在编码的哈夫曼编码for (int i = 0; i < n; i++){cout << HuffNode[i].value << ": Huffman code is: ";for (int j = HuffCode[i].start + 1; j < n; j++){cout << HuffCode[i].bit[j];}cout << endl;        }return 0;
}

趣学数据结构--第六章:树相关推荐

  1. 数据结构思维 第六章 树的遍历

    第六章 树的遍历 原文:Chapter 6 Tree traversal 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 本章将介绍一个 Web 搜索引擎,我们将在本书其余部分开 ...

  2. 《大话数据结构》第六章 树

    文章目录 第六章 树 树的定义 结点的分类 树的抽象数据类型 树的存储结构 双亲表示法 孩子表示法 孩子兄弟表示法 二叉树 特殊二叉树 斜树 满二叉树 完全二叉树 二叉树的性质 二叉树的存储结构 遍历 ...

  3. 《趣学数据结构》新书预售!

    <趣学数据结构>终于出版了,好事多磨,欢迎大家捧场! 当当:http://product.dangdang.com/27914358.html 京东:https://item.jd.com ...

  4. 【趣学算法】第二章 算法之美(下)

    14天阅读挑战赛 [趣学算法]第二章 算法之美(下) 1. 一棋盘的麦子 1.1 题目描述 1.2 题目解析 1.3 爆炸增量函数 称上面的函数(1.2中的第一个函数)为爆炸增量函数. 爆炸函数也就是 ...

  5. 【趣学算法】第一章 算法之美(上)

    14天阅读挑战赛 [趣学算法]第一章 算法之美(上) 文章目录 [趣学算法]第一章 算法之美(上) 1.打开算法之门 2.妙不可言---算法复杂性 2.1 算法的引入 [算法的定义] [算法题] [& ...

  6. Scala学习4之快学scala第六章习题之6.6花色枚举

    快学scala第六章习题之6.6花色枚举 6.6 编写一个扑克牌4种花色的枚举,让其toString方法分别返回♣,♦,♥,♠ 代码: </pre><pre name="c ...

  7. 数据结构第六章——图

    数据结构第六章--图 图的定义和术语 G = (V, E) V:顶点(数据元素的)有穷非空集合: E:边的有穷集合. 无向图:每条边都是无方向的. 有向图:每条边都是有方向的. 完全图:任意两个顶点都 ...

  8. 趣学算法【第一章:算法之美】感悟(上)

    14天阅读挑战赛 前言 努力是为了不平庸~ 算法学习有些时候是枯燥的,这一次,让我们先人一步,趣学算法! 1.什么是算法,为什么要学习? 其实算法是一个比较模糊的概念,简单来说,算法就是将解决一件事的 ...

  9. 中根遍历二叉查找树所得序列一定是有序序列_学习数据结构--第六章:查找(查找)

    第六章:查找 1.查找的基本概念 查找:在数据集合中寻找满足某种条件的数据元素的过程. 查找的结果 查找成功和查找失败 查找表:用于查找的数据集合,由同一种数据类型(或记录)的组成,可以是一个数组或链 ...

最新文章

  1. 公开SNS社区即时找朋友链的源代码和部署方案(续四)
  2. 劫持 function_core.php,function_core.php文件中常用函数
  3. mysqlperformanceblog
  4. SAP 开发陷阱一箩筐(02)——无法创建客户增强的包含程序
  5. java 飞行记录器_Java 11功能– Java飞行记录器
  6. C# datetime 操作
  7. windows文件保护_Windows系统下媲美时间机器的系统备份工具,统统免费
  8. Linux——less指令常用操作
  9. java 二分查找算法
  10. Session实现验证码登陆笔记
  11. 通过PO接口表导入PO数据
  12. 网络断网远程计算机会自动修复么,网络断网不怕,教你自己动手修复_电脑故障...
  13. 压力测试工具Siege详解
  14. 【操作系统】实时调度
  15. nrr评分预测_NRR的完整形式是什么?
  16. 《山海经》异兽75种,附图
  17. Postfix权威指南阅读笔记
  18. python练习题(一):输入某年某月某日,判断这一天是这一年的第几天
  19. 图像处理在医学方面的应用
  20. 最简单的加密---异或加密

热门文章

  1. 安装npm报错rollbackFailedOptional: verb npm-session原因及解决方案
  2. 通信原理知识点汇总1
  3. 【微信篇】微信导出个人信息浅谈
  4. GitHub 优秀的 Android 开源项目(值得研究)
  5. ruby , each,map,collect,inject,reject,select,shuffle[n..m],flatten
  6. css 3D 简单实践
  7. 分布式系统复习(课后重点题型)
  8. 刷新主板BIOS的几种方法
  9. 计算机与科学论文3000,计算机科学技术应用论文3000字(2)
  10. 业务流程设计的八大原则