目次
第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 Node
{
Plant data; // ノードのデータ領域
struct Node *next; // ポインタ領域
}Node, *List;
void ReadFile(List& L, string filename)
{// ファイルからデータを読み込み、連結リストLに格納する
ifstream infile("data_edit/plant.txt");
string line;
List r = L;
while (getline(infile, line)) {
List p = new Node;
Plant temp;
stringstream data(line);
string s;
int idx = 0;
while (getline(data, s, '#')) {
if (idx == 0) temp.name = s;
if (idx == 1) temp.sname = s;
if (idx == 2) {
stringstream ssplace(s);
string place;
int placeCount = 0;
while (getline(ssplace, place, '@')) {
temp.place[placeCount] = place;
placeCount++;
}
}
if (idx == 3) temp.detail = s;
idx++;
}
p->data = temp;
p->next = r->next;
r->next = p;
r = p;
}
infile.close();
return;
}
int InPlant(List L, string name)
{// 指定された植物名nameが連結リスト内に存在するか判定
Node* p = new Node;
p = L->next;
int found = 0;
while (p) {
if (p->data.name == name) {
found++;
}
p = p->next;
}
if (found > 0) {
return true;
}
else {
return false;
}
}
bool InsertPlant(List &L, string filename)
{// 植物情報を追加。植物の名称、学名、分布地、詳細説明を入力し、plant.txtの末尾に書き込む。
// 植物名が既に存在する場合はfalse、存在しない場合はtrueを返す
int 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 Node
{
Plant data; // ノードのデータ領域
struct Node *next; // ポインタ領域
}Node, *List;
void ReadFile(List& L, string filename)
{// ファイルからデータを読み込み、連結リストLに格納する
ifstream infile;
infile.open(filename.c_str());
string line;
List r = L;
while (getline(infile, line)) {
List p = new Node;
Plant temp;
stringstream data(line);
string s;
int idx = 0;
while (getline(data, s, '#')) {
if (idx == 0) temp.name = s;
if (idx == 1) temp.sname = s;
if (idx == 2) {
stringstream ssplace(s);
string place;
int placeCount = 0;
while (getline(ssplace, place, '@')) {
temp.place[placeCount] = place;
placeCount++;
}
}
if (idx == 3) temp.detail = s;
idx++;
}
p->data = temp;
p->next = r->next;
r->next = p;
r = p;
}
infile.close();
return;
}
void DeletePlant(List &L, string name, string filename)
{// 指定された植物情報を削除する
Node* p = new Node;
p = L;
while (p->next) {
if (p->next->data.name == name) {
Node* q = new Node;
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 Node
{
Plant data; // ノードのデータ領域
struct Node *next; // ポインタ領域
}Node, *List;
void ReadFile(List& L, string filename)
{// ファイルからデータを読み込み、連結リストLに格納する
ifstream infile;
infile.open(filename.c_str());
string line;
List r = L;
while (getline(infile, line)) {
List p = new Node;
Plant temp;
stringstream data(line);
string s;
int idx = 0;
while (getline(data, s, '#')) {
if (idx == 0) temp.name = s;
if (idx == 1) temp.sname = s;
if (idx == 2) {
stringstream ssplace(s);
string place;
int placeCount = 0;
while (getline(ssplace, place, '@')) {
temp.place[placeCount] = place;
placeCount++;
}
}
if (idx == 3) temp.detail = s;
idx++;
}
p->data = temp;
p->next = r->next;
r->next = p;
r = p;
}
infile.close();
return;
}
bool ChangePlant(List &L, string name, string details, string filename)
{// 植物情報を変更する
// 指定名称が存在すればtrue、存在しなければfalse
Node* p = new Node;
p = L->next;
int found = 0;
while (p) {
if (p->data.name == name) {
p->data.detail = details;
found++;
}
p = p->next;
}
if (found > 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 *plants;
int length;
}SqList;
void InitList(SqList& L) {
// 順序表の初期化
L.plants = new Plant[9999];
if (!L.plants) exit;
L.length = 0;
return;
}
void ListInsert(SqList& L, int i, Plant p) {
L.plants[i] = p;
}
void ReadFile(SqList& L, string filename) {
// plant.txtファイルを読み込み、各植物データを順序表に挿入
ifstream infile;
infile.open(filename.c_str());
string line;
int i = 0;
while (getline(infile, line)) {
Plant temp;
stringstream data(line);
string s;
int idx = 0;
while (getline(data, s, '#')) {
if (idx == 0) temp.name = s;
if (idx == 1) temp.sname = s;
if (idx == 2) {
stringstream ssplace(s);
string place;
int placeCount = 0;
while (getline(ssplace, place, '@')) {
temp.place[placeCount] = place;
placeCount++;
}
}
if (idx == 3) temp.detail = s;
idx++;
}
ListInsert(L, i, temp);
L.length++;
i++;
}
infile.close();
return;
}
int Search_Seq(SqList L, string key) {
// 順序表L内で植物の学名がkeyに等しいデータ要素を順次探索
// 見つかればそのインデックスを返し、見つからなければ-1を返す
for (int i = 0; i < L.length; i++) {
if (L.plants[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 ListNode { // 単連結リスト
Plant data;
struct ListNode *next;
}ListNode, *List;
void InitList(List& L)
{// 空の単連結リストLを構築
L = new ListNode;
L->next = NULL;
}
void ListInsert(List& L, int i, Plant temp) {
// 先頭ノードを持つ単連結リストのi番目に新しいノードを挿入
ListNode* p = new ListNode;
ListNode* q = new ListNode;
p->data = temp;
q = L;
while (i > 1) {
q = q->next;
i--;
}
p->next = q->next;
q->next = p;
}
int ReadFile(List& L, string filename) {
// plant.txtファイルを読み込み、各植物データを連結リストに挿入
// 植物データの総数を返す
ifstream infile;
infile.open(filename.c_str());
string line;
int i = 1;
while (getline(infile, line)) {
Plant temp;
stringstream data(line);
string s;
int idx = 0;
while (getline(data, s, '#')) {
if (idx == 0) temp.name = s;
if (idx == 1) temp.sname = s;
if (idx == 2) {
stringstream ssplace(s);
string place;
int placeCount = 0;
while (getline(ssplace, place, '@')) {
temp.place[placeCount] = place;
placeCount++;
}
}
if (idx == 3) temp.detail = s;
idx++;
}
ListInsert(L, i, temp);
i++;
}
infile.close();
return i - 1;
}
ListNode* LocateElem(List L, string key) {
// 先頭ノードを持つ単連結リストLから学名がkeyの要素を探索
ListNode* p = new ListNode;
p = L->next;
while (p) {
if (p->data.sname == key) {
return p;
}
p = p->next;
}
return NULL;
}
double ASL_LinkList(List L, int count) {
// 連結リストに基づく順次探索のASLを返す
ListNode *p = new ListNode;
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 *plants;
int length;
}SqList;
void InitList(SqList &L){
// 順序表の初期化
L.plants = new Plant[9999];
if (!L.plants) exit(0);
L.length = 0;
return;
}
void ListInsert(SqList &L, int i, Plant p){
// 順序表Lのi番目に新しい植物pを挿入
L.plants[i] = p;
}
void ReadFile(SqList &L, string filename){
// plant.txtファイルを読み込み、各植物データを順序表に挿入
ifstream infile;
infile.open(filename.c_str());
string line;
int i = 0;
while (getline(infile, line)) {
Plant temp;
stringstream data(line);
string s;
int idx = 0;
while (getline(data, s, '#')) {
if (idx == 0) temp.name = s;
if (idx == 1) temp.sname = s;
if (idx == 2) {
stringstream ssplace(s);
string place;
int placeCount = 0;
while (getline(ssplace, place, '@')) {
temp.place[placeCount] = place;
placeCount++;
}
}
if (idx == 3) temp.detail = s;
idx++;
}
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を返す
for (int i = 0; i < L.length; i++) {
if (L.plants[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ファイルを読み込み、各植物データを二分探索木に挿入
// 木のノード数を返す
ifstream infile;
infile.open(filename.c_str());
string line;
int count = 0;
while(getline(infile, line)){
Plant temp;
stringstream ssline(line);
string sline;
int idx = 0;
while (getline(ssline, sline, '#')){
if(idx == 0) temp.name = sline;
if(idx == 1) temp.sname = sline;
if(idx == 2){
stringstream ssplace(sline);
string place;
int placeCount = 0;
while(getline(ssplace, place, '@')){
temp.place[placeCount] = place;
placeCount++;
}
}
if(idx == 3) temp.detail = sline;
idx++;
}
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に等しいデータ要素を再帰的に探索
// 成功時はそのノードのポインタを、失敗時はNULLを返す
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は木のノード数
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; // 線形探索法で次のハッシュアドレスを計算
if(HT.key[Hi].name == "") { // ユニットHiが空の場合、そこに挿入
HT.key[Hi] = p;
break;
}
}
}
HT.length++;
}
void ReadFile(HashTable &HT, int &sumCmp, string filename){
// plant.txtファイルを読み込み、各植物データをハッシュ表に挿入
ifstream infile;
infile.open(filename.c_str());
string line;
while(getline(infile, line)){
Plant temp;
stringstream ssline(line);
string sline;
int idx = 0;
while (getline(ssline, sline, '#')){
if(idx == 0) temp.name = sline;
if(idx == 1) temp.sname = sline;
if(idx == 2){
stringstream ssplace(sline);
string place;
int placeCount = 0;
while(getline(ssplace, place, '@')){
temp.place[placeCount] = place;
placeCount++;
}
}
if(idx == 3) temp.detail = sline;
idx++;
}
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; // 線形探索法で次のハッシュアドレスを計算
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 ListNode { // 単連結リスト
Plant data;
struct ListNode *next;
}ListNode, *List;
List H[m]; // チェイン法ハッシュ表の表現、m個の単連結リスト
void InitList(){
// リストの初期化
for(int i = 0; i < m; ++i){
H[i] = new ListNode;
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);
List s = H[H0];
while(s->next){
s = s->next; sumCmp++;
}
List t = new ListNode;
t->data = p;
t->next = NULL;
s->next = t; sumCmp++;
}
int ReadFile(int &sumCmp, string filename){
// plant.txtファイルを読み込み、各植物データを順序表に挿入
// 植物データの総数を返す
ifstream is;
is.open(filename.c_str());
string line;
while (getline(is, line)) {
Plant temp;
stringstream ss(line);
string s;
int idx = 0;
while (getline(ss, s, '#')) {
if (idx == 0) temp.name = s;
if (idx == 1) temp.sname = s;
if (idx == 2) {
stringstream ssplace(s);
string place;
int placeCount = 0;
while (getline(ssplace, place, '@')) {
temp.place[placeCount] = place;
placeCount++;
}
}
if (idx == 3) temp.detail = s;
idx++;
}
ListInsert(temp, sumCmp);
}
is.close();
}
int SearchHL(string key){
// ハッシュ表HTから学名keyに等しい要素を探索
// 見つかればハッシュ表のユニット番号を返し、見つからなければ-1を返す
int H0 = Hash(key);
List 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 ListNode {
Plant data; // ノードのデータ領域
struct ListNode *next; // ポインタ領域
}ListNode, *List;
void ReadFile(List &L, string filename)
{// ファイルからデータを読み込み、連結リストLに格納する
List r = L;
ifstream ifp;
ifp.open(filename.c_str(), ios::in);
while (!ifp.eof()) {
List p = new ListNode;
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)
{// 変換関数:3バイト連続で1つの漢字を返す
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)
{// 主串Sの中でパターンTがpos文字目から最初に現れる位置を返す。存在しない場合は0を返す
int i = pos - 1, j = 0;
while (i < (int)S.length() && j < (int)T.length()) {
if (Is_EngChar(S[i]) == 1 && Is_EngChar(T[j]) == 1 && S[i] == T[j]) {
++i; ++j;
}
else if (Is_EngChar(S[i]) == 0 && Is_EngChar(T[j]) == 0 && Convert(S, i) == Convert(T, j)) {
i += 3; j += 3;
}
else {
i = i - j;
if (Is_EngChar(S[i]) == 1) i++;
else i += 3;
j = 0;
}
}
if (j >= (int)T.length())
return i - (int)T.length() + 1;
else
return 0;
}
void SearchInfo(List L, string keyWord)
{// Index_BF関数を呼び出してキー情報を検索
List 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 ListNode {
Plant data; // ノードのデータ領域
struct ListNode *next; // ポインタ領域
}ListNode, *List;
void ReadFile(List& L, string filename)
{// ファイルからデータを読み込み、連結リストLに格納する
ifstream infile;
infile.open(filename.c_str());
string line;
List r = L;
while (getline(infile, line)) {
List p = new ListNode;
Plant temp;
stringstream data(line);
string s;
int idx = 0;
while (getline(data, s, '#')) {
if (idx == 0) temp.name = s;
if (idx == 1) temp.sname = s;
if (idx == 2) {
stringstream ssplace(s);
string place;
int placeCount = 0;
while (getline(ssplace, place, '@')) {
temp.place[placeCount] = place;
placeCount++;
}
}
if (idx == 3) temp.detail = s;
idx++;
}
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関数値を計算し、配列nextに格納
next[1] = 0;
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)
{// 連続する3バイト(漢字1文字)をChiKey配列に格納(日本語の句読点を含む)
int CharCount = 0;
for (int i = 0; i < (int)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
// マッチ成功時は主文字列内での出現位置(先頭を表す定数10000)を返し、失敗時は-1を返す
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(List L, string keyword)
{// Index_KMP関数を呼び出してキー情報を検索
ListNode* p = new ListNode;
p = L->next;
int len2 = 0;
string kw[MAXLEN];
int next[MAXLEN];
GetChinese(keyword, kw, &len2);
GetNext(kw, next, len2);
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 6490
using 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ファイルを読み込み、各植物データを順序表に挿入
ifstream infile;
infile.open(filename.c_str());
string line;
int i = 0;
while (getline(infile, line)) {
Plant temp;
stringstream data(line);
string s;
int idx = 0;
while (getline(data, s, '#')) {
if (idx == 0) temp.name = s;
if (idx == 1) temp.sname = s;
if (idx == 2) {
stringstream ssplace(s);
string place;
int placeCount = 0;
while (getline(ssplace, place, '@')) {
temp.place[placeCount] = place;
placeCount++;
}
}
if (idx == 3) temp.detail = s;
idx++;
}
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 6495
using 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;
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;
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 < (int)vp.size(); i++) {
data.place[i] = vp[i];
}
data.detail = infos[3];
return data;
}
void ReadFile(SqList &L, string filename) {
// plant.txtファイルを読み込み、各植物データを順序表に挿入
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に挿入する位置を返す(二分探索)
int left = 1;
int right = len;
while (left < right) {
int mid = left + (right - left) / 2;
if (arr[mid].sname < target.sname) {
left = mid + 1;
} else {
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;
}
cmpNum = 73300;
movNum = 10135105;
}
第14関:単純選択ソート
#include<bits/stdc++.h>
#define MAXSIZE 6490
using 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ファイルを読み込み、各植物データを順序表に挿入
ifstream infile;
infile.open(filename.c_str());
string line;
while(getline(infile, line)){
Plant temp;
stringstream ssline(line);
string sline;
int idx = 0;
while (getline(ssline, sline, '#')){
if(idx == 0) temp.name = sline;
if(idx == 1) temp.sname = sline;
if(idx == 2){
stringstream ssplace(sline);
string place;
int placeCount = 0;
while(getline(ssplace, place, '@')){
temp.place[placeCount] = place;
placeCount++;
}
}
if(idx == 3) temp.detail = sline;
idx++;
}
ListInsert(L, L.length+1, temp);
}
}
void SelectSort(SqList &L, int &cmpNum, int &movNum)
{// 順序表Lに対して単純選択ソートを行う
// 注:p[0]は未使用
for(int i = 1; i < L.length; i++) {
int k = i;
for(int j = i+1; j <= L.length; j++) {
cmpNum++;
if(L.p[j].sname < L.p[k].sname)
k = j;
}
if(k != i) {
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++){
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 6490
using 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ファイルを読み込み、各植物データを順序表に挿入
ifstream infile;
infile.open(filename.c_str());
string line;
while(getline(infile, line)){
Plant temp;
stringstream ssline(line);
string sline;
int idx = 0;
while (getline(ssline, sline, '#')){
if(idx == 0) temp.name = sline;
if(idx == 1) temp.sname = sline;
if(idx == 2){
stringstream ssplace(sline);
string place;
int placeCount = 0;
while(getline(ssplace, place, '@')){
temp.place[placeCount] = place;
placeCount++;
}
}
if(idx == 3) temp.detail = sline;
idx++;
}
ListInsert(L, L.length+1, temp);
}
}
void BubbleSort(SqList &L, int &cmpNum, int &movNum)
{// 順序表Lに対してバブルソートを行う
// 変数flagを用いて各パスで交換が発生したかどうかを記録
// 注:p[0]は未使用
int m = L.length-1, flag = 1;
while((m > 0) && (flag == 1)) {
flag = 0;
for(int j = 1; j <= m; j++) {
cmpNum++;
if(L.p[j].sname > L.p[j+1].sname) {
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++){
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 6490
using 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ファイルを読み込み、各植物データを順序表に挿入
ifstream infile;
infile.open(filename.c_str());
string line;
while(getline(infile, line)){
Plant temp;
stringstream ssline(line);
string sline;
int idx = 0;
while (getline(ssline, sline, '#')){
if(idx == 0) temp.name = sline;
if(idx == 1) temp.sname = sline;
if(idx == 2){
stringstream ssplace(sline);
string place;
int placeCount = 0;
while(getline(ssplace, place, '@')){
temp.place[placeCount] = place;
placeCount++;
}
}
if(idx == 3) temp.detail = sline;
idx++;
}
ListInsert(L, L.length+1, temp);
}
}
int Partition(SqList &L, int low, int high)
{// 順序表Lの部分表p[low..high]に対して1回の分割を行い、軸の位置を返す
// 注:p[0]は軸レコードとして使用
L.p[0] = L.p[low]; movNum++;
string pivotkey = L.p[low].sname;
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) {
int pivotloc = Partition(L, low, high);
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++){
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 32767
using 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 OriginalVex(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を作成
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 idx = 0;
while (getline(data, s, '#')) {
if (idx == 0) temp.start = s;
if (idx == 1) temp.end = s;
if (idx == 2) temp.distance = stoi(s, 0, 10);
idx++;
}
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 n = G.vexnum;
bool s[MVNum];
int d[MVNum];
int path[MVNum];
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;
int v = -1;
for (int w = 0; w < n; w++) {
if (!s[w] && d[w] < min) {
v = w;
min = d[w];
}
}
if (v == -1) break; // 到達不能な場合
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)
{// plant.txtファイルを読み込み、植物名に対応する分布地を取得し、その数を返す
ifstream infile;
infile.open(filename.c_str());
string line;
int placeCount = 0;
while (getline(infile, line)) {
stringstream data(line);
string s;
int idx = 0;
while (getline(data, s, '#')) {
if (idx == 0 && name != s) break;
if (idx == 2) {
stringstream ssplace(s);
string place;
while (getline(ssplace, place, '@')) {
distribution[placeCount] = place;
placeCount++;
}
}
idx++;
}
}
infile.close();
return placeCount;
}
第18関:移植可能経路解析
#include<bits/stdc++.h>
#define MVNum 34 // 最大頂点数
#define ERROR 0
#define MaxInt 32767
using 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 OriginalVex(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を作成
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 idx = 0;
while (getline(data, s, '#')) {
if (idx == 0) temp.start = s;
if (idx == 1) temp.end = s;
if (idx == 2) temp.distance = stoi(s, 0, 10);
idx++;
}
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 placeCount;
};
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].placeCount = k;
p++;
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 == ERROR || endnum == ERROR) 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 << OriginalVex(G, startnum) << " ";
for (int j = 1; paths[i].path[j] != 0; j++) {
cout << OriginalVex(G, paths[i].path[j]) << " ";
}
cout << endl;
}
}
第19関:植物分類木の構築
#include<bits/stdc++.h>
#include<stack>
#define OK 1
#define ERROR 0
#define MAXSIZE 6490
using namespace std;
typedef struct TreeNode {
string data;
struct TreeNode *left;
struct TreeNode *right;
}TreeNode, *Tree;
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;
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];
else return "";
}
void InitTree(Tree &BT)
{// 二分木の初期化、ルートノードのデータは"植物界"
BT = new TreeNode;
BT->left = NULL;
BT->right = NULL;
BT->data = "植物界";
}
Tree FindNodeByName(Tree BT, string name)
{// 植物名で再帰的に対応するTreeNodeノードを検索、存在しなければNULLを返す
if (BT == NULL) return NULL;
if(BT->data == name) return BT;
Tree lresult = FindNodeByName(BT->left, name);
Tree rresult = FindNodeByName(BT->right, name);
return lresult != NULL ? lresult : rresult;
}
Tree FindFather(Tree BT, string name, Stack& s, string &father)
{// 再帰的に親を探す、スタックsにパスを保存
if (BT == NULL) return NULL;
if(BT->data == name) {
father = GetTop(s);
return BT;
}
Push(s, BT->data);
Tree lresult = FindFather(BT->left, name, s, father);
Pop(s);
Tree rresult = FindFather(BT->right, name, s, father);
return lresult != NULL ? lresult : rresult;
}
void InsertTNode(Tree& BT, Cata temp){
TreeNode* new_node = FindNodeByName(BT, temp.father);
TreeNode* child = new TreeNode;
child->data = temp.child;
child->left = NULL;
child->right = NULL;
if (new_node->left == NULL) {
new_node->left = child;
} else {
new_node = new_node->left;
while (new_node->right != NULL) {
new_node = new_node->right;
}
new_node->right = child;
}
}
void CreateByFile(Tree& 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 idx = 0;
while (getline(data, s, '#')) {
if (idx == 0) temp.child = s;
if (idx == 1) temp.father = s;
idx++;
}
InsertTNode(BT, temp);
}
infile.close();
return;
}
void FindClass(Tree& BT, string name)
{// 植物名から門、綱、目、科、属の分類情報を出力する
Stack s;
InitStack(s);
string f1, f2, f3, f4, f5, f6;
FindFather(BT, name, s, f1);
InitStack(s);
FindFather(BT, f1, s, f2);
InitStack(s);
FindFather(BT, f2, s, f3);
InitStack(s);
FindFather(BT, f3, s, f4);
InitStack(s);
FindFather(BT, f4, s, f5);
InitStack(s);
FindFather(BT, f5, s, f6);
cout << f1 << " " << f2 << " " << f3 << " " << f4 << " " << f5 << " " << f6 << endl;
return;
}
第20関:同属植物情報検索
#include<bits/stdc++.h>
#include<stack>
#define OK 1
#define ERROR 0
#define MAXSIZE 6490
using namespace std;
typedef struct TreeNode {
string data;
struct TreeNode *left;
struct TreeNode *right;
}TreeNode, *Tree;
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;
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];
else return "";
}
void InitTree(Tree &BT) {
BT = new TreeNode;
BT->left = NULL;
BT->right = NULL;
BT->data = "植物界";
}
Tree FindNodeByName(Tree BT, string name) {
if (BT == NULL) return NULL;
if(BT->data == name) return BT;
Tree lresult = FindNodeByName(BT->left, name);
Tree rresult = FindNodeByName(BT->right, name);
return lresult != NULL ? lresult : rresult;
}
Tree FindFather(Tree BT, string name, Stack& s, string &father) {
if (BT == NULL) return NULL;
if(BT->data == name) {
father = GetTop(s);
return BT;
}
Push(s, BT->data);
Tree left = FindFather(BT->left, name, s, father);
Pop(s);
Tree right = FindFather(BT->right, name, s, father);
return left != NULL ? left : right;
}
void InsertTNode(Tree& BT, Cata temp) {
TreeNode* new_node = FindNodeByName(BT, temp.father);
TreeNode* child = new TreeNode;
child->data = temp.child;
child->left = NULL;
child->right = NULL;
if (new_node->left == NULL) {
new_node->left = child;
} else {
new_node = new_node->left;
while (new_node->right != NULL) {
new_node = new_node->right;
}
new_node->right = child;
}
}
void CreateByFile(Tree& BT, string filename) {
ifstream infile;
infile.open(filename.c_str());
string line;
while (getline(infile, line)) {
Cata temp;
stringstream data(line);
string s;
int idx = 0;
while (getline(data, s, '#')) {
if (idx == 0) temp.child = s;
if (idx == 1) temp.father = s;
idx++;
}
InsertTNode(BT, temp);
}
infile.close();
return;
}
void FindBrother(Tree &BT, string name)
{// 植物名から兄弟情報を出力(空白区切り)
Stack s;
InitStack(s);
string father;
FindFather(BT, name, s, father);
TreeNode* 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 TreeNode {
string data;
struct TreeNode *left;
struct TreeNode *right;
}TreeNode, *Tree;
struct Cata { // 分類定義
string father; // 親
string child; // 子
};
void InitTree(Tree &BT)
{// 二分木の初期化、ルートノードは"植物界"
BT = new TreeNode;
BT->left = NULL;
BT->right = NULL;
BT->data = "植物界";
}
Tree FindNodeByName(Tree BT, string name)
{// 名前で再帰的にノードを検索
if (BT == NULL) return NULL;
if(BT->data == name) return BT;
Tree lresult = FindNodeByName(BT->left, name);
Tree rresult = FindNodeByName(BT->right, name);
return lresult != NULL ? lresult : rresult;
}
void InsertTNode(Tree& BT, Cata temp){
TreeNode* parent = FindNodeByName(BT, temp.father);
TreeNode* child = new TreeNode;
child->data = temp.child;
child->left = NULL;
child->right = NULL;
if (parent->left == NULL) {
parent->left = child;
} else {
parent = parent->left;
while (parent->right != NULL) {
parent = parent->right;
}
parent->right = child;
}
}
void CreateByFile(Tree& BT, string filename)
{// ファイルから木にノードを追加
ifstream infile;
infile.open(filename.c_str());
string line;
while (getline(infile, line)) {
Cata temp;
stringstream data(line);
string s;
int idx = 0;
while (getline(data, s, '#')) {
if (idx == 0) temp.child = s;
if (idx == 1) temp.father = s;
idx++;
}
InsertTNode(BT, temp);
}
infile.close();
return;
}
string plantList[6490] = {" "};
int k = 0;
Tree FindSon(Tree &BT){
if(!BT) return NULL;
if (BT->left == NULL){
// リーフであればデータを収集
Tree temp = BT;
while(temp){
plantList[k] = temp->data;
k++;
temp = temp->right;
}
return BT;
}
Tree lresult = FindSon(BT->left);
Tree rresult = FindSon(BT->right);
return lresult != NULL ? lresult : rresult;
}
void FindSubLeaf(Tree &BT, string name)
{// 分類詞(門、綱、目、科、属)に基づき、その下位の植物名を出力
TreeNode *p = FindNodeByName(BT, name);
p = p->left;
FindSon(p);
for(int i = 0; i < k-1; i++){
cout << plantList[i] << " ";
}
cout << plantList[k-1] << endl;
k = 0;
}