資料結構與演算法題目集7-27——家譜處理
我的資料結構與演算法題目集程式碼倉:https://github.com/617076674/Data-structure-and-algorithm-topic-set
原題連結:https://pintia.cn/problem-sets/15/problems/842
題目描述:
知識點:字串處理
思路:對5種關係寫5個判斷函式
在讀取資料過程中,需要儲存3個資訊,一個map<string, int>型變數stringToInt,代表名字對應的編號,編號從0開始;一個char型二維陣列intToString[100][11],代表編號對應的名字;一個int型陣列spaces[100],代表每行對應的空格數,行號即改行名字對應的編號,顯然也是從0開始。
為了讀取每行第一個字元前的空格數量,我選擇了getchar()函式一個個字元地讀取,對空格數量進行計數,讀取每一行就更新上述三個變數。注意,二維char型陣列的賦值需要用到<cstring>標頭檔案中的strcpy()函式。
對於待判斷語句的讀取,考慮到每個語句都由6個字串組成,由5個空格分隔,我用6個char型陣列變數str1 ~ str6,分別儲存這6個字串的資訊。其中str1和str6分別代表名字,str4代表待判斷的關係。將str1和str6分別轉換成行號line1和line2,再根據str4的關係選擇判斷函式,判斷該語句是否正確。判斷函式有以下5個:
(1)x是否是y的孩子
a:如果x前面的空格數減去2不等於y前面的空格數,顯然x不是y的孩子。
b:如果x < y,顯然x不是y的孩子。
c:如果在行號(y, x]之間,存在某一行,其前面的空格數小於x前面的空格數,x不是y的孩子。這種情況類似於樣例中的"David"和"Robert"的關係。
d:除去以上3種情況外,我們可以判斷x是y的孩子。
(2)x是否是y的父母
a:如果x前面的空格數加上2不等於y前面的空格數,顯然x不是y的父母。
b:如果x > y,顯然x不是y的父母。
c:如果在行號(x, y]之間,存在某一行,其前面的空格數小於y前面的空格數,x不是y的父母。這種情況類似於樣例中的"David"和"Robert"的關係。
d:除去以上3種情況外,我們可以判斷x是y的父母。
(3)x是否是y的兄弟姐妹
a:如果x和y前面的空格數不相等,x不是y的兄弟姐妹。
b:假設x < y,在(x, y)範圍內,如果存在某一行,其前面的空格數小於y前面的空格數,x不是y的兄弟姐妹。這種情況類似於樣例中"David"和"Andrew"的關係。
c:除去以上2種情況外,我們可以判斷x是y的兄弟姐妹。
(4)x是否是y的後代
a:如果x前面的空格數小於y前面的空格數,顯然x不是y的後代。
b:如果x < y,顯然x不是y的後代。
c:從y + 1行開始,直到某一行,該行前面的空格數和y行前面的空格數相等,如果在這個過程中發現了編號x,x是y的後代;否則,x不是y的後代。
(5)x是否是y的祖先
a:如果x前面的空格數大於y前面的空格數,顯然x不是y的祖先。
b:如果x > y,顯然x不是y的祖先。
c:從x + 1行開始,直到某一行,該行前面的空格數和x行前面的空格數相等,如果在這個過程中發現了編號y,x是y的祖先;否則,x不是y的祖先。
時間複雜度和查詢語句的兩個名字對應的編號間距有關。空間複雜度是O(100 * 11)。
C++程式碼:
#include<iostream>
#include<map>
#include<string>
#include<cstring>
using namespace std;
int N, M;
map<string, int> stringToInt; //名字編號,從0開始編號
char intToString[100][11]; //編號對應的名字,和stringToInt編號一致,也是從0開始編號
int spaces[100]; //每行對應的空格數,從0行開始計數
bool x_child_y(int x, int y);
bool x_parent_y(int x, int y);
bool x_sibling_y(int x, int y);
bool x_descendant_y(int x, int y);
bool x_ancestor_y(int x, int y);
int main() {
scanf("%d %d", &N, &M);
getchar();
for(int i = 0; i < N; i++) {
char c;
int space = 0;
while((c = getchar()) == ' ') {
space++;
}
char name[11];
name[0] = c;
int index = 1;
while((c = getchar()) != '\n') {
name[index++] = c;
}
name[index] = '\0';
stringToInt[name] = i;
strcpy(intToString[i], name);
spaces[i] = space;
}
for(int i = 0; i < M; i++){
char str1[11], str2[3], str3[4], str4[11], str5[3], str6[11];
scanf("%s %s %s %s %s %s", str1, str2, str3, str4, str5, str6);
int line1 = stringToInt[str1];
int line2 = stringToInt[str6];
if(strcmp(str4, "child") == 0){
if(x_child_y(line1, line2)){
printf("True\n");
}else{
printf("False\n");
}
}else if(strcmp(str4, "parent") == 0){
if(x_parent_y(line1, line2)){
printf("True\n");
}else{
printf("False\n");
}
}else if(strcmp(str4, "sibling") == 0){
if(x_sibling_y(line1, line2)){
printf("True\n");
}else{
printf("False\n");
}
}else if(strcmp(str4, "descendant") == 0){
if(x_descendant_y(line1, line2)){
printf("True\n");
}else{
printf("False\n");
}
}else if(strcmp(str4, "ancestor") == 0){
if(x_ancestor_y(line1, line2)){
printf("True\n");
}else{
printf("False\n");
}
}
}
return 0;
}
bool x_child_y(int x, int y){
if(spaces[x] - 2 != spaces[y]){
return false;
}
if(x < y){
return false;
}
for(int i = y + 1; i <= x; i++){
if(spaces[i] < spaces[x]){
return false;
}
}
return true;
}
bool x_parent_y(int x, int y){
if(spaces[x] + 2 != spaces[y]){
return false;
}
if(x > y){
return false;
}
for(int i = x + 1; i <= y; i++){
if(spaces[i] < spaces[y]){
return false;
}
}
return true;
}
bool x_sibling_y(int x, int y){
if(spaces[x] != spaces[y]){
return false;
}
if(x > y){
swap(x, y);
}
for(int i = x + 1; i <= y; i++){
if(spaces[i] < spaces[y]){
return false;
}
}
return true;
}
bool x_descendant_y(int x, int y){
if(spaces[x] < spaces[y]){
return false;
}
if(x < y){
return false;
}
int index = y + 1;
while(true){
if(spaces[index] == spaces[y]){
return false;
}
if(index == x){
return true;
}
index++;
}
}
bool x_ancestor_y(int x, int y){
if(spaces[x] > spaces[y]){
return false;
}
if(x > y){
return false;
}
int index = x + 1;
while(true){
if(spaces[index] == spaces[x]){
return false;
}
if(index == y){
return true;
}
index++;
}
}
C++解題報告: