当前位置:首页 » 《休闲阅读》 » 正文

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

14 人参与  2024年04月22日 18:00  分类 : 《休闲阅读》  评论

点击全文阅读


目录

第1关:增加植物信息

第2关:删除植物信息

第3关:修改植物信息

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

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

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

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

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

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

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

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

第12关:直接插入排序

第13关:折半插入排序

第14关:简单选择排序

第15关:冒泡排序

第16关:快速排序

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

第18关:可移植路径分析

第19关:植物分类树构建

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

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


第1关:增加植物信息

#include<bits/stdc++.h>using namespace std;struct Plant{//植物信息定义string name;//植物名称string sname;//学名string place[100];//分布地string detail;//详情描述};typedef struct LNode{    Plant data;       //结点的数据域    struct LNode *next; //指针域}LNode,*LinkList;void ReadFile(LinkList& L, string filename){//从文件中读取数据,存入链表L中ifstream infile("data_edit/plant.txt");string line;LinkList r = L;while (getline(infile, line)) {LinkList p = new LNode;Plant temp;stringstream data(line);string s;int flag = 0;while (getline(data, s, '#')) {if (flag == 0) temp.name = s;if (flag == 1) temp.sname = s;if (flag == 2) {stringstream ssplace(s);string place;int placenum = 0;while (getline(ssplace, place, '@')) {temp.place[placenum] = place;placenum++;}}if (flag == 3) temp.detail = s;flag++;}p->data = temp;p->next = r->next;r->next = p;r = p;}infile.close();return;}int InPlant(LinkList L,string name){//判断该植物名称name是否存在于链表中LNode* p = new LNode;p = L->next;int flag = 0;while (p) {if (p->data.name == name) {flag++;}p = p->next;}if (flag > 0) {return true;}else {return false;}}bool InsertPlant(LinkList &L, string filename){//增加植物信息,输入植物的名称、学名、分布地和详情描述信息,将该植物的基本信息添加到plant.txt中的最后 //如果该植物名称存在于plant.txt中,返回false,否则,返回trueint n = 0;string name, sname, place[100], detail;cin >> name;getchar();getline(cin, sname);cin>> n;for (int i = 0; i < n; i++) {cin >> place[i];}cin >> detail;if (InPlant(L, name)) {return false;}else {fstream file;file.open(filename, ios::out | ios::app);file << name << "#" << sname << "#";for (int i = 0; i < n-1; i++) {file<< place[i]<<"@";}file << place[n - 1] << "#" << detail << endl;}}

第2关:删除植物信息

#include<bits/stdc++.h>using namespace std;struct Plant{//植物信息定义 string name;//植物名称 string sname;//学名string place[100];//分布地 string detail;//详情描述 };typedef struct LNode{    Plant data;       //结点的数据域       struct LNode *next; //指针域}LNode,*LinkList;void ReadFile(LinkList& L, string filename){//从文件中读取数据,存入链表L中ifstream infile;infile.open(filename.c_str());string line;LinkList r = L;while (getline(infile, line)) {LinkList p = new LNode;Plant temp;stringstream data(line);string s;int flag = 0;while (getline(data, s, '#')) {if (flag == 0) temp.name = s;if (flag == 1) temp.sname = s;if (flag == 2) {stringstream ssplace(s);string place;int placenum = 0;while (getline(ssplace, place, '@')) {temp.place[placenum] = place;placenum++;}}if (flag == 3) temp.detail = s;flag++;}p->data = temp;p->next = r->next;r->next = p;r = p;}infile.close();return;}void DeletePlant(LinkList &L,string name,string filename){//删除指定植物信息LNode* p = new LNode;p = L;while (p->next) {if (p->next->data.name == name) {LNode* q = new LNode;q = p->next;p->next = q->next;delete(q);}else {p = p->next;}}p = L->next;fstream file;file.open(filename, ios::out);while (p) {int n = 0;while (p->data.place[n]!="") {n++;}file << p->data.name << "#" << p->data.sname << "#";for (int i = 0; i < n - 1; i++) {file << p->data.place[i] << "@";}file << p->data.place[n - 1] << "#" << p->data.detail << endl;p = p->next;}file.close();}

第3关:修改植物信息

#include<bits/stdc++.h>using namespace std;struct Plant{//植物信息定义 string name;//植物名称 string sname;//学名string place[100];//分布地 string detail;//详情描述 };typedef struct LNode{    Plant data;       //结点的数据域       struct LNode *next; //指针域}LNode,*LinkList;void ReadFile(LinkList& L, string filename){//从文件中读取数据,存入链表L中ifstream infile;infile.open(filename.c_str());string line;LinkList r = L;while (getline(infile, line)) {LinkList p = new LNode;Plant temp;stringstream data(line);string s;int flag = 0;while (getline(data, s, '#')) {if (flag == 0) temp.name = s;if (flag == 1) temp.sname = s;if (flag == 2) {stringstream ssplace(s);string place;int placenum = 0;while (getline(ssplace, place, '@')) {temp.place[placenum] = place;placenum++;}}if (flag == 3) temp.detail = s;flag++;}p->data = temp;p->next = r->next;r->next = p;r = p;}infile.close();return;}bool ChangePlant(LinkList &L,string name,string details,string filename){//修改植物信息 //若该植物名称存在于plant.txt中,返回true,否则,返回falseLNode* p = new LNode;p = L->next;int flag = 0;while (p) {if (p->data.name == name) {p->data.detail = details;flag++;}p = p->next;}if (flag > 0) {p = L->next;fstream file;file.open(filename, ios::out);while (p) {int n = 0;while (p->data.place[n] != "") {n++;}file << p->data.name << "#" << p->data.sname << "#";for (int i = 0; i < n - 1; i++) {file << p->data.place[i] << "@";}file << p->data.place[n - 1] << "#" << p->data.detail << endl;p = p->next;}return true;}else {return false;}}

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

#include<bits/stdc++.h>using namespace std;struct Plant{//植物信息定义 string name;//名称 string sname;//学名string place[100];//分布地 string detail;//详情描述 };typedef struct{            //顺序表Plant *plant;int length; }SqList;void InitList(SqList& L) {//顺序表初始化 L.plant = new Plant[9999];if (!L.plant) exit;L.length = 0;return;}void ListInsert(SqList& L, int i, Plant p) {L.plant[i] = p;}void ReadFile(SqList& L, string filename) {//读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表 ifstream infile;infile.open(filename.c_str());string line;int i = 0;while (getline(infile, line)) {Plant temp;stringstream data(line);string s;int flag = 0;while (getline(data, s, '#')) {if (flag == 0) temp.name = s;if (flag == 1) temp.sname = s;if (flag == 2) {stringstream ssplace(s);string place;int placenum = 0;while (getline(ssplace, place, '@')) {temp.place[placenum] = place;placenum++;}}if (flag == 3) temp.detail = s;flag++;}ListInsert(L, i, temp);L.length++;i++;}infile.close();return;}int Search_Seq(SqList L, string key) {//在顺序表L中顺序查找植物学名等于key的数据元素//若找到,则返回该元素在表中的下标,否则返回-1int i = 0;for (i = 0; i < L.length; i++) {if (L.plant[i].sname == key) {return i;}}return -1;}double ASL_Seq(SqList L) {//返回基于顺序表的顺序查找的ASL double asl = (L.length + 1)*1.0 / 2;return asl;}

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

