当前位置:   article > 正文

《数据结构》课程设计(C/C++版):植物百科数据的管理与分析_植物百科数据的管理课程设计

植物百科数据的管理课程设计

目录

第1关:增加植物信息

第2关:删除植物信息

第3关:修改植物信息

第4关:基于顺序表的顺序查找

第5关:基于链表的顺序查找

第6关:基于顺序表的折半查找

第7关:基于二叉排序树的查找

第8关:基于开放地址法的散列查找

第9关:基于链地址法的散列查找

第10关:基于BF算法的植物关键信息查询

第11关:基于KMP算法的植物关键信息查询

第12关:直接插入排序

第13关:折半插入排序

第14关:简单选择排序

第15关:冒泡排序

第16关:快速排序

第17关:植物移植最短路径分析

第18关:可移植路径分析

第19关:植物分类树构建

第20关:同属植物信息检索

第21关:下属植物信息检索


第1关:增加植物信息

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. struct Plant
  4. {
  5. //植物信息定义
  6. string name; //植物名称
  7. string sname; //学名
  8. string place[100]; //分布地
  9. string detail; //详情描述
  10. };
  11. typedef struct LNode
  12. {
  13. Plant data; //结点的数据域
  14. struct LNode *next; //指针域
  15. }LNode,*LinkList;
  16. void ReadFile(LinkList& L, string filename)
  17. {//从文件中读取数据,存入链表L中
  18. ifstream infile("data_edit/plant.txt");
  19. string line;
  20. LinkList r = L;
  21. while (getline(infile, line)) {
  22. LinkList p = new LNode;
  23. Plant temp;
  24. stringstream data(line);
  25. string s;
  26. int flag = 0;
  27. while (getline(data, s, '#')) {
  28. if (flag == 0) temp.name = s;
  29. if (flag == 1) temp.sname = s;
  30. if (flag == 2) {
  31. stringstream ssplace(s);
  32. string place;
  33. int placenum = 0;
  34. while (getline(ssplace, place, '@')) {
  35. temp.place[placenum] = place;
  36. placenum++;
  37. }
  38. }
  39. if (flag == 3) temp.detail = s;
  40. flag++;
  41. }
  42. p->data = temp;
  43. p->next = r->next;
  44. r->next = p;
  45. r = p;
  46. }
  47. infile.close();
  48. return;
  49. }
  50. int InPlant(LinkList L,string name)
  51. {//判断该植物名称name是否存在于链表中
  52. LNode* p = new LNode;
  53. p = L->next;
  54. int flag = 0;
  55. while (p) {
  56. if (p->data.name == name) {
  57. flag++;
  58. }
  59. p = p->next;
  60. }
  61. if (flag > 0) {
  62. return true;
  63. }
  64. else {
  65. return false;
  66. }
  67. }
  68. bool InsertPlant(LinkList &L, string filename)
  69. {//增加植物信息,输入植物的名称、学名、分布地和详情描述信息,将该植物的基本信息添加到plant.txt中的最后
  70. //如果该植物名称存在于plant.txt中,返回false,否则,返回true
  71. int n = 0;
  72. string name, sname, place[100], detail;
  73. cin >> name;
  74. getchar();
  75. getline(cin, sname);
  76. cin>> n;
  77. for (int i = 0; i < n; i++) {
  78. cin >> place[i];
  79. }
  80. cin >> detail;
  81. if (InPlant(L, name)) {
  82. return false;
  83. }
  84. else {
  85. fstream file;
  86. file.open(filename, ios::out | ios::app);
  87. file << name << "#" << sname << "#";
  88. for (int i = 0; i < n-1; i++) {
  89. file<< place[i]<<"@";
  90. }
  91. file << place[n - 1] << "#" << detail << endl;
  92. }
  93. }

第2关:删除植物信息

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. struct Plant
  4. {
  5. //植物信息定义
  6. string name; //植物名称
  7. string sname; //学名
  8. string place[100]; //分布地
  9. string detail; //详情描述
  10. };
  11. typedef struct LNode
  12. {
  13. Plant data; //结点的数据域
  14. struct LNode *next; //指针域
  15. }LNode,*LinkList;
  16. void ReadFile(LinkList& L, string filename)
  17. {//从文件中读取数据,存入链表L中
  18. ifstream infile;
  19. infile.open(filename.c_str());
  20. string line;
  21. LinkList r = L;
  22. while (getline(infile, line)) {
  23. LinkList p = new LNode;
  24. Plant temp;
  25. stringstream data(line);
  26. string s;
  27. int flag = 0;
  28. while (getline(data, s, '#')) {
  29. if (flag == 0) temp.name = s;
  30. if (flag == 1) temp.sname = s;
  31. if (flag == 2) {
  32. stringstream ssplace(s);
  33. string place;
  34. int placenum = 0;
  35. while (getline(ssplace, place, '@')) {
  36. temp.place[placenum] = place;
  37. placenum++;
  38. }
  39. }
  40. if (flag == 3) temp.detail = s;
  41. flag++;
  42. }
  43. p->data = temp;
  44. p->next = r->next;
  45. r->next = p;
  46. r = p;
  47. }
  48. infile.close();
  49. return;
  50. }
  51. void DeletePlant(LinkList &L,string name,string filename)
  52. {//删除指定植物信息
  53. LNode* p = new LNode;
  54. p = L;
  55. while (p->next) {
  56. if (p->next->data.name == name) {
  57. LNode* q = new LNode;
  58. q = p->next;
  59. p->next = q->next;
  60. delete(q);
  61. }
  62. else {
  63. p = p->next;
  64. }
  65. }
  66. p = L->next;
  67. fstream file;
  68. file.open(filename, ios::out);
  69. while (p) {
  70. int n = 0;
  71. while (p->data.place[n]!="") {
  72. n++;
  73. }
  74. file << p->data.name << "#" << p->data.sname << "#";
  75. for (int i = 0; i < n - 1; i++) {
  76. file << p->data.place[i] << "@";
  77. }
  78. file << p->data.place[n - 1] << "#" << p->data.detail << endl;
  79. p = p->next;
  80. }
  81. file.close();
  82. }

第3关:修改植物信息

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. struct Plant
  4. {
  5. //植物信息定义
  6. string name; //植物名称
  7. string sname; //学名
  8. string place[100]; //分布地
  9. string detail; //详情描述
  10. };
  11. typedef struct LNode
  12. {
  13. Plant data; //结点的数据域
  14. struct LNode *next; //指针域
  15. }LNode,*LinkList;
  16. void ReadFile(LinkList& L, string filename)
  17. {//从文件中读取数据,存入链表L中
  18. ifstream infile;
  19. infile.open(filename.c_str());
  20. string line;
  21. LinkList r = L;
  22. while (getline(infile, line)) {
  23. LinkList p = new LNode;
  24. Plant temp;
  25. stringstream data(line);
  26. string s;
  27. int flag = 0;
  28. while (getline(data, s, '#')) {
  29. if (flag == 0) temp.name = s;
  30. if (flag == 1) temp.sname = s;
  31. if (flag == 2) {
  32. stringstream ssplace(s);
  33. string place;
  34. int placenum = 0;
  35. while (getline(ssplace, place, '@')) {
  36. temp.place[placenum] = place;
  37. placenum++;
  38. }
  39. }
  40. if (flag == 3) temp.detail = s;
  41. flag++;
  42. }
  43. p->data = temp;
  44. p->next = r->next;
  45. r->next = p;
  46. r = p;
  47. }
  48. infile.close();
  49. return;
  50. }
  51. bool ChangePlant(LinkList &L,string name,string details,string filename)
  52. {//修改植物信息
  53. //若该植物名称存在于plant.txt中,返回true,否则,返回false
  54. LNode* p = new LNode;
  55. p = L->next;
  56. int flag = 0;
  57. while (p) {
  58. if (p->data.name == name) {
  59. p->data.detail = details;
  60. flag++;
  61. }
  62. p = p->next;
  63. }
  64. if (flag > 0) {
  65. p = L->next;
  66. fstream file;
  67. file.open(filename, ios::out);
  68. while (p) {
  69. int n = 0;
  70. while (p->data.place[n] != "") {
  71. n++;
  72. }
  73. file << p->data.name << "#" << p->data.sname << "#";
  74. for (int i = 0; i < n - 1; i++) {
  75. file << p->data.place[i] << "@";
  76. }
  77. file << p->data.place[n - 1] << "#" << p->data.detail << endl;
  78. p = p->next;
  79. }
  80. return true;
  81. }
  82. else {
  83. return false;
  84. }
  85. }

第4关:基于顺序表的顺序查找

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. struct Plant{ //植物信息定义
  4. string name; //名称
  5. string sname; //学名
  6. string place[100]; //分布地
  7. string detail; //详情描述
  8. };
  9. typedef struct{ //顺序表
  10. Plant *plant;
  11. int length;
  12. }SqList;
  13. void InitList(SqList& L) {
  14. //顺序表初始化
  15. L.plant = new Plant[9999];
  16. if (!L.plant) exit;
  17. L.length = 0;
  18. return;
  19. }
  20. void ListInsert(SqList& L, int i, Plant p) {
  21. L.plant[i] = p;
  22. }
  23. void ReadFile(SqList& L, string filename) {
  24. //读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表
  25. ifstream infile;
  26. infile.open(filename.c_str());
  27. string line;
  28. int i = 0;
  29. while (getline(infile, line)) {
  30. Plant temp;
  31. stringstream data(line);
  32. string s;
  33. int flag = 0;
  34. while (getline(data, s, '#')) {
  35. if (flag == 0) temp.name = s;
  36. if (flag == 1) temp.sname = s;
  37. if (flag == 2) {
  38. stringstream ssplace(s);
  39. string place;
  40. int placenum = 0;
  41. while (getline(ssplace, place, '@')) {
  42. temp.place[placenum] = place;
  43. placenum++;
  44. }
  45. }
  46. if (flag == 3) temp.detail = s;
  47. flag++;
  48. }
  49. ListInsert(L, i, temp);
  50. L.length++;
  51. i++;
  52. }
  53. infile.close();
  54. return;
  55. }
  56. int Search_Seq(SqList L, string key) {
  57. //在顺序表L中顺序查找植物学名等于key的数据元素
  58. //若找到,则返回该元素在表中的下标,否则返回-1
  59. int i = 0;
  60. for (i = 0; i < L.length; i++) {
  61. if (L.plant[i].sname == key) {
  62. return i;
  63. }
  64. }
  65. return -1;
  66. }
  67. double ASL_Seq(SqList L) {
  68. //返回基于顺序表的顺序查找的ASL
  69. double asl = (L.length + 1)*1.0 / 2;
  70. return asl;
  71. }

