PAT常用模板梳理
1.DFS+Dijkstra
(description): 最短路徑問題,如果約束條件不復雜的話直接寫個Dijkstra就可以了。如果約束條件比較複雜的話那麼可以先利用Dijkstra把所有搜索到的可疑路徑先用圖的結構存儲起來,然後再採用dfs進行搜索。
void Dijkstra(int n){//利用Dijkstra把所有滿足cost最小的路徑採用pre[N]的鄰接鏈表結構進行存儲
int newP = st;
fill(dis,dis+n,inf);
fill(mark,mark+n,false);
dis[newP] = 0;
mark[newP] = true;
int T=n;
while(T--){
for(int i=0;i<Vec[newP].size();i++){
int tmp_v = Vec[newP][i].v;
int tmp_c = Vec[newP][i].c;
if(mark[tmp_v])continue;
if(dis[newP]+tmp_c<dis[tmp_v]){
dis[tmp_v] = dis[newP]+tmp_c;
pre[tmp_v].clear();
pre[tmp_v].push_back(newP);
}
else if(dis[newP]+tmp_c==dis[tmp_v]){//處理多條結果相同的路徑
pre[tmp_v].push_back(newP);
}
}
int minn = inf;
for(int i=0;i<n;i++){
if(!mark[i]&&dis[i]<minn){
newP = i;minn = dis[i];
}
}
mark[newP]=true;
}
}
void dfs(int x){//利用dfs對鄰接鏈表pre進行搜索,以此判斷每一條路徑是否滿足條件
tmp.push_back(x);
if(x==target){
judge and calculate
}
for(int i=0;i<pre[x].size();i++)dfs(pre[x]);
tmp.pop_back();
}
2.並查集
description:並查集一般用於處理集合的相關問題。
fill(Tree,Tree+n,-1);
int findRoot(int x){//查找根結點
if(Tree[x]==-1)
return x;
else
return Tree[x]=findRoot(Tree[x]);
}
void Union(int x,int y){//合併兩個結點所在的集合
int rootA = findRoot(x);
int rootB = findRoot(y);
if(rootA!=rootB)
Tree[rootA]=rootB;
}
同時能用並查集解決的方法一般也可以採用dfs進行解決,以判斷一個圖中聯通域的個數爲例。
void dfs(int x){
if(!vis[x])
vis[x]=true;
for(int i=0;i<Vec[x].size();i++)
dfs(Vec[x][i]);
}
int main(){
int cnt=0;
for(int i=0;i<n-1;i++){
if(!vis[i]){
dfs(i);
cnt++;
}
}
}
3.樹的創建
對於:
①前序+中序->後序/層序 以及 後序+中序->前序/層序 均不需要進行建樹
②對於BST,CBT以及AVL Tree的相關操作需要進行建樹。
前序+中序->後序
int Pre[N],In[N];
vector<int> Post;
int build(int sp,int ep,int si,int ei){
if(sp>ep)return;
int i=si;
while(i<=ei&&In[i]!=Pre[sp])i++;
int len = i-si;
build(sp+1,sp+len,si,i);
build(sp+len+1,ep,i+1,ei);
Post.push_back(Pre[sp]);
return sp;
}
後序+中序->層序
//PAT 1020
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
const int N = 30+5;
int Post[N],In[N],n;
vector<int>Vec;
map<int,int>Ma;
bool cmp(int a,int b){return Ma[a]<Ma[b];}
void build(int ist,int ied,int pst,int ped,int idx){
if(ist>ied)return;
int i=ist;
while(i<=ied&&In[i]!=Post[ped])i++;
int len = i-ist;
Vec.push_back(Post[ped]);Ma[Post[ped]]=idx;
build(ist,i-1,pst,pst+len-1,2*idx+1);
build(i+1,ied,pst+len,ped-1,2*idx+2);
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)cin>>Post[i];
for(int i=0;i<n;i++)cin>>In[i];
build(0,n-1,0,n-1,0);
sort(Vec.begin(),Vec.end(),cmp);
for(int i=0;i<n;i++){
cout<<Vec[i];
if(i!=n-1)cout<<" ";
}
return 0;
}
/*
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
*/
BST的構建
Vec[root] = data;
void Insert(int root,int x){
if(Vec[root]<x){
if(Vec[root][0]==-1)
Vec[root][0]=x;
else
Insert(Vec[root][0],x);
}
else{
if(Vec[root][1]==-1)
Vec[root][1]=x;
else
Insert(Vec[root][1],x);
}
}
AVL樹的構建
struct Node{
Node *l,*r;
int data;
};
Node* leftRotate(Node*tree){
Node* tmp = tree->r;
tree->r = tmp->l;
tmp->l = tree;
return tmp;
}
Node* rightRotate(Node*tree){
Node* tmp = tree->l;
tree->l = tmp->r;
tmp->r = tree;
return tmp;
}
Node* leftRightRotate(Node*tree){
tree->l = leftRotate(tree->l);
return rightRotate(tree);
}
Node* rightLeftRotate(Node*tree){
tree->r = rightRotate(tree->r);
return leftRotate(tree);
}
int getHeight(Node*tree){
if(tree==NULL)
return 0;
else
return max(getHeight(tree->l,tree->r))+1;
}
void Insert(Node*tree,int x){
if(tree==NULL){
tree = new Node;
tree->data = x;
}
else if(tree->data<x){
Insert(tree->l,x);
int lh = getHeight(tree->l);
int rh = getHeight(tree->r);
if(lh-rh>1){
if(x<tree->l->data){
tree = rightRotate(tree);
}
else{
tree = leftRightRotate(tree);
}
}
}
else{
Insert(tree->r,x);
int lh = getHeight(tree->l);
int rh = getHeight(tree->r);
if(rh-lh>1){
if(x>tree->l->data){
tree = leftRotate(tree);
}
else{
tree = rightLeftRotate(tree);
}
}
}
}
判斷某一棵樹是否是完全二叉樹
判定方法:進行分level order travelsal,當出現一個結點存在空子樹的時候,其後續訪問的結點的子樹必須均爲空。