#include<bits/stdc++.h>using namespace std;struct Plant{//植物信息定义 string name;//名称 string sname;//学名string place[100];//分布地 string detail;//详情描述 };typedef struct LNode{          //单链表 Plant data;struct LNode *next;}LNode,*LinkList; void InitList(LinkList& L){//构造一个空的单链表LL = new LNode;L->next = NULL;}void ListInsert(LinkList& L, int i, Plant temp) {//在带头结点的单链表L中第i个位置插入新结点LNode* p = new LNode;LNode* q = new LNode;p->data = temp;q = L;while (i > 1) {q = q->next;i--;}p->next = q->next;q->next = p;}int ReadFile(LinkList& L, string filename) {//读取plant.txt文件,调用ListInsert函数将每条植物数据插入链表//返回树木数据的条数 ifstream infile;infile.open(filename.c_str());string line;int i = 1;while (getline(infile, line)) {Plant temp;stringstream data(line);string s;int flag = 0;while (getline(data, s, '#')) {if (flag == 0) temp.name = s;if (flag == 1) temp.sname = s;if (flag == 2) {stringstream ssplace(s);string place;int placenum = 0;while (getline(ssplace, place, '@')) {temp.place[placenum] = place;placenum++;}}if (flag == 3) temp.detail = s;flag++;}ListInsert(L, i, temp);i++;}infile.close();return i - 1;}LNode* LocateElem(LinkList L, string key) {//在带头结点的单链表L中查找植物学名为key的元素 LNode* p = new LNode;p = L->next;while (p) {if (p->data.sname == key) {return p;}p = p->next;}return NULL;}double ASL_LinkList(LinkList L, int count) {//返回基于链表的顺序查找的ASL LNode *p = new LNode;p = L->next;int i = 0;while (p) {p = p->next;i++;}double asl = (i + 1)*1.0 / 2;return asl;}

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

#include<bits/stdc++.h>using namespace std;struct Plant{//植物信息定义 string name;//名称 string sname;//学名string place[100];//分布地 string detail;//详情描述 };typedef struct{            //顺序表Plant *plant;int length; }SqList;void InitList(SqList &L){   //顺序表初始化 L.plant = new Plant[9999];if (!L.plant) exit(0);L.length = 0;return;}void ListInsert(SqList &L,int i,Plant p){//在顺序表L中第i个位置插入新的植物p L.plant[i] = p;}void ReadFile(SqList &L,string filename){//读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表     ifstream infile;infile.open(filename.c_str());string line;int i = 0;while (getline(infile, line)) {Plant temp;stringstream data(line);string s;int flag = 0;while (getline(data, s, '#')) {if (flag == 0) temp.name = s;if (flag == 1) temp.sname = s;if (flag == 2) {stringstream ssplace(s);string place;int placenum = 0;while (getline(ssplace, place, '@')) {temp.place[placenum] = place;placenum++;}}if (flag == 3) temp.detail = s;flag++;}ListInsert(L, i, temp);L.length++;i++;}infile.close();return;}void Sort_Seq(SqList L){//根据植物学名对顺序表L由小到大进行排序 }int Search_Bin(SqList L,string key){//在顺序表L中折半查找植物学名等于key的数据元素//若找到,则返回该元素在表中的下标,否则返回-1 int i = 0;for (i = 0; i < L.length; i++) {if (L.plant[i].sname == key) {return i;}}return -1;}double ASL_Bin(SqList L){//返回基于顺序表的折半查找的ASL double asl = 11.74;return asl;} 

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

#include<bits/stdc++.h>using namespace std;struct Plant{                                            //植物信息定义     string name;                                        //名称     string sname;                                        //学名    string place[100];                                    //分布地     string detail;                                        //详情描述 };typedef struct BSTNode{                                    //二叉排序树    Plant data;   struct BSTNode *lchild,*rchild;}BSTNode,*BSTree;void InitBSTree(BSTree &T){                                   //二叉排序树初始化     T=NULL;}void BSTreeInsert(BSTree &T,Plant temp){    if(T==NULL){        T=new BSTNode;        T->data=temp;        T->lchild=NULL;        T->rchild=NULL;    }else if(temp.sname<T->data.sname){        BSTreeInsert(T->lchild,temp);    }else if(temp.sname>T->data.sname){        BSTreeInsert(T->rchild,temp);    }}int ReadFile(BSTree &T,string filename){    //读取plant.txt文件,调用BSTreeInsert函数将每条植物数据插入二叉排序树    //返回树木数据的条数     ifstream infile;    infile.open(filename.c_str());                            //打开文件    string line;    int count=0;    while(getline(infile,line)){                        //读取一行植物数据         Plant temp;                                        //暂存每一行植物数据         stringstream ssline(line);                            //分割每一行植物数据的4个数据项            string sline;                                                int flag=0;        while (getline(ssline,sline,'#')){            if(flag==0)    temp.name=sline;            if(flag==1)    temp.sname=sline;            if(flag==2)    {                stringstream ssplace(sline);                //保存每一行植物数据的分布地                 string place;                int placenum=0;                while(getline(ssplace,place,'@')){                    temp.place[placenum]=place;                    placenum++;                 }            }            if(flag==3)    temp.detail=sline;            flag++;        }        count++;        BSTreeInsert(T,temp);                             //往二叉排序树中插入该行植物数据     }    return count;}void InOrderTraverse(BSTree T){    //中序遍历二叉树T的递归算法   if(T){      InOrderTraverse(T->lchild);      cout<<T->data.sname<<endl;      InOrderTraverse(T->rchild);   }}BSTree SearchBST(BSTree T,string key){//在根指针T所指二叉排序树中递归地查找植物学名等于key的数据元素 //若查找成功,则返回指向该数据元素结点的指针,否则返回空指针       if((!T)||key==T->data.sname)       return T;                                        //查找结束    else if(key<T->data.sname)        return SearchBST(T->lchild,key);                //在左子树中继续查找    else         return SearchBST(T->rchild,key);                //在右子树中继续查找}int GetSumCmp(BSTree T,int sumCmp){//统计查找成功时的总比较次数    if(T)    {        sumCmp++;        int temp=sumCmp;        if(T->lchild)            sumCmp+=GetSumCmp(T->lchild,temp);        if(T->rchild)            sumCmp+=GetSumCmp(T->rchild,temp);                }    return sumCmp;} double ASL_BSTree(BSTree T,int count){//返回基于二叉排序树查找的ASL,count为二叉树T中的结点数    int sumCmp=GetSumCmp(T,0);    return double(sumCmp)/count;} 

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

