PAT常用模板梳理

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,當出現一個結點存在空子樹的時候,其後續訪問的結點的子樹必須均爲空。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章