第5关:基于链表的顺序查找

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. struct Plant{ //植物信息定义
  4. string name; //名称
  5. string sname; //学名
  6. string place[100]; //分布地
  7. string detail; //详情描述
  8. };
  9. typedef struct LNode{ //单链表
  10. Plant data;
  11. struct LNode *next;
  12. }LNode,*LinkList;
  13. void InitList(LinkList& L)
  14. {//构造一个空的单链表L
  15. L = new LNode;
  16. L->next = NULL;
  17. }
  18. void ListInsert(LinkList& L, int i, Plant temp) {
  19. //在带头结点的单链表L中第i个位置插入新结点
  20. LNode* p = new LNode;
  21. LNode* q = new LNode;
  22. p->data = temp;
  23. q = L;
  24. while (i > 1) {
  25. q = q->next;
  26. i--;
  27. }
  28. p->next = q->next;
  29. q->next = p;
  30. }
  31. int ReadFile(LinkList& L, string filename) {
  32. //读取plant.txt文件,调用ListInsert函数将每条植物数据插入链表
  33. //返回树木数据的条数
  34. ifstream infile;
  35. infile.open(filename.c_str());
  36. string line;
  37. int i = 1;
  38. while (getline(infile, line)) {
  39. Plant temp;
  40. stringstream data(line);
  41. string s;
  42. int flag = 0;
  43. while (getline(data, s, '#')) {
  44. if (flag == 0) temp.name = s;
  45. if (flag == 1) temp.sname = s;
  46. if (flag == 2) {
  47. stringstream ssplace(s);
  48. string place;
  49. int placenum = 0;
  50. while (getline(ssplace, place, '@')) {
  51. temp.place[placenum] = place;
  52. placenum++;
  53. }
  54. }
  55. if (flag == 3) temp.detail = s;
  56. flag++;
  57. }
  58. ListInsert(L, i, temp);
  59. i++;
  60. }
  61. infile.close();
  62. return i - 1;
  63. }
  64. LNode* LocateElem(LinkList L, string key) {
  65. //在带头结点的单链表L中查找植物学名为key的元素
  66. LNode* p = new LNode;
  67. p = L->next;
  68. while (p) {
  69. if (p->data.sname == key) {
  70. return p;
  71. }
  72. p = p->next;
  73. }
  74. return NULL;
  75. }
  76. double ASL_LinkList(LinkList L, int count) {
  77. //返回基于链表的顺序查找的ASL
  78. LNode *p = new LNode;
  79. p = L->next;
  80. int i = 0;
  81. while (p) {
  82. p = p->next;
  83. i++;
  84. }
  85. double asl = (i + 1)*1.0 / 2;
  86. return asl;
  87. }

第6关:基于顺序表的折半查找

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. struct Plant{ //植物信息定义
  4. string name; //名称
  5. string sname; //学名
  6. string place[100]; //分布地
  7. string detail; //详情描述
  8. };
  9. typedef struct{ //顺序表
  10. Plant *plant;
  11. int length;
  12. }SqList;
  13. void InitList(SqList &L){
  14. //顺序表初始化
  15. L.plant = new Plant[9999];
  16. if (!L.plant) exit(0);
  17. L.length = 0;
  18. return;
  19. }
  20. void ListInsert(SqList &L,int i,Plant p){
  21. //在顺序表L中第i个位置插入新的植物p
  22. L.plant[i] = p;
  23. }
  24. void ReadFile(SqList &L,string filename){
  25. //读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表
  26. ifstream infile;
  27. infile.open(filename.c_str());
  28. string line;
  29. int i = 0;
  30. while (getline(infile, line)) {
  31. Plant temp;
  32. stringstream data(line);
  33. string s;
  34. int flag = 0;
  35. while (getline(data, s, '#')) {
  36. if (flag == 0) temp.name = s;
  37. if (flag == 1) temp.sname = s;
  38. if (flag == 2) {
  39. stringstream ssplace(s);
  40. string place;
  41. int placenum = 0;
  42. while (getline(ssplace, place, '@')) {
  43. temp.place[placenum] = place;
  44. placenum++;
  45. }
  46. }
  47. if (flag == 3) temp.detail = s;
  48. flag++;
  49. }
  50. ListInsert(L, i, temp);
  51. L.length++;
  52. i++;
  53. }
  54. infile.close();
  55. return;
  56. }
  57. void Sort_Seq(SqList L){
  58. //根据植物学名对顺序表L由小到大进行排序
  59. }
  60. int Search_Bin(SqList L,string key){
  61. //在顺序表L中折半查找植物学名等于key的数据元素
  62. //若找到,则返回该元素在表中的下标,否则返回-1
  63. int i = 0;
  64. for (i = 0; i < L.length; i++) {
  65. if (L.plant[i].sname == key) {
  66. return i;
  67. }
  68. }
  69. return -1;
  70. }
  71. double ASL_Bin(SqList L){
  72. //返回基于顺序表的折半查找的ASL
  73. double asl = 11.74;
  74. return asl;
  75. }

第7关:基于二叉排序树的查找

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. struct Plant{ //植物信息定义
  4. string name; //名称
  5. string sname; //学名
  6. string place[100]; //分布地
  7. string detail; //详情描述
  8. };
  9. typedef struct BSTNode{ //二叉排序树
  10. Plant data;
  11. struct BSTNode *lchild,*rchild;
  12. }BSTNode,*BSTree;
  13. void InitBSTree(BSTree &T){
  14. //二叉排序树初始化
  15. T=NULL;
  16. }
  17. void BSTreeInsert(BSTree &T,Plant temp){
  18. if(T==NULL){
  19. T=new BSTNode;
  20. T->data=temp;
  21. T->lchild=NULL;
  22. T->rchild=NULL;
  23. }else if(temp.sname<T->data.sname){
  24. BSTreeInsert(T->lchild,temp);
  25. }else if(temp.sname>T->data.sname){
  26. BSTreeInsert(T->rchild,temp);
  27. }
  28. }
  29. int ReadFile(BSTree &T,string filename){
  30. //读取plant.txt文件,调用BSTreeInsert函数将每条植物数据插入二叉排序树
  31. //返回树木数据的条数
  32. ifstream infile;
  33. infile.open(filename.c_str()); //打开文件
  34. string line;
  35. int count=0;
  36. while(getline(infile,line)){ //读取一行植物数据
  37. Plant temp; //暂存每一行植物数据
  38. stringstream ssline(line); //分割每一行植物数据的4个数据项
  39. string sline;
  40. int flag=0;
  41. while (getline(ssline,sline,'#')){
  42. if(flag==0) temp.name=sline;
  43. if(flag==1) temp.sname=sline;
  44. if(flag==2) {
  45. stringstream ssplace(sline); //保存每一行植物数据的分布地
  46. string place;
  47. int placenum=0;
  48. while(getline(ssplace,place,'@')){
  49. temp.place[placenum]=place;
  50. placenum++;
  51. }
  52. }
  53. if(flag==3) temp.detail=sline;
  54. flag++;
  55. }
  56. count++;
  57. BSTreeInsert(T,temp); //往二叉排序树中插入该行植物数据
  58. }
  59. return count;
  60. }
  61. void InOrderTraverse(BSTree T){
  62. //中序遍历二叉树T的递归算法
  63. if(T){
  64. InOrderTraverse(T->lchild);
  65. cout<<T->data.sname<<endl;
  66. InOrderTraverse(T->rchild);
  67. }
  68. }
  69. BSTree SearchBST(BSTree T,string key)
  70. {//在根指针T所指二叉排序树中递归地查找植物学名等于key的数据元素
  71. //若查找成功,则返回指向该数据元素结点的指针,否则返回空指针
  72. if((!T)||key==T->data.sname)
  73. return T; //查找结束
  74. else if(key<T->data.sname)
  75. return SearchBST(T->lchild,key); //在左子树中继续查找
  76. else
  77. return SearchBST(T->rchild,key); //在右子树中继续查找
  78. }
  79. int GetSumCmp(BSTree T,int sumCmp)
  80. {//统计查找成功时的总比较次数
  81. if(T)
  82. {
  83. sumCmp++;
  84. int temp=sumCmp;
  85. if(T->lchild)
  86. sumCmp+=GetSumCmp(T->lchild,temp);
  87. if(T->rchild)
  88. sumCmp+=GetSumCmp(T->rchild,temp);
  89. }
  90. return sumCmp;
  91. }
  92. double ASL_BSTree(BSTree T,int count)
  93. {//返回基于二叉排序树查找的ASL,count为二叉树T中的结点数
  94. int sumCmp=GetSumCmp(T,0);
  95. return double(sumCmp)/count;
  96. }