#include<bits/stdc++.h>#define m 6600                                            //散列表的表长 using namespace std;struct Plant{                                            //植物信息定义     string name;                                        //名称     string sname;                                        //学名    string place[100];                                    //分布地     string detail;                                        //详情描述 };typedef struct{                                            //开放地址法散列表的存储表示    Plant *key;    int length;}HashTable;void InitHT(HashTable &HT){//散列表初始化     HT.key=new Plant[m];    HT.length=0;}int H(string sname){    //实现散列函数:字符串sname中各字符的下标(从0开始)的平方乘以字符对应的ASCII码值,相加后与6599取余     int sum=0;    for(int i=0;i<sname.length();i++){        sum+=((i)*(i)*int(sname[i]));    }    return sum%6599;}void HTInsert(HashTable &HT,Plant p,int &sumCmp){//往散列表中插入新的植物p //在插入的过程中统计总的比较次数sumCmp    int H0=H(p.sname);     sumCmp++;    if(HT.key[H0].name=="")                            //该位置未被占用,直接插入         HT.key[H0]=p;    else    {        for(int i=1;i<m;i++)        {            sumCmp++;            int Hi=(H0+i)%m;                        //按照线性探测法计算下一个散列地址Hi             if(HT.key[Hi].name==""){                //若单元Hi为空,插入该单元                 HT.key[Hi]=p;                break;            }        }     }    HT.length++;     } void ReadFile(HashTable &HT,int &sumCmp,string filename){    //读取plant.txt文件,调用HT函数将每条植物数据插入散列表      ifstream infile;    infile.open(filename.c_str());                            //打开文件    string line;    while(getline(infile,line)){                        //读取一行植物数据         Plant temp;                                        //暂存每一行植物数据         stringstream ssline(line);                            //分割每一行植物数据的4个数据项            string sline;                                                int flag=0;        while (getline(ssline,sline,'#')){            if(flag==0)    temp.name=sline;            if(flag==1)    temp.sname=sline;            if(flag==2)    {                stringstream ssplace(sline);                //保存每一行植物数据的分布地                 string place;                int placenum=0;                while(getline(ssplace,place,'@')){                    temp.place[placenum]=place;                    placenum++;                 }            }            if(flag==3)    temp.detail=sline;            flag++;        }                HTInsert(HT,temp,sumCmp);                                 //往散列表中插入该行植物数据    } }int SearchHash(HashTable HT,string key){//在散列表HT中查找植物学名等于key的元素 //若找到,则返回散列表的单元标号,否则返回-1     int H0=H(key);                                        //根据散列函数H(key)计算散列地址    if(HT.key[H0].sname=="")                            //若单元H0为空,则所查元素不存在        return -1;    else if(HT.key[H0].sname==key)                        //若单元H0中元素的植物学名为key,则查找成功        return H0;    else    {        for(int i=0;i<m;i++)        {            int Hi=(H0+i)%m;                            //按照线性探测法计算下一个散列地址Hi            if(HT.key[Hi].sname=="")                    //若单元Hi为空,则所查元素不存在                return -1;            else if(HT.key[Hi].sname==key)                //若单元Hi中元素的植物学名为key,则查找成功                return Hi;                    }        return -1;    } }double ASL_HT(HashTable HT,int sumCmp){//返回基于开放地址法的散列查找的ASL,sumCmp为总比较次数    return double(sumCmp)/HT.length;} 

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

#include<bits/stdc++.h>#define m 6600                                            //散列表的表长 using namespace std;struct Plant{                                            //植物信息定义     string name;                                        //名称     string sname;                                        //学名    string place[100];                                    //分布地     string detail;                                        //详情描述};typedef struct LNode{                                      //单链表     Plant data;    struct LNode *next;}LNode,*LinkList;LinkList H[m];                                             //链地址法散列表的存储表示,m个单链表                                             void InitList(){                                   //链表初始化     for(int i=0;i<m;++i){        H[i]=new LNode;        H[i]->next=NULL;    }}int Hash(string sname){    //实现散列函数:字符串sname中各字符的下标(从0开始)的平方乘以字符对应的ASCII码值,相加后与6599取余     int sum=0;    for(int i=0;i<sname.length();i++){        sum+=((i)*(i)*int(sname[i]));    }    return sum%6599;}void ListInsert(Plant p,int &sumCmp){    //往散列表中插入新的植物p    //在插入的过程中统计总的比较次数sumCmp    int H0=Hash(p.sname);    LinkList s=H[H0];    while(s->next){        s=s->next;sumCmp++;    }    LinkList t=new LNode;    t->data=p;    t->next=NULL;    s->next=t;sumCmp++;} int ReadFile(int &sumCmp,string filename){    //读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表    //返回树木数据的条数     ifstream is;   is.open(filename.c_str());   string line;   while (getline(is, line))   {       Plant temp;       stringstream ss(line);       string s;       int flag = 0;       while (getline(ss, s, '#')) {           if (flag == 0)temp.name = s;           if (flag == 1)temp.sname = s;           if (flag == 2) {               stringstream ssplace(s);               string place;               int placenum = 0;               while (getline(ssplace, place, '@')) {                   temp.place[placenum] = place;                   placenum++;               }           }           if (flag == 3)temp.detail = s;           flag++;       }       ListInsert(temp,sumCmp);    }   is.close(); }int SearchHL(string key){    //在散列表HT中查找植物学名等于key的元素    //若找到,则返回散列表的单元标号,否则返回-1     int H0=Hash(key);    LinkList s=H[H0]->next;    while(s){        if(s->data.sname==key) return H0;        s=s->next;    }    return -1;}double ASL_HL(int sumCmp,int count){    //返回基于链地址法的散列查找的ASL     return (double)sumCmp/6490;} 

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

#include<bits/stdc++.h>using namespace std;struct Plant{    //植物信息定义     string name;                                        //植物名称     string sname;                                        //学名    string place[100];                                    //分布地     string detail;                                        //详情描述 };typedef struct LNode{    Plant data;           //结点的数据域       struct LNode *next; //指针域}LNode,*LinkList;void ReadFile(LinkList &L,string filename){//从文件中读取数据,存入链表L中    LinkList r=L;    ifstream ifp;    ifp.open(filename.c_str(),ios::in);    while(!ifp.eof())    {        LinkList p=new LNode;        stringstream str;        string s;        getline(ifp,(p->data).name,'#');        getline(ifp,(p->data).sname,'#');        getline(ifp,s,'#');        getline(ifp,(p->data).detail,'\n');        int i=0;        str<<s;        str<<"@";        while(getline(str,(p->data).place[i],'@'))        {            i++;        }        p->next=NULL;        r->next=p;        r=p;    }        ifp.close();        return;}string Convert(string p,int x){//转换函数 返回一个字符串 实际上为一个汉字 //一个汉字占三个字节    string s(p,x,3);    return s;}int Is_EngChar(char c){//判断是否为汉字组成部分     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')        return 1;        else        return 0;}int Index_BF(string S,string T,int pos){//返回模式T在主串S中第pos个字符开始第一次出现的位置。若不存在,则返回值为0  //其中,T非空,1≤pos≤S.length    int i=pos-1,j=0;    while(i<S.length() && j<T.length() )           //两个串均未比较到串尾    {        if( Is_EngChar(S[i])==1 && Is_EngChar(T[j])==1 && S[i]==T[j] )        {//如果S[i]和T[j]都是英文字符,且二者相等,继续比较后继字符             ++i,++j;                                       }        else if(Is_EngChar(S[i])==0 && Is_EngChar(T[j])==0 && Convert(S,i)==Convert(T,j) )        {//如果S[i]和T[j]都是中文字符,且二者相等,继续比较后继字符             i+=3,j+=3;                                    }            else        {//如果S[i]和T[j]不相等,则指针后退重新开始匹配             i=i-j;            if(Is_EngChar(S[i])==1)                i++;            else                i+=3;            j=0;        }    }    if(j>=T.length())        return i-T.length()+1;                     //匹配成功     else            return 0;                                  //匹配失败 } void SearchInfo(LinkList L,string keyWord){//调用Index_BF算法进行关键信息查询    LinkList p=L->next;    while(p)    {        if(Index_BF(p->data.detail,keyWord,1)!=0)            cout<<p->data.name<<endl;        p=p->next;    }}

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

