1. 程式人生 > >【資料結構高分筆記題目整理】

【資料結構高分筆記題目整理】

【題意】


    如上所示,由正整數1,2,3……組成了一顆特殊二叉樹。我們已知這個二叉樹的最後一個結點是n。現在的問題是,結點m所在的子樹中一共包括多少個結點。

    比如,n = 12,m = 3那麼上圖中的結點13,14,15以及後面的結點都是不存在的,結點m所在子樹中包括的結點有3,6,7,12,因此結點m的所在子樹中共有4個結點。

【解題思路】

用l和r分別儲存這個結點下一層的最左和最右結點,每一層結點的數目都是上一層*2,所以用cnt記數,當r大於等於n時跳出迴圈,說明現在已經到達所需的結點的那一層,即原結點數+所需結點-最左結點+1即為最後的結點數。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,m;
    while(~scanf("%d%d",&m,&n) && n || m)
    {
        int ans=1,l=2*m,r=2*m+1,cnt=1;
        while(r<n)
        {
            cnt=cnt*2;
            ans+=cnt;
            l=l*2;
            r=r*2+1;
        }
        if(l<=n)ans+=n-l+1;
        printf("%d\n",ans);
    }
    return 0;
}

【題意】

給定一棵二叉樹的前序遍歷和中序遍歷,求其後序遍歷(提示:給定前序遍歷與中序遍歷能夠唯一確定後序遍歷)。

【解題思路】

root為當前子樹的根結點在前序pre中的下標,left和rigtht為當前子樹的最左邊和最右邊的結點在中序in中的下標。用i找到當前子樹的根結點root在中序中的下標,然後左邊和右邊就分別為當前根結點root的左子樹和右子樹,然後遞迴實現。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
char pre[30],in[30];
int n;
vector<char>v;
void dfs(int root,int left,int right)
{
    if(left>right)return;
    int i=left;
    while(pre[root]!=in[i])i++;
    if(i>n)return;
    dfs(root+1,left,i-1);
    dfs(root+1+i-left,i+1,right);
    v.push_back(pre[root]);
}
int main()
{
    while(~scanf("%s%s",pre,in))
    {
        n=strlen(pre)-1;
        dfs(0,0,n);
        for(int i=0;i<v.size();i++)
            printf("%c",v[i]);
        printf("\n");
        memset(pre,0,sizeof(pre));
        memset(in,0,sizeof(in));
        v.clear();
    }
    return 0;
}

【題意】

有一棵樹,輸出某一深度的所有節點,有則輸出這些節點,無則輸出EMPTY。該樹是完全二叉樹。

【程式碼】

這題被自己蠢哭qaq題目還是簡單的辣

1.注意是完全二叉樹不是滿二叉樹,所以最後一層的葉子節點數不一定是滿的,在輸出節點時需要加上條件i<=n

2.因為完全二叉樹的最大高度h為log2(n)向下取整+1,所以只需判斷m和h的大小即可

【解題思路】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
int a[maxn];
int main()
{
    int n,m;
    while(~scanf("%d",&n) && n)
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        scanf("%d",&m);
        int h=floor(log(n)/log(2))+1;
        if(m>h)printf("EMPTY\n");
        else
        {
            int l=pow(2,m-1),r=pow(2,m);
            printf("%d",a[l]);
            for(int i=l+1;i<r && i<=n;i++)
                printf(" %d",a[i]);
            printf("\n");
        }
    }
    return 0;
}

【題意】

輸入一系列整數,建立二叉排序樹,並進行前序,中序,後序遍歷。

【解題思路】

模板題,注意一下輸出即可。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
typedef struct Node
{
    int data;
    struct Node* left,*right;
}Node,*PNode;
PNode insertBST(PNode root,int x)
{
    if(root==NULL)
    {
        root=new Node();
        root->data=x;
        root->left=NULL;
        root->right=NULL;
        return root;
    }
    else if(x<root->data)
        root->left=insertBST(root->left,x);
    else if(x>root->data)
        root->right=insertBST(root->right,x);
    return root;
}
void preorder(PNode root)
{
    if(root==NULL)return;
    printf("%d ",root->data);
    preorder(root->left);
    preorder(root->right);
}
void inorder(PNode root)
{
    if(root==NULL)return;
    inorder(root->left);
    printf("%d ",root->data);
    inorder(root->right);
}
void postorder(PNode root)
{
    if(root==NULL)return;
    postorder(root->left);
    postorder(root->right);
    printf("%d ",root->data);
}
PNode findMax(PNode root)
 {
    if(root!=NULL)                   //非遞迴查詢
        while(root->right!=NULL)
            root=root->right;
    return root;
 }
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        PNode root=NULL;
        for(int i=0;i<n;i++)
        {
            int x;
            scanf("%d",&x);
            root=insertBST(root,x);
        }
        preorder(root);
        printf("\n");
        inorder(root);
        printf("\n");
        postorder(root);
        printf("\n");
    }
    return 0;
}

【題意】

判斷兩序列是否為同一二叉搜尋樹序列。

【解題思路】

只需判斷兩棵樹的前序遍歷序列是否相同即可。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
vector<int>a,b;
typedef struct Node
{
    int val;
    struct Node *left,*right;
}Node,*BNode;
BNode insertnode(BNode root,int x)
{
    if(root==NULL)
    {
        root=new Node();
        root->val=x;
        root->left=root->right=NULL;
        return root;
    }
    if(x<root->val)
        root->left=insertnode(root->left,x);
    else if(x>root->val)
        root->right=insertnode(root->right,x);
    return root;
}
void preorder(BNode root,int flag)
{
    if(root==NULL)return;
    if(flag)a.push_back(root->val);
    else b.push_back(root->val);
    preorder(root->left,flag);
    preorder(root->right,flag);
}
int main()
{
    int n;
    string s;
    while(~scanf("%d",&n) && n)
    {
        a.clear();
        cin>>s;
        BNode root=NULL;
        for(int i=0;i<s.size();i++)
            root=insertnode(root,s[i]-'0');
        preorder(root,1);
        for(int i=0;i<n;i++)
        {
            cin>>s;
            b.clear();
            BNode root2=NULL;
            for(int i=0;i<s.size();i++)
                root2=insertnode(root2,s[i]-'0');
            preorder(root2,0);
            if(a==b)printf("YES\n");
            else printf("NO\n");
        }
    }
    return 0;
}