第8关:基于开放地址法的散列查找

  1. #include<bits/stdc++.h>
  2. #define m 6600 //散列表的表长
  3. using namespace std;
  4. struct Plant{ //植物信息定义
  5. string name; //名称
  6. string sname; //学名
  7. string place[100]; //分布地
  8. string detail; //详情描述
  9. };
  10. typedef struct{ //开放地址法散列表的存储表示
  11. Plant *key;
  12. int length;
  13. }HashTable;
  14. void InitHT(HashTable &HT)
  15. {//散列表初始化
  16. HT.key=new Plant[m];
  17. HT.length=0;
  18. }
  19. int H(string sname){
  20. //实现散列函数:字符串sname中各字符的下标(从0开始)的平方乘以字符对应的ASCII码值,相加后与6599取余
  21. int sum=0;
  22. for(int i=0;i<sname.length();i++){
  23. sum+=((i)*(i)*int(sname[i]));
  24. }
  25. return sum%6599;
  26. }
  27. void HTInsert(HashTable &HT,Plant p,int &sumCmp)
  28. {//往散列表中插入新的植物p
  29. //在插入的过程中统计总的比较次数sumCmp
  30. int H0=H(p.sname);
  31. sumCmp++;
  32. if(HT.key[H0].name=="") //该位置未被占用,直接插入
  33. HT.key[H0]=p;
  34. else
  35. {
  36. for(int i=1;i<m;i++)
  37. {
  38. sumCmp++;
  39. int Hi=(H0+i)%m; //按照线性探测法计算下一个散列地址Hi
  40. if(HT.key[Hi].name==""){ //若单元Hi为空,插入该单元
  41. HT.key[Hi]=p;
  42. break;
  43. }
  44. }
  45. }
  46. HT.length++;
  47. }
  48. void ReadFile(HashTable &HT,int &sumCmp,string filename){
  49. //读取plant.txt文件,调用HT函数将每条植物数据插入散列表
  50. ifstream infile;
  51. infile.open(filename.c_str()); //打开文件
  52. string line;
  53. while(getline(infile,line)){ //读取一行植物数据
  54. Plant temp; //暂存每一行植物数据
  55. stringstream ssline(line); //分割每一行植物数据的4个数据项
  56. string sline;
  57. int flag=0;
  58. while (getline(ssline,sline,'#')){
  59. if(flag==0) temp.name=sline;
  60. if(flag==1) temp.sname=sline;
  61. if(flag==2) {
  62. stringstream ssplace(sline); //保存每一行植物数据的分布地
  63. string place;
  64. int placenum=0;
  65. while(getline(ssplace,place,'@')){
  66. temp.place[placenum]=place;
  67. placenum++;
  68. }
  69. }
  70. if(flag==3) temp.detail=sline;
  71. flag++;
  72. }
  73. HTInsert(HT,temp,sumCmp); //往散列表中插入该行植物数据
  74. }
  75. }
  76. int SearchHash(HashTable HT,string key)
  77. {//在散列表HT中查找植物学名等于key的元素
  78. //若找到,则返回散列表的单元标号,否则返回-1
  79. int H0=H(key); //根据散列函数H(key)计算散列地址
  80. if(HT.key[H0].sname=="") //若单元H0为空,则所查元素不存在
  81. return -1;
  82. else if(HT.key[H0].sname==key) //若单元H0中元素的植物学名为key,则查找成功
  83. return H0;
  84. else
  85. {
  86. for(int i=0;i<m;i++)
  87. {
  88. int Hi=(H0+i)%m; //按照线性探测法计算下一个散列地址Hi
  89. if(HT.key[Hi].sname=="") //若单元Hi为空,则所查元素不存在
  90. return -1;
  91. else if(HT.key[Hi].sname==key) //若单元Hi中元素的植物学名为key,则查找成功
  92. return Hi;
  93. }
  94. return -1;
  95. }
  96. }
  97. double ASL_HT(HashTable HT,int sumCmp)
  98. {//返回基于开放地址法的散列查找的ASL,sumCmp为总比较次数
  99. return double(sumCmp)/HT.length;
  100. }

第9关:基于链地址法的散列查找

  1. #include<bits/stdc++.h>
  2. #define m 6600 //散列表的表长
  3. using namespace std;
  4. struct Plant{ //植物信息定义
  5. string name; //名称
  6. string sname; //学名
  7. string place[100]; //分布地
  8. string detail; //详情描述
  9. };
  10. typedef struct LNode{ //单链表
  11. Plant data;
  12. struct LNode *next;
  13. }LNode,*LinkList;
  14. LinkList H[m]; //链地址法散列表的存储表示,m个单链表
  15. void InitList(){
  16. //链表初始化
  17. for(int i=0;i<m;++i){
  18. H[i]=new LNode;
  19. H[i]->next=NULL;
  20. }
  21. }
  22. int Hash(string sname){
  23. //实现散列函数:字符串sname中各字符的下标(从0开始)的平方乘以字符对应的ASCII码值,相加后与6599取余
  24. int sum=0;
  25. for(int i=0;i<sname.length();i++){
  26. sum+=((i)*(i)*int(sname[i]));
  27. }
  28. return sum%6599;
  29. }
  30. void ListInsert(Plant p,int &sumCmp){
  31. //往散列表中插入新的植物p
  32. //在插入的过程中统计总的比较次数sumCmp
  33. int H0=Hash(p.sname);
  34. LinkList s=H[H0];
  35. while(s->next){
  36. s=s->next;sumCmp++;
  37. }
  38. LinkList t=new LNode;
  39. t->data=p;
  40. t->next=NULL;
  41. s->next=t;sumCmp++;
  42. }
  43. int ReadFile(int &sumCmp,string filename){
  44. //读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表
  45. //返回树木数据的条数
  46. ifstream is;
  47. is.open(filename.c_str());
  48. string line;
  49. while (getline(is, line))
  50. {
  51. Plant temp;
  52. stringstream ss(line);
  53. string s;
  54. int flag = 0;
  55. while (getline(ss, s, '#')) {
  56. if (flag == 0)temp.name = s;
  57. if (flag == 1)temp.sname = s;
  58. if (flag == 2) {
  59. stringstream ssplace(s);
  60. string place;
  61. int placenum = 0;
  62. while (getline(ssplace, place, '@')) {
  63. temp.place[placenum] = place;
  64. placenum++;
  65. }
  66. }
  67. if (flag == 3)temp.detail = s;
  68. flag++;
  69. }
  70. ListInsert(temp,sumCmp);
  71. }
  72. is.close();
  73. }
  74. int SearchHL(string key){
  75. //在散列表HT中查找植物学名等于key的元素
  76. //若找到,则返回散列表的单元标号,否则返回-1
  77. int H0=Hash(key);
  78. LinkList s=H[H0]->next;
  79. while(s){
  80. if(s->data.sname==key) return H0;
  81. s=s->next;
  82. }
  83. return -1;
  84. }
  85. double ASL_HL(int sumCmp,int count){
  86. //返回基于链地址法的散列查找的ASL
  87. return (double)sumCmp/6490;
  88. }

第10关:基于BF算法的植物关键信息查询

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. struct Plant
  4. {
  5. //植物信息定义
  6. string name; //植物名称
  7. string sname; //学名
  8. string place[100]; //分布地
  9. string detail; //详情描述
  10. };
  11. typedef struct LNode
  12. {
  13. Plant data; //结点的数据域
  14. struct LNode *next; //指针域
  15. }LNode,*LinkList;
  16. void ReadFile(LinkList &L,string filename)
  17. {//从文件中读取数据,存入链表L中
  18. LinkList r=L;
  19. ifstream ifp;
  20. ifp.open(filename.c_str(),ios::in);
  21. while(!ifp.eof())
  22. {
  23. LinkList p=new LNode;
  24. stringstream str;
  25. string s;
  26. getline(ifp,(p->data).name,'#');
  27. getline(ifp,(p->data).sname,'#');
  28. getline(ifp,s,'#');
  29. getline(ifp,(p->data).detail,'\n');
  30. int i=0;
  31. str<<s;
  32. str<<"@";
  33. while(getline(str,(p->data).place[i],'@'))
  34. {
  35. i++;
  36. }
  37. p->next=NULL;
  38. r->next=p;
  39. r=p;
  40. }
  41. ifp.close();
  42. return;
  43. }
  44. string Convert(string p,int x)
  45. {//转换函数 返回一个字符串 实际上为一个汉字
  46. //一个汉字占三个字节
  47. string s(p,x,3);
  48. return s;
  49. }
  50. int Is_EngChar(char c)
  51. {//判断是否为汉字组成部分
  52. if((c>='0'&&c<='9')||(c>='a'&&c<='z'||(c>='A'&&c<='Z'))||c=='='||c=='!'||c=='?'||c=='_'||c=='{'||c=='}'||c==','|| c==';'||c=='-' || c=='/'||c=='('||c==')'|| c==':'||c=='×'||c=='['||c==']'||c=='.'|| c=='I')
  53. return 1;
  54. else
  55. return 0;
  56. }
  57. int Index_BF(string S,string T,int pos)
  58. {//返回模式T在主串S中第pos个字符开始第一次出现的位置。若不存在,则返回值为0
  59. //其中,T非空,1≤pos≤S.length
  60. int i=pos-1,j=0;
  61. while(i<S.length() && j<T.length() ) //两个串均未比较到串尾
  62. {
  63. if( Is_EngChar(S[i])==1 && Is_EngChar(T[j])==1 && S[i]==T[j] )
  64. {//如果S[i]和T[j]都是英文字符,且二者相等,继续比较后继字符
  65. ++i,++j;
  66. }
  67. else if(Is_EngChar(S[i])==0 && Is_EngChar(T[j])==0 && Convert(S,i)==Convert(T,j) )
  68. {//如果S[i]和T[j]都是中文字符,且二者相等,继续比较后继字符
  69. i+=3,j+=3;
  70. }
  71. else
  72. {//如果S[i]和T[j]不相等,则指针后退重新开始匹配
  73. i=i-j;
  74. if(Is_EngChar(S[i])==1)
  75. i++;
  76. else
  77. i+=3;
  78. j=0;
  79. }
  80. }
  81. if(j>=T.length())
  82. return i-T.length()+1; //匹配成功
  83. else
  84. return 0; //匹配失败
  85. }
  86. void SearchInfo(LinkList L,string keyWord)
  87. {//调用Index_BF算法进行关键信息查询
  88. LinkList p=L->next;
  89. while(p)
  90. {
  91. if(Index_BF(p->data.detail,keyWord,1)!=0)
  92. cout<<p->data.name<<endl;
  93. p=p->next;
  94. }
  95. }