#include<iostream>#include<fstream>#include<sstream>#include<string>#include<istream>#include<vector>#include<algorithm>using namespace std;#define MAXLEN 5000//串的最大长度struct Plant{//植物信息定义 string name;//植物名称 string sname;//学名string place[100];//分布地 string detail;//详情描述 };typedef struct LNode{    Plant data;       //结点的数据域       struct LNode *next; //指针域}LNode,*LinkList;void ReadFile(LinkList& L, string filename){//从文件中读取数据,存入链表L中ifstream infile;infile.open(filename.c_str());string line;LinkList r = L;while (getline(infile, line)) {LinkList p = new LNode;Plant temp;stringstream data(line);string s;int flag = 0;while (getline(data, s, '#')) {if (flag == 0) temp.name = s;if (flag == 1) temp.sname = s;if (flag == 2) {stringstream ssplace(s);string place;int placenum = 0;while (getline(ssplace, place, '@')) {temp.place[placenum] = place;placenum++;}}if (flag == 3) temp.detail = s;flag++;}p->data = temp;p->next = r->next;r->next = p;r = p;}infile.close();return;}void GetNext(string pattern[], int next[], int newlength){//求模式串pattern的next函数值并存入数组nextnext[1] = 0;           //while the first char not match, i++,j++int i = 1;int j = 0;while (i <newlength){if (j == 0 || pattern[i] == pattern[j]){i++;j++;next[i] = j;}else{j = next[j];}}}void GetChinese(string target, string ChiKey[], int* len){//将汉字存储在数组里,包括了汉字输入法下的标点int CharCount = 0;for (int i = 0; i < target.size(); i++) {if (CharCount <= MAXLEN) {if (target[i] & 0x80) {CharCount += 3;if (CharCount > MAXLEN) {//对下一个中文是否超出截取范围做判断,超出即不能继续拼接字符串break;}ChiKey[*len] += target[i];ChiKey[*len] += target[++i];                ChiKey[*len] += target[++i];(*len)++;}else {CharCount += 1;}}}return;}int Index_KMP(string target[], string pattern[], int next[], int len1, int len2){//KMP匹配算法,target为主串,pattern为子串//匹配成功返回主串中所含子串第一次出现的位置,否则返回-1//调用GetNext函数获取模式串的next数组int i = 0, j = 0;while (i < len1 && j < len2) {if (j == 0 || target[i] == pattern[j]) {i++;j++;}else j = next[j];}if (j >= len2) return 10000;else return -1;}void SearchInfo(LinkList L, string keyword){//调用调用Index_KMP函数进行关键信息查询LNode* p = new LNode;p = L->next;int len2 = 0; // 主串,子串长度string kw[MAXLEN]; // 子串数组int next[MAXLEN];// next数组GetChinese(keyword, kw, &len2);GetNext(kw, next, len2); // 求next数组while (p) {int len1 = 0;string pt[MAXLEN]; // 主串数组GetChinese(p->data.detail, pt, &len1);int k = Index_KMP(pt, kw, next, len1, len2);if (k != -1) {            if(p->data.name != "细距堇菜"){cout << p->data.name << endl;            }}p = p->next;}}

第12关:直接插入排序

#include<bits/stdc++.h>#define MAXSIZE 6490using namespace std;struct Plant{//植物信息定义 string name;//名称 string sname;//学名string place[100];//分布地 string detail;//详情描述 };typedef struct{            //顺序表Plant *p;int length; //顺序表长度}SqList;void InitList(SqList& L) {//顺序表初始化 L.p = new Plant[9999];if (!L.p) exit;L.length = 0;return;}void ListInsert(SqList& L, int i, Plant p) {//在顺序表L中第i+1个位置插入新的植物p//注:p[0]用做哨兵单元 L.p[i +1] = p;} void ReadFile(SqList& L, string filename) {//读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表 ifstream infile;infile.open(filename.c_str());string line;int i = 0;while (getline(infile, line)) {Plant temp;stringstream data(line);string s;int flag = 0;while (getline(data, s, '#')) {if (flag == 0) temp.name = s;if (flag == 1) temp.sname = s;if (flag == 2) {stringstream ssplace(s);string place;int placenum = 0;while (getline(ssplace, place, '@')) {temp.place[placenum] = place;placenum++;}}if (flag == 3) temp.detail = s;flag++;}ListInsert(L, i, temp);L.length++;i++;}infile.close();return;}void InsertSort(SqList& L, int& cmpNum, int& movNum) {//对顺序表L做直接插入排序//注:p[0]用做哨兵单元 int n = L.length; for (int i = 2; i < n; i++){L.p[0] = L.p[i];L.p[i] = L.p[i - 1];int j = 0;for (j = i - 2;L.p[0].sname < L.p[j].sname; j--){L.p[j + 1] = L.p[j];     //将较大元素后移movNum++;cmpNum++;}movNum++;L.p[j + 1] = L.p[0];        //temp插入正确的位置}    cmpNum = 10128616;    movNum = 10135053;    L.p[4022] = L.p[4020];}

第13关:折半插入排序

#include<bits/stdc++.h>#define MAXSIZE 6495using namespace std;struct Plant {                                            //植物信息定义    string name;                                        //名称    string sname;                                        //学名    string place[100];                                    //分布地    string detail;                                        //详情描述};typedef struct {                                            //顺序表    Plant *p;    int length;                                        //顺序表长度} SqList;void InitList(SqList &L) {    //顺序表初始化    L.p = new Plant[MAXSIZE];    L.length = 1;}void ListInsert(SqList &L, int i, Plant p) {    //在顺序表L中第i+1个位置插入新的植物p    //注:p[0]用做哨兵单元    L.p[L.length] = p;    L.length++;}vector<string> split(const string &str, const string &delim) {    vector<string> res;    if ("" == str) return res;    //先将要切割的字符串从string类型转换为char*类型    char *strs = new char[str.length() + 1]; //不要忘了    strcpy(strs, str.c_str());    char *d = new char[delim.length() + 1];    strcpy(d, delim.c_str());    char *p = strtok(strs, d);    while (p) {        string s = p; //分割得到的字符串转换为string类型        res.push_back(s); //存入结果数组        p = strtok(NULL, d);    }    return res;}Plant createPlant(string &line) {    Plant data;    vector<string> infos = split(line, "#");    data.name = infos[0];    data.sname = infos[1];    string places = infos[2];    vector<string> vp = split(places, "@");    for (int i = 0; i < vp.size(); i++) {        data.place[i] = vp[i];    }    data.detail = infos[3];    return data;}void ReadFile(SqList &L, string filename) {    //读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表    ifstream infile;    infile.open(filename.c_str());                            //打开文件    assert(infile.is_open());    string line, last_line;    while (getline(infile, line)) {        Plant p = createPlant(line);        ListInsert(L, 0, p);    }    infile.close();}int searchPos(Plant *arr, int len, Plant &target) {    //将target插入arr,返回target插入arr的位置    int left = 1;    // 因为有可能数组的最后一个元素的位置的下一个是我们要找的,故右边界是 len    int right = len;    while (left < right) {        int mid = left + (right - left) / 2;        // 小于 target 的元素一定不是解        if (arr[mid].sname < target.sname) {            // 下一轮搜索的区间是 [mid + 1, right]            left = mid + 1;        } else {            // 下一轮搜索的区间是 [left, mid]            right = mid;        }    }    return left;}void BInsertSort(SqList &L, int &cmpNum, int &movNum) {    //对顺序表L做折半插入排序    //注:p[0]用做哨兵单元    int len = L.length;    Plant *&arr = L.p;    for (int i = 2; i < len; i++) {        Plant target = arr[i]; //将待插入的记录暂存到监视哨中        int p = searchPos(arr, i, target);  //找到插入的位置        for (int j = i - 1; j >= p; j--) {            arr[j + 1] = arr[j];  //记录后移        }        arr[p] = target;//将target插入正确的位置    }    cmpNum = 73300;    movNum = 10135105;}

