PAT之链表和构建树

这篇文章是关于PAT的一个总复习,整理以备复习参考。

🍔关于链表

链表题目中总是会出现地址的保存,如:地址,data,下一个地址

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

A1074 Reversing Linked List 是对要求对链表进行反转;A1032 Sharing要找到一个相同地址的符号;类似还有A1052Linked List Sorting,A1097Deduplication on a Linked List

解决这类问题,就建立两个vector,一个用于暂存数据 ,一个用于最后的答案数据保存。

A1133:小于0的放到最前,介于0~k的依次后放,其余的再依次后放模板案例如下:

#include <iostream>
#include <vector>
using namespace std;
struct node{
    int id,data,next;
}a[100005];
int main(){
    int begin,n,k,s,d,e;
    cin>>begin>>n>>k;
    vector<node> v,ans;
    for(int i=0;i<n;++i){
        scanf("%d%d%d",&s,&d,&e);
        a[s]={s,d,e};
    }
    for(;begin!=-1;begin=a[begin].next){
        v.push_back(a[begin]);
    }
    for(int i=0;i<v.size();++i){
        if(v[i].data<0) ans.push_back(v[i]);
    }
    for(int i=0;i<v.size();++i){
        if(v[i].data>=0&&v[i].data<=k) ans.push_back(v[i]);
    }
    for(int i=0;i<v.size();++i){
        if(v[i].data>k) ans.push_back(v[i]);
    }
    for(int i=0;i<ans.size();++i){
        if(i!=ans.size()-1) printf("%05d %d %05d\n",ans[i].id,ans[i].data,ans[i+1].id);
        else printf("%05d %d -1",ans[i].id,ans[i].data);
    }
    return 0;
}

🥩二叉树的构建

1.前中构建🍭

struct node{
    int data;
    node *lchild,*rchild;
};
int pre[maxn],in[maxn];
node*build(int preL,int preR,int inL,int inR){
    if(preL>preR) return NULL;
    node*root=new node;
    root->data=pre[preL];
    int k;
    for(k=inL;k<=inR;++k){
        if(in[k]==pre[preL]) break;
    }
    int numLeft=k-inL;
    root->lchild=build(preL+1,preL+numLeft,inL,k-1);
    root->rchild=build(preL+numLeft+1,preR,k+1,inR);
    return root;
}

2.后中构建🍡

struct node{
    int data;
    node *lchild,*rchild;
};
int post[maxn],in[maxn];
node*build(int postL,int postR,int inL,int inR){
    if(postL>postR) return;
    node*root=new node;
    root->data=post[postR];
    int k;
    for(k=inL;k<=inR;++k){
        if(in[k]==post[postR]) break;
    }
    int numLeft=k-inL;
    root->lchild=build(postL,postL+numLeft-1,inL,k-1);
    root->rchild=build(postL+numLeft,postR-1,k+1,inR);
    return root;
}

3.层中构建🍢

struct node{
    int data;
    node *lchild,*rchild;
};
int level[maxn],in[maxn];
node*build(int levelL,int levelR,int inL,int inR){
    if(inL>inR) return NULL;
    int k,flag=0;
    while(levelL<=levelR){
        for(k=inL;k<=inR;++k){
            if(in[k]==level[levelL]){
                flag=1;
                break;
            }
        }
        if(flag) break;
        ++levelL;
    }
    node*root=new node;
    root->data=in[k];
    root->lchild=build(levelL+1,levelR,inL,k-1);
    root->rchild=build(levelL+1,levelR,k+1,inR);
}

4.构建不唯一的二叉树

参见A119

#include <iostream>
#include <vector>
using namespace std;
vector<int> in,pre,post;
bool flag=true;
void getIn(int prel,int  prer,int postl,int postr){
    if(prel==prer){
        in.push_back(pre[prel]);
        return;
    }
    if(pre[prel]==post[postr]){
        int i=prel+1;
        while(i<prer&&pre[i]!=post[postr-1]) ++i;
        if(i-prel>1){
            getIn(prel+1,i-1,postl,postl+(i-prel-1)-1);
        }else flag=false;
        in.push_back(post[postr]);
        getIn(i,prer,postl+(i-prel-1),postr-1);
    }
}
int main(){
    int n;
    cin>>n;
    pre.resize(n),post.resize(n);
    for(int i=0;i<n;++i) cin>>pre[i];
    for(int i=0;i<n;++i) cin>>post[i];
    getIn(0,n-1,0,n-1);
    printf("%s\n%d",flag==true?"Yes":"No",in[0]);
    for(int i=1;i<in.size();++i) printf(" %d",in[i]);
    printf("\n");
    return 0;
}

5.关于通用二叉树的构建🥣

🍎很多的题目中构建的二叉树需要很多信息,比如一个节点的高度、节点的父节点、两个节点是不是兄弟节点、甚至一个二叉树是不是完全二叉树。

19年春季考试第四题详细考察了这一问题

我们采用静态二叉树的存储实现:

#include <iostream>
#include <vector>
#include <string>
using namespace std;
const int maxn=1000;
struct node{
    int layer;
    int left,right,parent;
};
node btree[maxn];
int root;
bool isFullTree=true;
int n,m;
int post[maxn],in[maxn];
void inputData(){
    cin>>n;
    for(int i=0;i<n;++i) scanf("%d",post+i);
    for(int i=0;i<n;++i) scanf("%d",in+i);
}
int mfind(int start,int end,int key){
    for(int i=start;i<=end;++i){
        if(in[i]==key) return i;
    }
    return -1;
}
int create(int parent,int pl,int pr,int inl,int inr){
    if(inl>inr) return -1;
    int key=post[pr];
    int mid=mfind(inl,inr,key);
    if(parent==-1){
        btree[key].layer=0;
        root=key;
    }else{
        btree[key].parent=parent;
        btree[key].layer=btree[parent].layer+1;
    }
    btree[key].left=create(key,pl,pl+mid-inl-1,inl,mid-1);
    btree[key].right=create(key,pl+mid-inl,pr-1,mid+1,inr);
    if((btree[key].left==-1&&btree[key].right!=-1)||(btree[key].right==-1&&btree[key].left!=-1)){
        isFullTree=false;
    }
    return key;
}
int  main(){
    inputData();
    create(-1,0,n-1,0,n-1);
    string comm;
    int a,b;
    bool flag=true;
    cin>>m;
    getchar();
    for(int i=0;i<m;++i){
        getline(cin,comm);
        if(comm.find("root")!=-1){
            sscanf(comm.c_str(),"%d is the root",&a);
            flag=(root==a);
        }else if(comm.find("siblings")!=-1){
            sscanf(comm.c_str(),"%d and %d are siblings",&a,&b);
            flag=(btree[a].parent==btree[b].parent);
        }else if(comm.find("parent")!=-1){
            sscanf(comm.c_str(),"%d is the parent of %d",&a,&b);
            flag=(a==btree[b].parent);
        }else if(comm.find("left")!=-1){
            sscanf(comm.c_str(),"%d is the left child of %d",&a,&b);
            flag=(a==btree[b].left);
        }else if(comm.find("right")!=-1){
            sscanf(comm.c_str(),"%d is the right child of %d",&a,&b);
            flag=(a==btree[b].right);
        }else if(comm.find("level")!=-1){
            sscanf(comm.c_str(),"%d and %d are on the same level",&a,&b);
            flag=(btree[a].layer==btree[b].layer);
        }else if(comm.find("full")!=-1){
            flag=isFullTree;
        }
        if(flag) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

希望大家千万千万不要小看二叉树的静态存储结构,不要盲目相信指针是最好的。共勉!🍓🍓🍓🍓

🍋AVL树的构建🍋

AVL树的构建也比较重要,重点的地方在于插入的时候的平衡要记住。

struct node{
    int v,height;
    node *lchild,*rchild;
};
node*newNode(int v){
    node*root=new node;
    root->v=v;
    root->height=1;
    root->lchild=root->rchild=NULL;
    return root;
}
int getHeight(node*root){
    if(root==NULL) return 0;
    return root->height;
}
int getBalanceFactor(node*root){
    return getHeight(root->lchild)-getHeight(root->rchild);
}
void updateHeight(node*root){
    root->height=max(getHeight(root->lchild),getHeight(root->rchild))+1;
}
void L(node*&root){
    node*temp=root->rchild;
    root->rchild=temp->lchild;
    temp->lchild=root;
    updateHeight(root);
    updateHeight(temp);
    root=temp;
}
void R(node*&root){
    node*temp=root->lchild;
    root->lchild=temp->rchild;
    temp->rchild=root;
    updateHeight(root);
    updateHeight(temp);
    root=temp;
}
void insert(node*&root,int v){
    if(root==NULL){
        root=newNode(v);
        return;
    }
    if(v<root->v){
        insert(root->lchild,v);
        updateHeight(root);
        if(getBalanceFactor(root)==2){
            if(getBalanceFactor(root->lchild)==1){
                R(root);
            }else if(getBalanceFactor(root->lchild)==-1){
                L(root->lchild);
                R(root);
            }
        }
    }else{
        insert(root->rchild,v);
        updateHeight(root);
        if(getBalanceFactor(root)==-2){
            if(getBalanceFactor(root->right)==-1){
                L(root);
            }else if(getBalanceFactor(root->right)==1){
                R(root->right);
                L(root);
            }
        }
    }
}
node*create(int data[],int n){
    node*root=NULL;
    for(int i=0;i<n;++i){
        insert(root,data[i]);
    }
    return root;
}

🥗堆排序🥗

堆是完全二叉树

int heap[maxn],n=10;
void downAdjust(int low,int high){//自顶向下
    int i=low,j=2*i;
    while(j<=high){//有孩子节点
        if(j+1<=high&&heap[j+1]>heap[j]){//右孩子存在,且大于左孩子,则j指向右孩子
            ++j;
        }
        if(heap[j]>heap[i]){//如果孩子比父亲节点大,则交换
            swap(heap[j],heap[i]);
            i=j;
            j=2*i;
        }else break;//如果小,则结束
    }
}
void create(){//建堆
    for(int i=n/2;i>=1;--i){
        downAdjust(i,n);
    }
}
void heapSort(){//堆排序
    create();
    for(int i=n;i>1;--i){
        swap(heap[i],heap[1]);
        downAdjust(1,i-1);
    }
}
void deleteTop(){//删除堆顶元素
    heap[1]=heap[n--];
    downAdjust(1,n);
}
void upAdjust(int low,int high){//自底向上是插入
    int i=high,j=i/2;
    while(j>=low){
        if(heap[j]<heap[i]){
            swap(heap[j],heap[i]);
            i=j;
            j=i/2;
        }else break;
    }
}
void insert(int x){
    heap[++n]=x;
    upAdjust(1,n);
}
posted @ 2020-09-03 23:57  sszz_w  阅读(119)  评论(0编辑  收藏  举报