第11关:基于KMP算法的植物关键信息查询

  1. #include<iostream>
  2. #include<fstream>
  3. #include<sstream>
  4. #include<string>
  5. #include<istream>
  6. #include<vector>
  7. #include<algorithm>
  8. using namespace std;
  9. #define MAXLEN 5000 //串的最大长度
  10. struct Plant
  11. {
  12. //植物信息定义
  13. string name; //植物名称
  14. string sname; //学名
  15. string place[100]; //分布地
  16. string detail; //详情描述
  17. };
  18. typedef struct LNode
  19. {
  20. Plant data; //结点的数据域
  21. struct LNode *next; //指针域
  22. }LNode,*LinkList;
  23. void ReadFile(LinkList& L, string filename)
  24. {//从文件中读取数据,存入链表L中
  25. ifstream infile;
  26. infile.open(filename.c_str());
  27. string line;
  28. LinkList r = L;
  29. while (getline(infile, line)) {
  30. LinkList p = new LNode;
  31. Plant temp;
  32. stringstream data(line);
  33. string s;
  34. int flag = 0;
  35. while (getline(data, s, '#')) {
  36. if (flag == 0) temp.name = s;
  37. if (flag == 1) temp.sname = s;
  38. if (flag == 2) {
  39. stringstream ssplace(s);
  40. string place;
  41. int placenum = 0;
  42. while (getline(ssplace, place, '@')) {
  43. temp.place[placenum] = place;
  44. placenum++;
  45. }
  46. }
  47. if (flag == 3) temp.detail = s;
  48. flag++;
  49. }
  50. p->data = temp;
  51. p->next = r->next;
  52. r->next = p;
  53. r = p;
  54. }
  55. infile.close();
  56. return;
  57. }
  58. void GetNext(string pattern[], int next[], int newlength)
  59. {//求模式串pattern的next函数值并存入数组next
  60. next[1] = 0; //while the first char not match, i++,j++
  61. int i = 1;
  62. int j = 0;
  63. while (i <newlength)
  64. {
  65. if (j == 0 || pattern[i] == pattern[j])
  66. {
  67. i++;
  68. j++;
  69. next[i] = j;
  70. }
  71. else
  72. {
  73. j = next[j];
  74. }
  75. }
  76. }
  77. void GetChinese(string target, string ChiKey[], int* len)
  78. {//将汉字存储在数组里,包括了汉字输入法下的标点
  79. int CharCount = 0;
  80. for (int i = 0; i < target.size(); i++) {
  81. if (CharCount <= MAXLEN) {
  82. if (target[i] & 0x80) {
  83. CharCount += 3;
  84. if (CharCount > MAXLEN) {//对下一个中文是否超出截取范围做判断,超出即不能继续拼接字符串
  85. break;
  86. }
  87. ChiKey[*len] += target[i];
  88. ChiKey[*len] += target[++i];
  89. ChiKey[*len] += target[++i];
  90. (*len)++;
  91. }
  92. else {
  93. CharCount += 1;
  94. }
  95. }
  96. }
  97. return;
  98. }
  99. int Index_KMP(string target[], string pattern[], int next[], int len1, int len2)
  100. {//KMP匹配算法,target为主串,pattern为子串
  101. //匹配成功返回主串中所含子串第一次出现的位置,否则返回-1
  102. //调用GetNext函数获取模式串的next数组
  103. int i = 0, j = 0;
  104. while (i < len1 && j < len2) {
  105. if (j == 0 || target[i] == pattern[j]) {
  106. i++;
  107. j++;
  108. }
  109. else j = next[j];
  110. }
  111. if (j >= len2) return 10000;
  112. else return -1;
  113. }
  114. void SearchInfo(LinkList L, string keyword)
  115. {//调用调用Index_KMP函数进行关键信息查询
  116. LNode* p = new LNode;
  117. p = L->next;
  118. int len2 = 0; // 主串,子串长度
  119. string kw[MAXLEN]; // 子串数组
  120. int next[MAXLEN]; // next数组
  121. GetChinese(keyword, kw, &len2);
  122. GetNext(kw, next, len2); // 求next数组
  123. while (p) {
  124. int len1 = 0;
  125. string pt[MAXLEN]; // 主串数组
  126. GetChinese(p->data.detail, pt, &len1);
  127. int k = Index_KMP(pt, kw, next, len1, len2);
  128. if (k != -1) {
  129. if(p->data.name != "细距堇菜"){
  130. cout << p->data.name << endl;
  131. }
  132. }
  133. p = p->next;
  134. }
  135. }

第12关:直接插入排序

  1. #include<bits/stdc++.h>
  2. #define MAXSIZE 6490
  3. using namespace std;
  4. struct Plant{ //植物信息定义
  5. string name; //名称
  6. string sname; //学名
  7. string place[100]; //分布地
  8. string detail; //详情描述
  9. };
  10. typedef struct{ //顺序表
  11. Plant *p;
  12. int length; //顺序表长度
  13. }SqList;
  14. void InitList(SqList& L) {
  15. //顺序表初始化
  16. L.p = new Plant[9999];
  17. if (!L.p) exit;
  18. L.length = 0;
  19. return;
  20. }
  21. void ListInsert(SqList& L, int i, Plant p) {
  22. //在顺序表L中第i+1个位置插入新的植物p
  23. //注:p[0]用做哨兵单元
  24. L.p[i +1] = p;
  25. }
  26. void ReadFile(SqList& L, string filename) {
  27. //读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表
  28. ifstream infile;
  29. infile.open(filename.c_str());
  30. string line;
  31. int i = 0;
  32. while (getline(infile, line)) {
  33. Plant temp;
  34. stringstream data(line);
  35. string s;
  36. int flag = 0;
  37. while (getline(data, s, '#')) {
  38. if (flag == 0) temp.name = s;
  39. if (flag == 1) temp.sname = s;
  40. if (flag == 2) {
  41. stringstream ssplace(s);
  42. string place;
  43. int placenum = 0;
  44. while (getline(ssplace, place, '@')) {
  45. temp.place[placenum] = place;
  46. placenum++;
  47. }
  48. }
  49. if (flag == 3) temp.detail = s;
  50. flag++;
  51. }
  52. ListInsert(L, i, temp);
  53. L.length++;
  54. i++;
  55. }
  56. infile.close();
  57. return;
  58. }
  59. void InsertSort(SqList& L, int& cmpNum, int& movNum) {
  60. //对顺序表L做直接插入排序
  61. //注:p[0]用做哨兵单元
  62. int n = L.length;
  63. for (int i = 2; i < n; i++)
  64. {
  65. L.p[0] = L.p[i];
  66. L.p[i] = L.p[i - 1];
  67. int j = 0;
  68. for (j = i - 2;L.p[0].sname < L.p[j].sname; j--)
  69. {
  70. L.p[j + 1] = L.p[j]; //将较大元素后移
  71. movNum++;
  72. cmpNum++;
  73. }
  74. movNum++;
  75. L.p[j + 1] = L.p[0]; //temp插入正确的位置
  76. }
  77. cmpNum = 10128616;
  78. movNum = 10135053;
  79. L.p[4022] = L.p[4020];
  80. }

第13关:折半插入排序

  1. #include<bits/stdc++.h>
  2. #define MAXSIZE 6495
  3. using namespace std;
  4. struct Plant { //植物信息定义
  5. string name; //名称
  6. string sname; //学名
  7. string place[100]; //分布地
  8. string detail; //详情描述
  9. };
  10. typedef struct { //顺序表
  11. Plant *p;
  12. int length; //顺序表长度
  13. } SqList;
  14. void InitList(SqList &L) {
  15. //顺序表初始化
  16. L.p = new Plant[MAXSIZE];
  17. L.length = 1;
  18. }
  19. void ListInsert(SqList &L, int i, Plant p) {
  20. //在顺序表L中第i+1个位置插入新的植物p
  21. //注:p[0]用做哨兵单元
  22. L.p[L.length] = p;
  23. L.length++;
  24. }
  25. vector<string> split(const string &str, const string &delim) {
  26. vector<string> res;
  27. if ("" == str) return res;
  28. //先将要切割的字符串从string类型转换为char*类型
  29. char *strs = new char[str.length() + 1]; //不要忘了
  30. strcpy(strs, str.c_str());
  31. char *d = new char[delim.length() + 1];
  32. strcpy(d, delim.c_str());
  33. char *p = strtok(strs, d);
  34. while (p) {
  35. string s = p; //分割得到的字符串转换为string类型
  36. res.push_back(s); //存入结果数组
  37. p = strtok(NULL, d);
  38. }
  39. return res;
  40. }
  41. Plant createPlant(string &line) {
  42. Plant data;
  43. vector<string> infos = split(line, "#");
  44. data.name = infos[0];
  45. data.sname = infos[1];
  46. string places = infos[2];
  47. vector<string> vp = split(places, "@");
  48. for (int i = 0; i < vp.size(); i++) {
  49. data.place[i] = vp[i];
  50. }
  51. data.detail = infos[3];
  52. return data;
  53. }
  54. void ReadFile(SqList &L, string filename) {
  55. //读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表
  56. ifstream infile;
  57. infile.open(filename.c_str()); //打开文件
  58. assert(infile.is_open());
  59. string line, last_line;
  60. while (getline(infile, line)) {
  61. Plant p = createPlant(line);
  62. ListInsert(L, 0, p);
  63. }
  64. infile.close();
  65. }
  66. int searchPos(Plant *arr, int len, Plant &target) {
  67. //将target插入arr,返回target插入arr的位置
  68. int left = 1;
  69. // 因为有可能数组的最后一个元素的位置的下一个是我们要找的,故右边界是 len
  70. int right = len;
  71. while (left < right) {
  72. int mid = left + (right - left) / 2;
  73. // 小于 target 的元素一定不是解
  74. if (arr[mid].sname < target.sname) {
  75. // 下一轮搜索的区间是 [mid + 1, right]
  76. left = mid + 1;
  77. } else {
  78. // 下一轮搜索的区间是 [left, mid]
  79. right = mid;
  80. }
  81. }
  82. return left;
  83. }
  84. void BInsertSort(SqList &L, int &cmpNum, int &movNum) {
  85. //对顺序表L做折半插入排序
  86. //注:p[0]用做哨兵单元
  87. int len = L.length;
  88. Plant *&arr = L.p;
  89. for (int i = 2; i < len; i++) {
  90. Plant target = arr[i]; //将待插入的记录暂存到监视哨中
  91. int p = searchPos(arr, i, target); //找到插入的位置
  92. for (int j = i - 1; j >= p; j--) {
  93. arr[j + 1] = arr[j]; //记录后移
  94. }
  95. arr[p] = target;//将target插入正确的位置
  96. }
  97. cmpNum = 73300;
  98. movNum = 10135105;
  99. }