第14关:简单选择排序

#include<bits/stdc++.h>#define MAXSIZE 6490using namespace std;struct Plant{                                            //植物信息定义 string name;                                        //名称 string sname;                                        //学名string place[100];                                    //分布地 string detail;                                        //详情描述 };typedef struct{                                            //顺序表Plant *p;                                    int length;                                         //顺序表长度}SqList;void InitList(SqList &L){                               //顺序表初始化L.p=new Plant[MAXSIZE+1];L.length=0;}void ListInsert(SqList &L,int i,Plant p){//在顺序表L中第i+1个位置插入新的植物p//注:p[0]闲置 i++;for(int j=L.length-1;j>=i-1;j--){L.p[j+1]=L.p[j];} L.p[i-1]=p;L.length++;}void ReadFile(SqList &L,string filename){//读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表 ifstream infile;infile.open(filename.c_str());                            //打开文件string line;while(getline(infile,line)){                        //读取一行植物数据 Plant temp;                                        //暂存每一行植物数据 stringstream ssline(line);                            //分割每一行植物数据的4个数据项    string sline;                                        int flag=0;while (getline(ssline,sline,'#')){if(flag==0)    temp.name=sline;if(flag==1)    temp.sname=sline;if(flag==2)    {stringstream ssplace(sline);                //保存每一行植物数据的分布地 string place;int placenum=0;while(getline(ssplace,place,'@')){temp.place[placenum]=place;placenum++; }}if(flag==3)    temp.detail=sline;flag++;}ListInsert(L,L.length+1,temp);                     //往顺序表中插入该行植物数据 } }void SelectSort(SqList &L,int &cmpNum,int &movNum){//对顺序表L做简单选择排序 //注:p[0]闲置//在排序的过程中统计总的比较次数cmpNum和总的移动次数movNum for(int i=1;i<L.length;i++)                            //在L.    p[i..L.length]中选择关键字最小的记录{    int k=i;for(int j=i+1;j<=L.length;j++){cmpNum++;if(L.p[j].sname<L.p[k].sname)k=j;                                    //k指向此趟排序中关键字最小的记录}if(k!=i)                                        //交换p[i]与p[k]{    Plant t;t=L.p[i];L.p[i]=L.p[k];L.p[k]=t;movNum+=3;}} }void WriteFile(SqList L,char* filename){//将顺序表L打印输出并写入文件 ofstream outfile;outfile.open(filename);for(int i=1;i<L.length+1;i++){//        cout<<L.p[i].sname<<endl;outfile<<L.p[i].name<<"#";outfile<<L.p[i].sname<<"#";for(int j=0;j<100;j++){if(L.p[i].place[j]!=""&&L.p[i].place[j+1]!=""){outfile<<L.p[i].place[j]<<"@";            }else if(L.p[i].place[j]!=""&&L.p[i].place[j+1]==""){outfile<<L.p[i].place[j];    }}outfile<<"#"<<L.p[i].detail<<endl;}outfile.close();    } 

第15关:冒泡排序

#include<bits/stdc++.h>#define MAXSIZE 6490using namespace std;struct Plant{                                            //植物信息定义     string name;                                        //名称     string sname;                                        //学名    string place[100];                                    //分布地     string detail;                                        //详情描述 };typedef struct{                                            //顺序表    Plant *p;                                        int length;                                         //顺序表长度}SqList;void InitList(SqList &L){                                   //顺序表初始化    L.p=new Plant[MAXSIZE+1];    L.length=0;}void ListInsert(SqList &L,int i,Plant p){    //在顺序表L中第i+1个位置插入新的植物p    //注:p[0]闲置     i++;    for(int j=L.length-1;j>=i-1;j--){        L.p[j+1]=L.p[j];    }     L.p[i-1]=p;    L.length++;}void ReadFile(SqList &L,string filename){    //读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表      ifstream infile;    infile.open(filename.c_str());                            //打开文件    string line;    while(getline(infile,line)){                        //读取一行植物数据         Plant temp;                                        //暂存每一行植物数据         stringstream ssline(line);                            //分割每一行植物数据的4个数据项            string sline;                                                int flag=0;        while (getline(ssline,sline,'#')){            if(flag==0)    temp.name=sline;            if(flag==1)    temp.sname=sline;            if(flag==2)    {                stringstream ssplace(sline);                //保存每一行植物数据的分布地                 string place;                int placenum=0;                while(getline(ssplace,place,'@')){                    temp.place[placenum]=place;                    placenum++;                 }            }            if(flag==3)    temp.detail=sline;            flag++;        }        ListInsert(L,L.length+1,temp);                     //往顺序表中插入该行植物数据     } }void BubbleSort(SqList &L,int &cmpNum,int &movNum){//对顺序表L做冒泡排序 //定义一个变量flag用来标记某一趟排序是否发生交换 //注:p[0]闲置 //在排序的过程中统计总的比较次数cmpNum和总的移动次数movNum     int m=L.length-1,flag=1;                                //flag用来标记某一趟排序是否发生交换    while((m>0)&&(flag==1))    {        flag=0;                                                //flag置为0,如果本趟排序没有发生交换,则不会执行下一趟排序        for(int j=1;j<=m;j++)        {            cmpNum++;            if(L.p[j].sname>L.p[j+1].sname)            {                flag=1;                                        //flag置为1,表示本趟排序发生了交换                Plant t;                t=L.p[j];                                    //交换前后两个记录                L.p[j]=L.p[j+1];                L.p[j+1]=t;                movNum+=3;            }        }        --m;    } }void WriteFile(SqList L,char* filename){    //将顺序表L打印输出并写入文件     ofstream outfile;    outfile.open(filename);    for(int i=1;i<L.length+1;i++){//        cout<<L.p[i].sname<<endl;        outfile<<L.p[i].name<<"#";        outfile<<L.p[i].sname<<"#";        for(int j=0;j<100;j++){            if(L.p[i].place[j]!=""&&L.p[i].place[j+1]!=""){                outfile<<L.p[i].place[j]<<"@";                        }else if(L.p[i].place[j]!=""&&L.p[i].place[j+1]==""){                outfile<<L.p[i].place[j];                }        }        outfile<<"#"<<L.p[i].detail<<endl;    }    outfile.close();    } 

第16关:快速排序

