1. 程式人生 > 實用技巧 >[PAT] A1110 Complete Binary Tree

[PAT] A1110 Complete Binary Tree

完全二叉樹

題目大意

給出各個結點的左右孩子,問這棵樹是不是完全二叉樹,若是則輸出YES和最後一個結點編號;若不是則輸出NO和根節點編號。N個結點編號0~N-1。

思路

結構體陣列儲存樹,為了找到根節點,輸入時用bool陣列ifchild記錄,若有孩子,則該孩子的ifchild值為true,最後不是ture的就是根節點。根據父子關係遍歷一遍該樹,求出最大下標的和n比較。求最大下標的時候順便儲存其對應的結點編號。(一開始自己寫的複雜程式碼是:儲存每個下標,並將該下標再建立一個bool型陣列標記是否填入下標值,若最後沒有標記則是非完全二叉樹。但這樣非常多餘,不必儲存每個下標。)

改進

(1) string轉到整數有stoi(str)函式,無需手寫,但要保證string裡面都是數字!!!
(2) 完全二叉樹一定把前面的下標充滿,即:最大的下標值 == 最大的節點數;不完全二叉樹前滿一定有位置是空,會往後擠:最大的下標值 > 最大的節點數。根據這個可以直接在遞迴中求出最大下標,無需儲存。

tips

一定要注意輸入有數字和符號的情況,統一用string輸入然後stoi。有可能數字不止一位數!!!

AC程式碼

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
#define N 200
struct Node {
	int lchild, rchild;
}node[N];
bool ifchild[N] = { false };
int maxvalue = 0, maxid;
void pre(int root, int index) {
	if (maxvalue < index) {
		maxvalue = index; maxid = root;
	}
	if (node[root].lchild != -1)pre(node[root].lchild, index * 2);
	if (node[root].rchild != -1)pre(node[root].rchild, index * 2 + 1);
}
int main() {
	int i, n;
	scanf("%d", &n);
	for (i = 0;i < n;i++) {
		string s_tleft, s_tright;
		cin >> s_tleft >> s_tright;
		if (s_tleft == "-")node[i].lchild = -1;
		else {
			node[i].lchild = stoi(s_tleft);
			ifchild[node[i].lchild] = true;
		}
		if (s_tright == "-")node[i].rchild = -1;
		else {
			node[i].rchild = stoi(s_tright);
			ifchild[node[i].rchild] = true;
		}	
	}
	int root = 0;
	for (i = 0;i < n;i++)
		if (ifchild[i] == false) {
			root = i;
			break;
		}
	if (n != 0)pre(root, 1);
	if (maxvalue != n) printf("NO %d", root);
	else printf("YES %d", maxid);	
	return 0;
}

初次程式碼:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
#define N 200
struct Node {
	int lchild, rchild, index;
}node[N];
bool ifchild[N] = { false }, ifindex[N + 1] = { false };
int maxvalue = 0, maxid;
int strtoint(string a) {
	if (a == "-")return -1;
	else {
		int ans = 0;
		for (int i = 0;i < a.size();i++) {
			ans = ans * 10 + a[i] - '0';
		}
		return ans;
	}
}
void pre(int root, int index) {
	node[root].index = index;
	ifindex[index] = true;
	if (maxvalue < index) {
		maxvalue = index; maxid = root;
	}
	if (node[root].lchild != -1)pre(node[root].lchild, index * 2);
	if (node[root].rchild != -1)pre(node[root].rchild, index * 2 + 1);
}
int main() {
	int i, n;
	scanf("%d", &n);
	for (i = 0;i < n;i++) {
		string s_tleft, s_tright;
		cin >> s_tleft >> s_tright;
		int tleft = strtoint(s_tleft), tright = strtoint(s_tright);
		if (tleft >= 0 && tleft < N) {
			node[i].lchild = tleft;
			ifchild[tleft] = true;
		}
		else node[i].lchild = -1;
		if (tright >= 0 && tright < N) {
			node[i].rchild = tright;
			ifchild[tright] = true;
		}
		else node[i].rchild = -1;
	}
	int root = 0;
	for (i = 0;i < n;i++)
		if (ifchild[i] == false) {
			root = i;
			break;
		}
	if (n != 0)pre(root, 1);
	i = 1;
	while (ifindex[i] && i <= n)i++;
	if (i != n + 1) printf("NO %d", root);
	else printf("YES %d", maxid);	
	return 0;
}