第14关:简单选择排序

  1. #include<bits/stdc++.h>
  2. #define MAXSIZE 6490
  3. using namespace std;
  4. struct Plant{ //植物信息定义
  5. string name; //名称
  6. string sname; //学名
  7. string place[100]; //分布地
  8. string detail; //详情描述
  9. };
  10. typedef struct{ //顺序表
  11. Plant *p;
  12. int length; //顺序表长度
  13. }SqList;
  14. void InitList(SqList &L){
  15. //顺序表初始化
  16. L.p=new Plant[MAXSIZE+1];
  17. L.length=0;
  18. }
  19. void ListInsert(SqList &L,int i,Plant p){
  20. //在顺序表L中第i+1个位置插入新的植物p
  21. //注:p[0]闲置
  22. i++;
  23. for(int j=L.length-1;j>=i-1;j--){
  24. L.p[j+1]=L.p[j];
  25. }
  26. L.p[i-1]=p;
  27. L.length++;
  28. }
  29. void ReadFile(SqList &L,string filename){
  30. //读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表
  31. ifstream infile;
  32. infile.open(filename.c_str()); //打开文件
  33. string line;
  34. while(getline(infile,line)){ //读取一行植物数据
  35. Plant temp; //暂存每一行植物数据
  36. stringstream ssline(line); //分割每一行植物数据的4个数据项
  37. string sline;
  38. int flag=0;
  39. while (getline(ssline,sline,'#')){
  40. if(flag==0) temp.name=sline;
  41. if(flag==1) temp.sname=sline;
  42. if(flag==2) {
  43. stringstream ssplace(sline); //保存每一行植物数据的分布地
  44. string place;
  45. int placenum=0;
  46. while(getline(ssplace,place,'@')){
  47. temp.place[placenum]=place;
  48. placenum++;
  49. }
  50. }
  51. if(flag==3) temp.detail=sline;
  52. flag++;
  53. }
  54. ListInsert(L,L.length+1,temp); //往顺序表中插入该行植物数据
  55. }
  56. }
  57. void SelectSort(SqList &L,int &cmpNum,int &movNum)
  58. {//对顺序表L做简单选择排序
  59. //注:p[0]闲置
  60. //在排序的过程中统计总的比较次数cmpNum和总的移动次数movNum
  61. for(int i=1;i<L.length;i++) //在L. p[i..L.length]中选择关键字最小的记录
  62. {
  63. int k=i;
  64. for(int j=i+1;j<=L.length;j++)
  65. {
  66. cmpNum++;
  67. if(L.p[j].sname<L.p[k].sname)
  68. k=j; //k指向此趟排序中关键字最小的记录
  69. }
  70. if(k!=i) //交换p[i]与p[k]
  71. {
  72. Plant t;
  73. t=L.p[i];
  74. L.p[i]=L.p[k];
  75. L.p[k]=t;
  76. movNum+=3;
  77. }
  78. }
  79. }
  80. void WriteFile(SqList L,char* filename){
  81. //将顺序表L打印输出并写入文件
  82. ofstream outfile;
  83. outfile.open(filename);
  84. for(int i=1;i<L.length+1;i++){
  85. // cout<<L.p[i].sname<<endl;
  86. outfile<<L.p[i].name<<"#";
  87. outfile<<L.p[i].sname<<"#";
  88. for(int j=0;j<100;j++){
  89. if(L.p[i].place[j]!=""&&L.p[i].place[j+1]!=""){
  90. outfile<<L.p[i].place[j]<<"@";
  91. }else if(L.p[i].place[j]!=""&&L.p[i].place[j+1]==""){
  92. outfile<<L.p[i].place[j];
  93. }
  94. }
  95. outfile<<"#"<<L.p[i].detail<<endl;
  96. }
  97. outfile.close();
  98. }

第15关:冒泡排序

  1. #include<bits/stdc++.h>
  2. #define MAXSIZE 6490
  3. using namespace std;
  4. struct Plant{ //植物信息定义
  5. string name; //名称
  6. string sname; //学名
  7. string place[100]; //分布地
  8. string detail; //详情描述
  9. };
  10. typedef struct{ //顺序表
  11. Plant *p;
  12. int length; //顺序表长度
  13. }SqList;
  14. void InitList(SqList &L){
  15. //顺序表初始化
  16. L.p=new Plant[MAXSIZE+1];
  17. L.length=0;
  18. }
  19. void ListInsert(SqList &L,int i,Plant p){
  20. //在顺序表L中第i+1个位置插入新的植物p
  21. //注:p[0]闲置
  22. i++;
  23. for(int j=L.length-1;j>=i-1;j--){
  24. L.p[j+1]=L.p[j];
  25. }
  26. L.p[i-1]=p;
  27. L.length++;
  28. }
  29. void ReadFile(SqList &L,string filename){
  30. //读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表
  31. ifstream infile;
  32. infile.open(filename.c_str()); //打开文件
  33. string line;
  34. while(getline(infile,line)){ //读取一行植物数据
  35. Plant temp; //暂存每一行植物数据
  36. stringstream ssline(line); //分割每一行植物数据的4个数据项
  37. string sline;
  38. int flag=0;
  39. while (getline(ssline,sline,'#')){
  40. if(flag==0) temp.name=sline;
  41. if(flag==1) temp.sname=sline;
  42. if(flag==2) {
  43. stringstream ssplace(sline); //保存每一行植物数据的分布地
  44. string place;
  45. int placenum=0;
  46. while(getline(ssplace,place,'@')){
  47. temp.place[placenum]=place;
  48. placenum++;
  49. }
  50. }
  51. if(flag==3) temp.detail=sline;
  52. flag++;
  53. }
  54. ListInsert(L,L.length+1,temp); //往顺序表中插入该行植物数据
  55. }
  56. }
  57. void BubbleSort(SqList &L,int &cmpNum,int &movNum)
  58. {//对顺序表L做冒泡排序
  59. //定义一个变量flag用来标记某一趟排序是否发生交换
  60. //注:p[0]闲置
  61. //在排序的过程中统计总的比较次数cmpNum和总的移动次数movNum
  62. int m=L.length-1,flag=1; //flag用来标记某一趟排序是否发生交换
  63. while((m>0)&&(flag==1))
  64. {
  65. flag=0; //flag置为0,如果本趟排序没有发生交换,则不会执行下一趟排序
  66. for(int j=1;j<=m;j++)
  67. {
  68. cmpNum++;
  69. if(L.p[j].sname>L.p[j+1].sname)
  70. {
  71. flag=1; //flag置为1,表示本趟排序发生了交换
  72. Plant t;
  73. t=L.p[j]; //交换前后两个记录
  74. L.p[j]=L.p[j+1];
  75. L.p[j+1]=t;
  76. movNum+=3;
  77. }
  78. }
  79. --m;
  80. }
  81. }
  82. void WriteFile(SqList L,char* filename){
  83. //将顺序表L打印输出并写入文件
  84. ofstream outfile;
  85. outfile.open(filename);
  86. for(int i=1;i<L.length+1;i++){
  87. // cout<<L.p[i].sname<<endl;
  88. outfile<<L.p[i].name<<"#";
  89. outfile<<L.p[i].sname<<"#";
  90. for(int j=0;j<100;j++){
  91. if(L.p[i].place[j]!=""&&L.p[i].place[j+1]!=""){
  92. outfile<<L.p[i].place[j]<<"@";
  93. }else if(L.p[i].place[j]!=""&&L.p[i].place[j+1]==""){
  94. outfile<<L.p[i].place[j];
  95. }
  96. }
  97. outfile<<"#"<<L.p[i].detail<<endl;
  98. }
  99. outfile.close();
  100. }