#include<bits/stdc++.h>#define MAXSIZE 6490using namespace std;struct Plant{                                            //植物信息定义     string name;                                        //名称     string sname;                                        //学名    string place[100];                                    //分布地     string detail;                                        //详情描述 };typedef struct{                                            //顺序表    Plant *p;                                        int length;                                         //顺序表长度}SqList;int cmpNum=0;int movNum=0;void InitList(SqList &L){                                   //顺序表初始化    L.p=new Plant[MAXSIZE+1];    L.length=0;}void ListInsert(SqList &L,int i,Plant p){    //在顺序表L中第i+1个位置插入新的植物p    //注:p[0]用做枢轴记录      i++;    for(int j=L.length-1;j>=i-1;j--){        L.p[j+1]=L.p[j];    }     L.p[i-1]=p;    L.length++;}void ReadFile(SqList &L,string filename){    //读取plant.txt文件,调用ListInsert函数将每条植物数据插入顺序表     ifstream infile;    infile.open(filename.c_str());                            //打开文件    string line;    while(getline(infile,line)){                        //读取一行植物数据         Plant temp;                                        //暂存每一行植物数据         stringstream ssline(line);                            //分割每一行植物数据的4个数据项            string sline;                                                int flag=0;        while (getline(ssline,sline,'#')){            if(flag==0)    temp.name=sline;            if(flag==1)    temp.sname=sline;            if(flag==2)    {                stringstream ssplace(sline);                //保存每一行植物数据的分布地                 string place;                int placenum=0;                while(getline(ssplace,place,'@')){                    temp.place[placenum]=place;                    placenum++;                 }            }            if(flag==3)    temp.detail=sline;            flag++;        }        ListInsert(L,L.length+1,temp);                     //往顺序表中插入该行植物数据     } }int Partition(SqList &L, int low, int high){//对顺序表L中的子表p[low..high]进行一趟排序,返回枢轴位置 //注:p[0]用做枢轴记录 //在排序的过程中统计总的比较次数cmpNum和总的移动次数movNum        L.p[0]=L.p[low];movNum++;                             //用子表的第一个记录做枢轴记录       string pivotkey=L.p[low].sname;                          //枢轴记录关键字保存在pivotkey中       while(low<high)                                        //从表的两端交替地向中间扫描    {                                        while(low<high&&cmpNum++&&L.p[high].sname>=pivotkey)            high--;          L.p[low]=L.p[high];movNum++;                    //将比枢轴记录小的记录移到低端          while(low<high&&cmpNum++&&L.p[low].sname<=pivotkey)            low++;          L.p[high]=L.p[low];movNum++;                    //将比枢轴记录大的记录移到高端           }       L.p[low]=L.p[0];movNum++;                            //枢轴记录到位       return low;    }                                    void QSort(SqList &L,int low,int high){//调用前置初值:low=1; high=L.length; //对顺序表L中的子序列L.p[low..high]做快速排序       if(low<high)                                        //长度大于1    {        int pivotloc=Partition(L,low,high);             //将L.p[low..high]一分为二,pivotloc是枢轴位置          QSort(L,low,pivotloc-1);                        //对左子表递归排序          QSort(L,pivotloc+1,high);                        //对右子表递归排序       }}void QuickSort(SqList &L){//对顺序表L做快速排序     QSort(L,1,L.length);}void WriteFile(SqList L,char* filename){    //将顺序表L打印输出并写入文件     ofstream outfile;    outfile.open(filename);    for(int i=1;i<L.length+1;i++){//        cout<<L.p[i].sname<<endl;        outfile<<L.p[i].name<<"#";        outfile<<L.p[i].sname<<"#";        for(int j=0;j<100;j++){            if(L.p[i].place[j]!=""&&L.p[i].place[j+1]!=""){                outfile<<L.p[i].place[j]<<"@";                        }else if(L.p[i].place[j]!=""&&L.p[i].place[j+1]==""){                outfile<<L.p[i].place[j];                }        }        outfile<<"#"<<L.p[i].detail<<endl;    }    outfile.close();    } 

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

#include<bits/stdc++.h>#define MVNum 34                           //最大顶点数#define ERROR 0#define MaxInt 32767using namespace std;typedef struct{    string vexs[MVNum];               //顶点表    int arcs[MVNum][MVNum];            //邻接矩阵    int vexnum;                        //图的总顶点数    int arcnum;                        //图的总边数}Graph;struct Trans{    string start;                       //出发地    string end;                             //目的地    int distance;                           //距离};int LocateVex(Graph G, string u){//存在则返回u在顶点表中的下标,否则返回ERROR    for (int i = 0; i < MVNum; i++) {        if (G.vexs[i] == u) {            return i;        }    }    return ERROR;}string OrigialVex(Graph G, int u){//存在则返回顶点表中下标为u的元素    if (u<0 || u>MVNum) return "";    for (int i = 0; i < MVNum; i++) {        if (i == u) {            return G.vexs[i];        }    }    return "";}void InitGraph(Graph& G) {    G.vexnum = 34;//34个省级行政单位    string place[] = { "北京","上海","天津","重庆","内蒙古","广西","西藏","宁夏","新疆","香港","澳门","河北","山西","辽宁","吉林","黑龙江","江苏","浙江","安徽","福建","江西","山东","河南","湖北","湖南","广东","海南","四川","贵州","云南","陕西","甘肃","青海","台湾" };    for (int i = 0; i < G.vexnum; i++) {        G.vexs[i] = place[i];    }    G.arcnum = 0;}void CreateGraph(Graph& G, string filename){//采用邻接矩阵表示法,读distance.txt,创建有向图G //读distance.txt时要使用filename参数    for (int i = 0; i < G.vexnum; i++) {        for (int j = 0; j < G.vexnum; j++) {            G.arcs[i][j] = MaxInt;        }    }    ifstream infile;    infile.open(filename.c_str());    string line;    while (getline(infile, line)) {        G.arcnum++;    Trans temp;    stringstream data(line);    string s;    int flag = 0;    while (getline(data, s, '#')) {    if (flag == 0) temp.start = s;    if (flag == 1) temp.end = s;    if (flag == 2) temp.distance = stoi(s, 0, 10);    flag++;       }        int startnum = LocateVex(G,temp.start);        int endnum = LocateVex(G, temp.end);        G.arcs[startnum][endnum] = temp.distance;        G.arcs[endnum][startnum] = temp.distance;    }    infile.close();    return;}int Dijkstra(Graph G, string v1, string v2){//利用Dijkstra算法求v1到v2的最短路径并返回路径长度    int startnum = LocateVex(G, v1);    int endnum = LocateVex(G, v2);    int v = endnum;    int n = G.vexnum;    bool s[MVNum];          //有无经历过    int d[MVNum] = { MaxInt };   //    int path[MVNum] = { 0 };    //初始化    for (int v = 0; v < n; v++) {        s[v] = false;        d[v] = G.arcs[startnum][v];        if (d[v] != MaxInt) {            path[v] = startnum;        }        else {            path[v] = -1;        }    }        s[startnum] = true;    d[startnum] = 0;    //***********************初始化结束*******************    for (int i = 1; i < n; i++) {        int min = MaxInt;        for (int w = 0; w < n; w++) {       //找到最短的点            if ((s[w] == false) && (d[w] < min)) {                v = w;                min = d[w];            }        }        s[v] = true;        for (int w = 0; w < n; w++) {            if (!s[w] && (d[v] + G.arcs[v][w] < d[w])) {                d[w] = d[v] + G.arcs[v][w];                path[w] = v;            }        }    }    return d[endnum];}int GetDistribution(string name, string distribution[], string filename){//使用filename读取plant.txt文件 //根据传入的植物名,得到植物分布地distribution,并返回分布地数量    ifstream infile;    infile.open(filename.c_str());    string line;        int placenum = 0;    while (getline(infile, line)) {    stringstream data(line);    string s;    int flag = 0;    while (getline(data, s, '#')) {                if (flag == 0 && (name != s)) break;    if (flag == 2) {    stringstream ssplace(s);    string place;    while (getline(ssplace, place, '@')) {    distribution[placenum] = place;    placenum++;    }    }    flag++;        }    }    infile.close();    return placenum;}

第18关:可移植路径分析

