普通二叉树

首先是二叉树的结构,假如数据用以下方式给出:

第一行一个整数n​​​​​​​​​​​​​​​(1≤n≤50​​​​​​​​​​​),表示二叉树的结点个数;

接下来n​​行,每行一个结点,按顺序给出编号从0到n-1的结点的左子结点编号和右子结点编号,中间用空格隔开。如果不存在对应的子结点,那么用-1表示。

6
2 5
-1 -1
1 4
-1 -1
-1 -1
-1 3

那么模板如下:

struct Node{
	Node* left = NULL;
	Node* right = NULL;
	int val = -1;
	Node(int x){
		val = x;
		left = NULL;
		right = NULL;
	}	
};

//结点表,存储第i号结点(val不一定和i相同)
vector<Node*> nodes;
int main(){
    int n;cin>>n;
    for(int i = 0 ; i < n; i++){
        //默认为无效的结点,因此val为-1
        //无效结点的判定为nodes[i] == -1; 相当于lc中的node == NULL;
  		Node* tnode = new Node(-1);
  		nodes.push_back(tnode);
  	}
  	for(int i = 0; i < n; i++){
        //为结点赋予逻辑意义,如果是明确指定值的结构可能需要另外赋值
  		nodes[i]->val = i;
  		int left,right; cin >> left >> right;
  		if(left != -1){
  			nodes[i]->left = nodes[left];
  		}
  		if(right != -1){
  			nodes[i]->right = nodes[right];
  		}
  	}
}

图的邻接表/逆邻接表

自己写题的时候不用过分考虑空间上的利用率,因此大部分情况我们可以用同一套模板,把记录出点和入点的表都写上:

struct Node{
	int val;
    //出入边表,记录出点和入点的编号
	vector<int>	oedge;
	vector<int>	iedge;
	Node(int x){
		val = x;
	}
};

vector<Node*> nodes;
int main() {
	int n,m; cin >> n >> m;
	for(int i = 0; i < n; i++){
		Node* tnode = new Node(i);
		nodes.push_back(tnode);
	}
	for(int i = 0; i < m; i++){
		int a,b; cin >> a >> b;
		nodes[a]->oedge.push_back(b);
		nodes[b]->iedge.push_back(a);
	}
	return 0;
}