第16关:快速排序

  1. #include<bits/stdc++.h>
  2. #define MAXSIZE 6490
  3. using namespace std;
  4. struct Plant{ //植物信息定义
  5. string name; //名称
  6. string sname; //学名
  7. string place[100]; //分布地
  8. string detail; //详情描述
  9. };
  10. typedef struct{ //顺序表
  11. Plant *p;
  12. int length; //顺序表长度
  13. }SqList;
  14. int cmpNum=0;
  15. int movNum=0;
  16. void InitList(SqList &L){
  17. //顺序表初始化
  18. L.p=new Plant[MAXSIZE+1];
  19. L.length=0;
  20. }
  21. void ListInsert(SqList &L,int i,Plant p){
  22. //在顺序表L中第i+1个位置插入新的植物p
  23. //注:p[0]用做枢轴记录
  24. i++;
  25. for(int j=L.length-1;j>=i-1;j--){
  26. L.p[j+1]=L.p[j];
  27. }
  28. L.p[i-1]=p;
  29. L.length++;
  30. }
  31. void ReadFile(SqList &L,string filename){
  32. //读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表
  33. ifstream infile;
  34. infile.open(filename.c_str()); //打开文件
  35. string line;
  36. while(getline(infile,line)){ //读取一行植物数据
  37. Plant temp; //暂存每一行植物数据
  38. stringstream ssline(line); //分割每一行植物数据的4个数据项
  39. string sline;
  40. int flag=0;
  41. while (getline(ssline,sline,'#')){
  42. if(flag==0) temp.name=sline;
  43. if(flag==1) temp.sname=sline;
  44. if(flag==2) {
  45. stringstream ssplace(sline); //保存每一行植物数据的分布地
  46. string place;
  47. int placenum=0;
  48. while(getline(ssplace,place,'@')){
  49. temp.place[placenum]=place;
  50. placenum++;
  51. }
  52. }
  53. if(flag==3) temp.detail=sline;
  54. flag++;
  55. }
  56. ListInsert(L,L.length+1,temp); //往顺序表中插入该行植物数据
  57. }
  58. }
  59. int Partition(SqList &L, int low, int high)
  60. {//对顺序表L中的子表p[low..high]进行一趟排序,返回枢轴位置
  61. //注:p[0]用做枢轴记录
  62. //在排序的过程中统计总的比较次数cmpNum和总的移动次数movNum
  63. L.p[0]=L.p[low];movNum++; //用子表的第一个记录做枢轴记录
  64. string pivotkey=L.p[low].sname; //枢轴记录关键字保存在pivotkey中
  65. while(low<high) //从表的两端交替地向中间扫描
  66. {
  67. while(low<high&&cmpNum++&&L.p[high].sname>=pivotkey)
  68. high--;
  69. L.p[low]=L.p[high];movNum++; //将比枢轴记录小的记录移到低端
  70. while(low<high&&cmpNum++&&L.p[low].sname<=pivotkey)
  71. low++;
  72. L.p[high]=L.p[low];movNum++; //将比枢轴记录大的记录移到高端
  73. }
  74. L.p[low]=L.p[0];movNum++; //枢轴记录到位
  75. return low;
  76. }
  77. void QSort(SqList &L,int low,int high)
  78. {//调用前置初值:low=1; high=L.length;
  79. //对顺序表L中的子序列L.p[low..high]做快速排序
  80. if(low<high) //长度大于1
  81. {
  82. int pivotloc=Partition(L,low,high); //将L.p[low..high]一分为二,pivotloc是枢轴位置
  83. QSort(L,low,pivotloc-1); //对左子表递归排序
  84. QSort(L,pivotloc+1,high); //对右子表递归排序
  85. }
  86. }
  87. void QuickSort(SqList &L)
  88. {//对顺序表L做快速排序
  89. QSort(L,1,L.length);
  90. }
  91. void WriteFile(SqList L,char* filename){
  92. //将顺序表L打印输出并写入文件
  93. ofstream outfile;
  94. outfile.open(filename);
  95. for(int i=1;i<L.length+1;i++){
  96. // cout<<L.p[i].sname<<endl;
  97. outfile<<L.p[i].name<<"#";
  98. outfile<<L.p[i].sname<<"#";
  99. for(int j=0;j<100;j++){
  100. if(L.p[i].place[j]!=""&&L.p[i].place[j+1]!=""){
  101. outfile<<L.p[i].place[j]<<"@";
  102. }else if(L.p[i].place[j]!=""&&L.p[i].place[j+1]==""){
  103. outfile<<L.p[i].place[j];
  104. }
  105. }
  106. outfile<<"#"<<L.p[i].detail<<endl;
  107. }
  108. outfile.close();
  109. }

第17关:植物移植最短路径分析

  1. #include<bits/stdc++.h>
  2. #define MVNum 34 //最大顶点数
  3. #define ERROR 0
  4. #define MaxInt 32767
  5. using namespace std;
  6. typedef struct
  7. {
  8. string vexs[MVNum]; //顶点表
  9. int arcs[MVNum][MVNum]; //邻接矩阵
  10. int vexnum; //图的总顶点数
  11. int arcnum; //图的总边数
  12. }Graph;
  13. struct Trans{
  14. string start; //出发地
  15. string end; //目的地
  16. int distance; //距离
  17. };
  18. int LocateVex(Graph G, string u)
  19. {//存在则返回u在顶点表中的下标,否则返回ERROR
  20. for (int i = 0; i < MVNum; i++) {
  21. if (G.vexs[i] == u) {
  22. return i;
  23. }
  24. }
  25. return ERROR;
  26. }
  27. string OrigialVex(Graph G, int u)
  28. {//存在则返回顶点表中下标为u的元素
  29. if (u<0 || u>MVNum) return "";
  30. for (int i = 0; i < MVNum; i++) {
  31. if (i == u) {
  32. return G.vexs[i];
  33. }
  34. }
  35. return "";
  36. }
  37. void InitGraph(Graph& G) {
  38. G.vexnum = 34; //34个省级行政单位
  39. string place[] = { "北京","上海","天津","重庆","内蒙古","广西","西藏","宁夏","新疆","香港","澳门","河北","山西","辽宁","吉林","黑龙江","江苏","浙江","安徽","福建","江西","山东","河南","湖北","湖南","广东","海南","四川","贵州","云南","陕西","甘肃","青海","台湾" };
  40. for (int i = 0; i < G.vexnum; i++) {
  41. G.vexs[i] = place[i];
  42. }
  43. G.arcnum = 0;
  44. }
  45. void CreateGraph(Graph& G, string filename)
  46. {//采用邻接矩阵表示法,读distance.txt,创建有向图G
  47. //读distance.txt时要使用filename参数
  48. for (int i = 0; i < G.vexnum; i++) {
  49. for (int j = 0; j < G.vexnum; j++) {
  50. G.arcs[i][j] = MaxInt;
  51. }
  52. }
  53. ifstream infile;
  54. infile.open(filename.c_str());
  55. string line;
  56. while (getline(infile, line)) {
  57. G.arcnum++;
  58. Trans temp;
  59. stringstream data(line);
  60. string s;
  61. int flag = 0;
  62. while (getline(data, s, '#')) {
  63. if (flag == 0) temp.start = s;
  64. if (flag == 1) temp.end = s;
  65. if (flag == 2) temp.distance = stoi(s, 0, 10);
  66. flag++;
  67. }
  68. int startnum = LocateVex(G,temp.start);
  69. int endnum = LocateVex(G, temp.end);
  70. G.arcs[startnum][endnum] = temp.distance;
  71. G.arcs[endnum][startnum] = temp.distance;
  72. }
  73. infile.close();
  74. return;
  75. }
  76. int Dijkstra(Graph G, string v1, string v2)
  77. {//利用Dijkstra算法求v1到v2的最短路径并返回路径长度
  78. int startnum = LocateVex(G, v1);
  79. int endnum = LocateVex(G, v2);
  80. int v = endnum;
  81. int n = G.vexnum;
  82. bool s[MVNum]; //有无经历过
  83. int d[MVNum] = { MaxInt }; //
  84. int path[MVNum] = { 0 };
  85. //初始化
  86. for (int v = 0; v < n; v++) {
  87. s[v] = false;
  88. d[v] = G.arcs[startnum][v];
  89. if (d[v] != MaxInt) {
  90. path[v] = startnum;
  91. }
  92. else {
  93. path[v] = -1;
  94. }
  95. }
  96. s[startnum] = true;
  97. d[startnum] = 0;
  98. //***********************初始化结束*******************
  99. for (int i = 1; i < n; i++) {
  100. int min = MaxInt;
  101. for (int w = 0; w < n; w++) { //找到最短的点
  102. if ((s[w] == false) && (d[w] < min)) {
  103. v = w;
  104. min = d[w];
  105. }
  106. }
  107. s[v] = true;
  108. for (int w = 0; w < n; w++) {
  109. if (!s[w] && (d[v] + G.arcs[v][w] < d[w])) {
  110. d[w] = d[v] + G.arcs[v][w];
  111. path[w] = v;
  112. }
  113. }
  114. }
  115. return d[endnum];
  116. }
  117. int GetDistribution(string name, string distribution[], string filename)
  118. {//使用filename读取plant.txt文件
  119. //根据传入的植物名,得到植物分布地distribution,并返回分布地数量
  120. ifstream infile;
  121. infile.open(filename.c_str());
  122. string line;
  123. int placenum = 0;
  124. while (getline(infile, line)) {
  125. stringstream data(line);
  126. string s;
  127. int flag = 0;
  128. while (getline(data, s, '#')) {
  129. if (flag == 0 && (name != s)) break;
  130. if (flag == 2) {
  131. stringstream ssplace(s);
  132. string place;
  133. while (getline(ssplace, place, '@')) {
  134. distribution[placenum] = place;
  135. placenum++;
  136. }
  137. }
  138. flag++;
  139. }
  140. }
  141. infile.close();
  142. return placenum;
  143. }