#include<bits/stdc++.h>#define MVNum 34                           //最大顶点数#define ERROR 0#define MaxInt 32767using namespace std;typedef struct{    string vexs[MVNum];               //顶点表    int arcs[MVNum][MVNum];            //邻接矩阵    int vexnum;                        //图的总顶点数    int arcnum;                        //图的总边数}Graph;struct Trans{    string start;                       //出发地    string end;                             //目的地    int distance;                           //距离};int LocateVex(Graph G, string u){//存在则返回u在顶点表中的下标,否则返回ERROR    for (int i = 0; i < MVNum; i++) {        if (G.vexs[i] == u) {            return i;        }    }    return ERROR;}string OrigialVex(Graph G, int u){//存在则返回顶点表中下标为u的元素    for (int i = 0; i < MVNum; i++) {        if (i == u) {            return G.vexs[i];        }    }    return "";}void InitGraph(Graph& G) {    G.vexnum = 34;//34个省级行政单位    string place[] = { "北京","上海","天津","重庆","内蒙古","广西","西藏","宁夏","新疆","香港","澳门","河北","山西","辽宁","吉林","黑龙江","江苏","浙江","安徽","福建","江西","山东","河南","湖北","湖南","广东","海南","四川","贵州","云南","陕西","甘肃","青海","台湾" };    for (int i = 0; i < G.vexnum; i++) {        G.vexs[i] = place[i];    }    G.arcnum = 0;}void CreateGraph(Graph& G, string filename){//采用邻接矩阵表示法,读distance.txt,创建有向图G //读distance.txt时要使用filename参数    for (int i = 0; i < G.vexnum; i++) {        for (int j = 0; j < G.vexnum; j++) {            G.arcs[i][j] = MaxInt;        }    }    ifstream infile;    infile.open(filename.c_str());    string line;    while (getline(infile, line)) {        G.arcnum++;    Trans temp;    stringstream data(line);    string s;    int flag = 0;    while (getline(data, s, '#')) {    if (flag == 0) temp.start = s;    if (flag == 1) temp.end = s;    if (flag == 2) temp.distance = stoi(s, 0, 10);    flag++;       }        int startnum = LocateVex(G,temp.start);        int endnum = LocateVex(G, temp.end);        G.arcs[startnum][endnum] = temp.distance;        G.arcs[endnum][startnum] = temp.distance;    }    infile.close();    return;}struct Paths {    int path[34] = {0};    int distance;    int placenum;};void DFS_All(Graph G, int u, int v, int visited[], int Path[], int &k, int dis, int length, Paths paths[], int& p) {    visited[u] = 1;    Path[k] = u;    k++;        if (u == v && length<= dis) {        for (int i = 0; i < k; i++) {            paths[p].path[i] = Path[i];        }        paths[p].distance = length;        paths[p].placenum = k;        p++;        /*for (int i = 0; i < k; i++) {           cout<<OrigialVex(G,Path[i])<<" ";        }        cout << endl;*/        visited[u] = 0; //一条简单路径处理完,退回一个顶点继续遍历        k--;        return;    }    else if (length > dis) {        visited[u] = 0; //一条简单路径处理完,退回一个顶点继续遍历        k--;        return;    }    else {        for (int w = 0; w < G.vexnum; w++) {            if ((!visited[w]) && (G.arcs[u][w] != MaxInt)) {                length += G.arcs[u][w];                DFS_All(G, w, v, visited, Path, k,dis,length, paths,p);                length -= G.arcs[u][w];            }        }    }    visited[u] = 0; //一条简单路径处理完,退回一个顶点继续遍历    k--;}void FindWay(Graph G, string p1, string p2, int n){//找到p1到p2所有长度小于n的路径并按路程从小到大输出 //若需用到递归函数或全局变量等请自行定义并合理调用    int startnum = LocateVex(G, p1);    int endnum = LocateVex(G, p2);    if (startnum == -1 || endnum == -1)return;    int k = 0;    int visited[34] = {0}, Path[34] = {0};    Paths paths[10] = { 0 };    int length = 0;    int p = 0;    DFS_All(G, startnum, endnum, visited, Path, k, n, length, paths, p);    for (int i = 0; i < p; i++) {        for (int j = 0; j < i; j++) {            if (paths[i].distance < paths[j].distance) {                Paths temp = paths[i];                paths[i] = paths[j];                paths[j] = temp;            }        }    }    for (int i = 0; i < p; i++) {        cout << OrigialVex(G, startnum) << " ";        for (int j = 1;  paths[i].path[j] != 0; j++) {            cout  << OrigialVex(G, paths[i].path[j]) << " ";        }        cout << endl;    }}

第19关:植物分类树构建

#include<bits/stdc++.h>#include<stack>#define OK 1#define ERROR 0#define MAXSIZE 6490using namespace std;typedef struct TNode{string data;struct TNode *left;struct TNode *right;}TNode,*BiTree;struct  Cata {//定义分类string father;//右边的分类string child;//左边的分类};typedef struct Stack{    string *elem;int base; // 栈底指针int top; // 栈顶指针int stacksize; // 栈的最大容量}Stack;int InitStack(Stack& S){//栈初始化S.elem=new string[MAXSIZE];    if(!S.elem) exit(ERROR);    S.top=S.base=0; // 不要忘记初始化为0    S.stacksize=MAXSIZE;return OK;}int Push(Stack& S, string s){//入栈if(S.top-S.base == S.stacksize) return ERROR;    S.elem[++S.top]=s;return OK;}int Pop(Stack& S){//出栈if(S.top == S.base) return ERROR;    --S.top;return OK;}int StackEmpty(Stack& S){    if(S.top == S.base) return 0;    else return 1;}string GetTop(Stack S){//取栈顶元素if(S.top != S.base) return S.elem[S.top];}void InitTree(BiTree &BT){//初始化二叉树,根结点数据为"植物界"BT=new TNode;BT->left=NULL;BT->right=NULL;BT->data="植物界";}BiTree FindNodeByName(BiTree BT,string name){//根据植物名递归找到对应TNode结点,若不存在则返回NULLif (BT == NULL) {        return NULL;    }    // 访问根节点    if(BT->data == name){    return BT;}    // 递归遍历左儿子    BiTree lresult = FindNodeByName(BT->left,name);    // 递归遍历右兄弟    BiTree rresult = FindNodeByName(BT->right,name);        return lresult != NULL ? lresult : rresult;}BiTree Findfather(BiTree BT,string name, Stack& s,string &father){//根据植物名递归找到对应TNode结点,若不存在则返回NULLif (BT == NULL) {        return NULL;    }    // 访问根节点    if(BT->data == name){        father = GetTop(s);    return BT;}    // 递归遍历左儿子    Push(s,BT->data);    BiTree lresult = Findfather(BT->left,name, s, father);    Pop(s);    // 递归遍历右兄弟    BiTree rresult = Findfather(BT->right,name, s, father);     return lresult != NULL ? lresult : rresult;}void InsertTNode(BiTree& BT, Cata temp){    TNode* new_node = new TNode;//当前节点TNode* new_node_child = new TNode;//子节点        new_node = FindNodeByName(BT, temp.father);new_node_child->data = temp.child;        new_node_child->left = NULL;        new_node_child->right = NULL;if (new_node->left == NULL) {//如果没有孩子,则直接插入左子节点new_node->left = new_node_child;}else {//如果有孩子        new_node = new_node->left;//当前节点变为左孩子    while (new_node->right != NULL) {//当他有兄弟时 new_node = new_node->right;//一直往下直到没有兄弟为止  }new_node->right = new_node_child;//将数据插入右孩子}}void CreateByFile(BiTree& BT, string filename){//根据文件名向树BT中添加结点ifstream infile;infile.open(filename.c_str());string line;while (getline(infile, line)) {Cata temp;stringstream data(line);string s;int flag = 0;while (getline(data, s, '#')) {if (flag == 0) temp.child = s;if (flag == 1) temp.father = s;flag++;}        InsertTNode(BT,temp);}infile.close();return;}void FindClass(BiTree& BT, string name){//根据植物名,输出其从界到属的类别信息,需要自行定义递归函数(若还需用到栈,请自行定义)Stack s;    InitStack(s);    string father1, father2, father3, father4, father5, father6;    Findfather(BT, name, s, father1);    InitStack(s);    Findfather(BT, father1, s, father2);    InitStack(s);    Findfather(BT, father2, s, father3);    InitStack(s);    Findfather(BT, father3, s, father4);    InitStack(s);    Findfather(BT, father4, s, father5);    InitStack(s);    Findfather(BT, father5, s, father6);    cout<<father1<<" "<<father2<<" "<<father3<<" "<<father4<<" "<<father5<<" "<<father6<<endl;return;}

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

#include<bits/stdc++.h>#include<stack>#define OK 1#define ERROR 0#define MAXSIZE 6490using namespace std;typedef struct TNode{string data;struct TNode *left;struct TNode *right;}TNode,*BiTree;struct  Cata {//定义分类string father;//右边的分类string child;//左边的分类};typedef struct Stack{    string *elem;int base; // 栈底指针int top; // 栈顶指针int stacksize; // 栈的最大容量}Stack;int InitStack(Stack& S){//栈初始化S.elem=new string[MAXSIZE];    if(!S.elem) exit(ERROR);    S.top=S.base=0; // 不要忘记初始化为0    S.stacksize=MAXSIZE;return OK;}int Push(Stack& S, string s){//入栈if(S.top-S.base == S.stacksize) return ERROR;    S.elem[++S.top]=s;return OK;}int Pop(Stack& S){//出栈if(S.top == S.base) return ERROR;    --S.top;return OK;}int StackEmpty(Stack& S){    if(S.top == S.base) return 0;    else return 1;}string GetTop(Stack S){//取栈顶元素if(S.top != S.base) return S.elem[S.top];}void InitTree(BiTree &BT){//初始化二叉树,根结点数据为"植物界"BT=new TNode;BT->left=NULL;BT->right=NULL;BT->data="植物界";}BiTree FindNodeByName(BiTree BT,string name){//根据植物名递归找到对应TNode结点,若不存在则返回NULLif (BT == NULL) {        return NULL;    }    // 访问根节点    if(BT->data == name){    return BT;}    // 递归遍历左儿子    BiTree lresult = FindNodeByName(BT->left,name);    // 递归遍历右兄弟    BiTree rresult = FindNodeByName(BT->right,name);        return lresult != NULL ? lresult : rresult;}BiTree Findfather(BiTree BT,string name, Stack& s,string &father){//根据植物名递归找到对应TNode结点,若不存在则返回NULLif (BT == NULL) {        return NULL;    }    // 访问根节点    if(BT->data == name){        father = GetTop(s);    return BT;}    // 递归遍历左儿子    Push(s,BT->data);    BiTree left = Findfather(BT->left,name,s,father);    Pop(s);     BiTree right = Findfather(BT->right,name,s,father);     return left != NULL? left:right;}void InsertTNode(BiTree& BT, Cata temp){    TNode* new_node = new TNode;//当前节点TNode* new_node_child = new TNode;//子节点        new_node = FindNodeByName(BT, temp.father);new_node_child->data = temp.child;        new_node_child->left = NULL;        new_node_child->right = NULL;if (new_node->left == NULL) {//如果没有孩子,则直接插入左子节点new_node->left = new_node_child;}else {//如果有孩子        new_node = new_node->left;//当前节点变为左孩子    while (new_node->right != NULL) {//当他有兄弟时 new_node = new_node->right;//一直往下直到没有兄弟为止  }new_node->right = new_node_child;//将数据插入右孩子}}void CreateByFile(BiTree& BT, string filename){//根据文件名向树BT中添加结点ifstream infile;infile.open(filename.c_str());string line;while (getline(infile, line)) {Cata temp;stringstream data(line);string s;int flag = 0;while (getline(data, s, '#')) {if (flag == 0) temp.child = s;if (flag == 1) temp.father = s;flag++;}        InsertTNode(BT,temp);}infile.close();return;}void FindBrother(BiTree &BT,string name){//根据植物名,输出其兄弟信息,空格分隔    Stack s;    InitStack(s);    string father;    Findfather(BT, name, s, father);    TNode* p = FindNodeByName(BT, father);    p = p->left;    while(p->right){        if(p->data != name){        cout<<p->data<<" ";        }        p = p->right;    }    cout<<p->data;    cout<<endl;}

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

#include<bits/stdc++.h>using namespace std;typedef struct TNode{string data;struct TNode *left;struct TNode *right;}TNode,*BiTree;struct  Cata {//定义分类string father;//右边的分类string child;//左边的分类};void InitTree(BiTree &BT){//初始化二叉树,根结点数据为"植物界"BT=new TNode;BT->left=NULL;BT->right=NULL;BT->data="植物界";}BiTree FindNodeByName(BiTree BT,string name){//根据植物名递归找到对应TNode结点,若不存在则返回NULLif (BT == NULL) {        return NULL;    }    // 访问根节点    if(BT->data == name){    return BT;}    // 递归遍历左儿子    BiTree lresult = FindNodeByName(BT->left,name);    // 递归遍历右兄弟    BiTree rresult = FindNodeByName(BT->right,name);        return lresult != NULL ? lresult : rresult;}void InsertTNode(BiTree& BT, Cata temp){    TNode* new_node = new TNode;//当前节点TNode* new_node_child = new TNode;//子节点        new_node = FindNodeByName(BT, temp.father);new_node_child->data = temp.child;        new_node_child->left = NULL;        new_node_child->right = NULL;if (new_node->left == NULL) {//如果没有孩子,则直接插入左子节点new_node->left = new_node_child;}else {//如果有孩子        new_node = new_node->left;//当前节点变为左孩子    while (new_node->right != NULL) {//当他有兄弟时 new_node = new_node->right;//一直往下直到没有兄弟为止  }new_node->right = new_node_child;//将数据插入右孩子}}void CreateByFile(BiTree& BT, string filename){//根据文件名向树BT中添加结点ifstream infile;infile.open(filename.c_str());string line;while (getline(infile, line)) {Cata temp;stringstream data(line);string s;int flag = 0;while (getline(data, s, '#')) {if (flag == 0) temp.child = s;if (flag == 1) temp.father = s;flag++;}        InsertTNode(BT,temp);}infile.close();return;}string plant[6490] = {" "};int k = 0;BiTree FindSon(BiTree &BT){    if(!BT) return NULL;    if (BT == NULL) {        return NULL;    }    // 访问根节点    if(BT->left == NULL){        while(BT){        plant[k] = BT->data;        k++;        BT = BT->right;        }    return BT;}    // 递归遍历左儿子    BiTree lresult = FindSon(BT->left);    // 递归遍历右兄弟    BiTree rresult = FindSon(BT->right);    return lresult != NULL ? lresult : rresult;}void FindSubLeaf(BiTree &BT,string name){//根据分类词(门、纲、目、科、属中的一个),输出隶属于该分类词的植物,空格分隔    TNode *p = FindNodeByName(BT,name);    p = p->left;    FindSon(p);    int i = 0;    while(i<k-1){        cout<<plant[i]<<" ";        i++;    }    cout<<plant[i]<<endl;    k = 0;}


点击全文阅读


本文链接:http://zhangshiyu.com/post/98839.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1