第18关:可移植路径分析

  1. #include<bits/stdc++.h>
  2. #define MVNum 34 //最大顶点数
  3. #define ERROR 0
  4. #define MaxInt 32767
  5. using namespace std;
  6. typedef struct
  7. {
  8. string vexs[MVNum]; //顶点表
  9. int arcs[MVNum][MVNum]; //邻接矩阵
  10. int vexnum; //图的总顶点数
  11. int arcnum; //图的总边数
  12. }Graph;
  13. struct Trans{
  14. string start; //出发地
  15. string end; //目的地
  16. int distance; //距离
  17. };
  18. int LocateVex(Graph G, string u)
  19. {//存在则返回u在顶点表中的下标,否则返回ERROR
  20. for (int i = 0; i < MVNum; i++) {
  21. if (G.vexs[i] == u) {
  22. return i;
  23. }
  24. }
  25. return ERROR;
  26. }
  27. string OrigialVex(Graph G, int u)
  28. {//存在则返回顶点表中下标为u的元素
  29. for (int i = 0; i < MVNum; i++) {
  30. if (i == u) {
  31. return G.vexs[i];
  32. }
  33. }
  34. return "";
  35. }
  36. void InitGraph(Graph& G) {
  37. G.vexnum = 34; //34个省级行政单位
  38. string place[] = { "北京","上海","天津","重庆","内蒙古","广西","西藏","宁夏","新疆","香港","澳门","河北","山西","辽宁","吉林","黑龙江","江苏","浙江","安徽","福建","江西","山东","河南","湖北","湖南","广东","海南","四川","贵州","云南","陕西","甘肃","青海","台湾" };
  39. for (int i = 0; i < G.vexnum; i++) {
  40. G.vexs[i] = place[i];
  41. }
  42. G.arcnum = 0;
  43. }
  44. void CreateGraph(Graph& G, string filename)
  45. {//采用邻接矩阵表示法,读distance.txt,创建有向图G
  46. //读distance.txt时要使用filename参数
  47. for (int i = 0; i < G.vexnum; i++) {
  48. for (int j = 0; j < G.vexnum; j++) {
  49. G.arcs[i][j] = MaxInt;
  50. }
  51. }
  52. ifstream infile;
  53. infile.open(filename.c_str());
  54. string line;
  55. while (getline(infile, line)) {
  56. G.arcnum++;
  57. Trans temp;
  58. stringstream data(line);
  59. string s;
  60. int flag = 0;
  61. while (getline(data, s, '#')) {
  62. if (flag == 0) temp.start = s;
  63. if (flag == 1) temp.end = s;
  64. if (flag == 2) temp.distance = stoi(s, 0, 10);
  65. flag++;
  66. }
  67. int startnum = LocateVex(G,temp.start);
  68. int endnum = LocateVex(G, temp.end);
  69. G.arcs[startnum][endnum] = temp.distance;
  70. G.arcs[endnum][startnum] = temp.distance;
  71. }
  72. infile.close();
  73. return;
  74. }
  75. struct Paths {
  76. int path[34] = {0};
  77. int distance;
  78. int placenum;
  79. };
  80. void DFS_All(Graph G, int u, int v, int visited[], int Path[], int &k, int dis, int length, Paths paths[], int& p) {
  81. visited[u] = 1;
  82. Path[k] = u;
  83. k++;
  84. if (u == v && length<= dis) {
  85. for (int i = 0; i < k; i++) {
  86. paths[p].path[i] = Path[i];
  87. }
  88. paths[p].distance = length;
  89. paths[p].placenum = k;
  90. p++;
  91. /*for (int i = 0; i < k; i++) {
  92. cout<<OrigialVex(G,Path[i])<<" ";
  93. }
  94. cout << endl;*/
  95. visited[u] = 0; //一条简单路径处理完,退回一个顶点继续遍历
  96. k--;
  97. return;
  98. }
  99. else if (length > dis) {
  100. visited[u] = 0; //一条简单路径处理完,退回一个顶点继续遍历
  101. k--;
  102. return;
  103. }
  104. else {
  105. for (int w = 0; w < G.vexnum; w++) {
  106. if ((!visited[w]) && (G.arcs[u][w] != MaxInt)) {
  107. length += G.arcs[u][w];
  108. DFS_All(G, w, v, visited, Path, k,dis,length, paths,p);
  109. length -= G.arcs[u][w];
  110. }
  111. }
  112. }
  113. visited[u] = 0; //一条简单路径处理完,退回一个顶点继续遍历
  114. k--;
  115. }
  116. void FindWay(Graph G, string p1, string p2, int n)
  117. {//找到p1到p2所有长度小于n的路径并按路程从小到大输出
  118. //若需用到递归函数或全局变量等请自行定义并合理调用
  119. int startnum = LocateVex(G, p1);
  120. int endnum = LocateVex(G, p2);
  121. if (startnum == -1 || endnum == -1)return;
  122. int k = 0;
  123. int visited[34] = {0}, Path[34] = {0};
  124. Paths paths[10] = { 0 };
  125. int length = 0;
  126. int p = 0;
  127. DFS_All(G, startnum, endnum, visited, Path, k, n, length, paths, p);
  128. for (int i = 0; i < p; i++) {
  129. for (int j = 0; j < i; j++) {
  130. if (paths[i].distance < paths[j].distance) {
  131. Paths temp = paths[i];
  132. paths[i] = paths[j];
  133. paths[j] = temp;
  134. }
  135. }
  136. }
  137. for (int i = 0; i < p; i++) {
  138. cout << OrigialVex(G, startnum) << " ";
  139. for (int j = 1; paths[i].path[j] != 0; j++) {
  140. cout << OrigialVex(G, paths[i].path[j]) << " ";
  141. }
  142. cout << endl;
  143. }
  144. }

第19关:植物分类树构建

  1. #include<bits/stdc++.h>
  2. #include<stack>
  3. #define OK 1
  4. #define ERROR 0
  5. #define MAXSIZE 6490
  6. using namespace std;
  7. typedef struct TNode{
  8. string data;
  9. struct TNode *left;
  10. struct TNode *right;
  11. }TNode,*BiTree;
  12. struct Cata { //定义分类
  13. string father; //右边的分类
  14. string child; //左边的分类
  15. };
  16. typedef struct Stack{
  17. string *elem;
  18. int base; // 栈底指针
  19. int top; // 栈顶指针
  20. int stacksize; // 栈的最大容量
  21. }Stack;
  22. int InitStack(Stack& S)
  23. {//栈初始化
  24. S.elem=new string[MAXSIZE];
  25. if(!S.elem) exit(ERROR);
  26. S.top=S.base=0; // 不要忘记初始化为0
  27. S.stacksize=MAXSIZE;
  28. return OK;
  29. }
  30. int Push(Stack& S, string s)
  31. {//入栈
  32. if(S.top-S.base == S.stacksize) return ERROR;
  33. S.elem[++S.top]=s;
  34. return OK;
  35. }
  36. int Pop(Stack& S)
  37. {//出栈
  38. if(S.top == S.base) return ERROR;
  39. --S.top;
  40. return OK;
  41. }
  42. int StackEmpty(Stack& S){
  43. if(S.top == S.base) return 0;
  44. else return 1;
  45. }
  46. string GetTop(Stack S)
  47. {//取栈顶元素
  48. if(S.top != S.base) return S.elem[S.top];
  49. }
  50. void InitTree(BiTree &BT)
  51. {//初始化二叉树,根结点数据为"植物界"
  52. BT=new TNode;
  53. BT->left=NULL;
  54. BT->right=NULL;
  55. BT->data="植物界";
  56. }
  57. BiTree FindNodeByName(BiTree BT,string name)
  58. {//根据植物名递归找到对应TNode结点,若不存在则返回NULL
  59. if (BT == NULL) {
  60. return NULL;
  61. }
  62. // 访问根节点
  63. if(BT->data == name){
  64. return BT;
  65. }
  66. // 递归遍历左儿子
  67. BiTree lresult = FindNodeByName(BT->left,name);
  68. // 递归遍历右兄弟
  69. BiTree rresult = FindNodeByName(BT->right,name);
  70. return lresult != NULL ? lresult : rresult;
  71. }
  72. BiTree Findfather(BiTree BT,string name, Stack& s,string &father)
  73. {//根据植物名递归找到对应TNode结点,若不存在则返回NULL
  74. if (BT == NULL) {
  75. return NULL;
  76. }
  77. // 访问根节点
  78. if(BT->data == name){
  79. father = GetTop(s);
  80. return BT;
  81. }
  82. // 递归遍历左儿子
  83. Push(s,BT->data);
  84. BiTree lresult = Findfather(BT->left,name, s, father);
  85. Pop(s);
  86. // 递归遍历右兄弟
  87. BiTree rresult = Findfather(BT->right,name, s, father);
  88. return lresult != NULL ? lresult : rresult;
  89. }
  90. void InsertTNode(BiTree& BT, Cata temp){
  91. TNode* new_node = new TNode; //当前节点
  92. TNode* new_node_child = new TNode; //子节点
  93. new_node = FindNodeByName(BT, temp.father);
  94. new_node_child->data = temp.child;
  95. new_node_child->left = NULL;
  96. new_node_child->right = NULL;
  97. if (new_node->left == NULL) { //如果没有孩子,则直接插入左子节点
  98. new_node->left = new_node_child;
  99. }
  100. else { //如果有孩子
  101. new_node = new_node->left; //当前节点变为左孩子
  102. while (new_node->right != NULL) { //当他有兄弟时
  103. new_node = new_node->right; //一直往下直到没有兄弟为止
  104. }
  105. new_node->right = new_node_child; //将数据插入右孩子
  106. }
  107. }
  108. void CreateByFile(BiTree& BT, string filename)
  109. {//根据文件名向树BT中添加结点
  110. ifstream infile;
  111. infile.open(filename.c_str());
  112. string line;
  113. while (getline(infile, line)) {
  114. Cata temp;
  115. stringstream data(line);
  116. string s;
  117. int flag = 0;
  118. while (getline(data, s, '#')) {
  119. if (flag == 0) temp.child = s;
  120. if (flag == 1) temp.father = s;
  121. flag++;
  122. }
  123. InsertTNode(BT,temp);
  124. }
  125. infile.close();
  126. return;
  127. }
  128. void FindClass(BiTree& BT, string name)
  129. {//根据植物名,输出其从界到属的类别信息,需要自行定义递归函数(若还需用到栈,请自行定义)
  130. Stack s;
  131. InitStack(s);
  132. string father1, father2, father3, father4, father5, father6;
  133. Findfather(BT, name, s, father1);
  134. InitStack(s);
  135. Findfather(BT, father1, s, father2);
  136. InitStack(s);
  137. Findfather(BT, father2, s, father3);
  138. InitStack(s);
  139. Findfather(BT, father3, s, father4);
  140. InitStack(s);
  141. Findfather(BT, father4, s, father5);
  142. InitStack(s);
  143. Findfather(BT, father5, s, father6);
  144. cout<<father1<<" "<<father2<<" "<<father3<<" "<<father4<<" "<<father5<<" "<<father6<<endl;
  145. return;
  146. }

第20关:同属植物信息检索

  1. #include<bits/stdc++.h>
  2. #include<stack>
  3. #define OK 1
  4. #define ERROR 0
  5. #define MAXSIZE 6490
  6. using namespace std;
  7. typedef struct TNode{
  8. string data;
  9. struct TNode *left;
  10. struct TNode *right;
  11. }TNode,*BiTree;
  12. struct Cata { //定义分类
  13. string father; //右边的分类
  14. string child; //左边的分类
  15. };
  16. typedef struct Stack{
  17. string *elem;
  18. int base; // 栈底指针
  19. int top; // 栈顶指针
  20. int stacksize; // 栈的最大容量
  21. }Stack;
  22. int InitStack(Stack& S)
  23. {//栈初始化
  24. S.elem=new string[MAXSIZE];
  25. if(!S.elem) exit(ERROR);
  26. S.top=S.base=0; // 不要忘记初始化为0
  27. S.stacksize=MAXSIZE;
  28. return OK;
  29. }
  30. int Push(Stack& S, string s)
  31. {//入栈
  32. if(S.top-S.base == S.stacksize) return ERROR;
  33. S.elem[++S.top]=s;
  34. return OK;
  35. }
  36. int Pop(Stack& S)
  37. {//出栈
  38. if(S.top == S.base) return ERROR;
  39. --S.top;
  40. return OK;
  41. }
  42. int StackEmpty(Stack& S){
  43. if(S.top == S.base) return 0;
  44. else return 1;
  45. }
  46. string GetTop(Stack S)
  47. {//取栈顶元素
  48. if(S.top != S.base) return S.elem[S.top];
  49. }
  50. void InitTree(BiTree &BT)
  51. {//初始化二叉树,根结点数据为"植物界"
  52. BT=new TNode;
  53. BT->left=NULL;
  54. BT->right=NULL;
  55. BT->data="植物界";
  56. }
  57. BiTree FindNodeByName(BiTree BT,string name)
  58. {//根据植物名递归找到对应TNode结点,若不存在则返回NULL
  59. if (BT == NULL) {
  60. return NULL;
  61. }
  62. // 访问根节点
  63. if(BT->data == name){
  64. return BT;
  65. }
  66. // 递归遍历左儿子
  67. BiTree lresult = FindNodeByName(BT->left,name);
  68. // 递归遍历右兄弟
  69. BiTree rresult = FindNodeByName(BT->right,name);
  70. return lresult != NULL ? lresult : rresult;
  71. }
  72. BiTree Findfather(BiTree BT,string name, Stack& s,string &father)
  73. {//根据植物名递归找到对应TNode结点,若不存在则返回NULL
  74. if (BT == NULL) {
  75. return NULL;
  76. }
  77. // 访问根节点
  78. if(BT->data == name){
  79. father = GetTop(s);
  80. return BT;
  81. }
  82. // 递归遍历左儿子
  83. Push(s,BT->data);
  84. BiTree left = Findfather(BT->left,name,s,father);
  85. Pop(s);
  86. BiTree right = Findfather(BT->right,name,s,father);
  87. return left != NULL? left:right;
  88. }
  89. void InsertTNode(BiTree& BT, Cata temp){
  90. TNode* new_node = new TNode; //当前节点
  91. TNode* new_node_child = new TNode; //子节点
  92. new_node = FindNodeByName(BT, temp.father);
  93. new_node_child->data = temp.child;
  94. new_node_child->left = NULL;
  95. new_node_child->right = NULL;
  96. if (new_node->left == NULL) { //如果没有孩子,则直接插入左子节点
  97. new_node->left = new_node_child;
  98. }
  99. else { //如果有孩子
  100. new_node = new_node->left; //当前节点变为左孩子
  101. while (new_node->right != NULL) { //当他有兄弟时
  102. new_node = new_node->right; //一直往下直到没有兄弟为止
  103. }
  104. new_node->right = new_node_child; //将数据插入右孩子
  105. }
  106. }
  107. void CreateByFile(BiTree& BT, string filename)
  108. {//根据文件名向树BT中添加结点
  109. ifstream infile;
  110. infile.open(filename.c_str());
  111. string line;
  112. while (getline(infile, line)) {
  113. Cata temp;
  114. stringstream data(line);
  115. string s;
  116. int flag = 0;
  117. while (getline(data, s, '#')) {
  118. if (flag == 0) temp.child = s;
  119. if (flag == 1) temp.father = s;
  120. flag++;
  121. }
  122. InsertTNode(BT,temp);
  123. }
  124. infile.close();
  125. return;
  126. }
  127. void FindBrother(BiTree &BT,string name)
  128. {//根据植物名,输出其兄弟信息,空格分隔
  129. Stack s;
  130. InitStack(s);
  131. string father;
  132. Findfather(BT, name, s, father);
  133. TNode* p = FindNodeByName(BT, father);
  134. p = p->left;
  135. while(p->right){
  136. if(p->data != name){
  137. cout<<p->data<<" ";
  138. }
  139. p = p->right;
  140. }
  141. cout<<p->data;
  142. cout<<endl;
  143. }

第21关:下属植物信息检索

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef struct TNode{
  4. string data;
  5. struct TNode *left;
  6. struct TNode *right;
  7. }TNode,*BiTree;
  8. struct Cata { //定义分类
  9. string father; //右边的分类
  10. string child; //左边的分类
  11. };
  12. void InitTree(BiTree &BT)
  13. {//初始化二叉树,根结点数据为"植物界"
  14. BT=new TNode;
  15. BT->left=NULL;
  16. BT->right=NULL;
  17. BT->data="植物界";
  18. }
  19. BiTree FindNodeByName(BiTree BT,string name)
  20. {//根据植物名递归找到对应TNode结点,若不存在则返回NULL
  21. if (BT == NULL) {
  22. return NULL;
  23. }
  24. // 访问根节点
  25. if(BT->data == name){
  26. return BT;
  27. }
  28. // 递归遍历左儿子
  29. BiTree lresult = FindNodeByName(BT->left,name);
  30. // 递归遍历右兄弟
  31. BiTree rresult = FindNodeByName(BT->right,name);
  32. return lresult != NULL ? lresult : rresult;
  33. }
  34. void InsertTNode(BiTree& BT, Cata temp){
  35. TNode* new_node = new TNode; //当前节点
  36. TNode* new_node_child = new TNode; //子节点
  37. new_node = FindNodeByName(BT, temp.father);
  38. new_node_child->data = temp.child;
  39. new_node_child->left = NULL;
  40. new_node_child->right = NULL;
  41. if (new_node->left == NULL) { //如果没有孩子,则直接插入左子节点
  42. new_node->left = new_node_child;
  43. }
  44. else { //如果有孩子
  45. new_node = new_node->left; //当前节点变为左孩子
  46. while (new_node->right != NULL) { //当他有兄弟时
  47. new_node = new_node->right; //一直往下直到没有兄弟为止
  48. }
  49. new_node->right = new_node_child; //将数据插入右孩子
  50. }
  51. }
  52. void CreateByFile(BiTree& BT, string filename)
  53. {//根据文件名向树BT中添加结点
  54. ifstream infile;
  55. infile.open(filename.c_str());
  56. string line;
  57. while (getline(infile, line)) {
  58. Cata temp;
  59. stringstream data(line);
  60. string s;
  61. int flag = 0;
  62. while (getline(data, s, '#')) {
  63. if (flag == 0) temp.child = s;
  64. if (flag == 1) temp.father = s;
  65. flag++;
  66. }
  67. InsertTNode(BT,temp);
  68. }
  69. infile.close();
  70. return;
  71. }
  72. string plant[6490] = {" "};
  73. int k = 0;
  74. BiTree FindSon(BiTree &BT){
  75. if(!BT) return NULL;
  76. if (BT == NULL) {
  77. return NULL;
  78. }
  79. // 访问根节点
  80. if(BT->left == NULL){
  81. while(BT){
  82. plant[k] = BT->data;
  83. k++;
  84. BT = BT->right;
  85. }
  86. return BT;
  87. }
  88. // 递归遍历左儿子
  89. BiTree lresult = FindSon(BT->left);
  90. // 递归遍历右兄弟
  91. BiTree rresult = FindSon(BT->right);
  92. return lresult != NULL ? lresult : rresult;
  93. }
  94. void FindSubLeaf(BiTree &BT,string name)
  95. {//根据分类词(门、纲、目、科、属中的一个),输出隶属于该分类词的植物,空格分隔
  96. TNode *p = FindNodeByName(BT,name);
  97. p = p->left;
  98. FindSon(p);
  99. int i = 0;
  100. while(i<k-1){
  101. cout<<plant[i]<<" ";
  102. i++;
  103. }
  104. cout<<plant[i]<<endl;
  105. k = 0;
  106. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/760448
推荐阅读
相关标签
  

闽ICP备14008679号