1. 程式人生 > >uva122 二叉樹的實現和層次遍歷(bfs)

uva122 二叉樹的實現和層次遍歷(bfs)

原型 null 內存泄漏 計算 內存溢出 遍歷 max 二叉樹的層次遍歷 構造函數

題目見紫書

6.3.2 二叉樹的層次遍歷

1.二叉樹的實現:

a.用指針實現:用結構體記錄結點,利用指針訪問結點

其中變量left,right的值 new的返回值都是地址

/*二叉樹的結點定義和操作*/
//結點類型
struct Node{
    bool have_value;                       //是否被賦值過
    int v;                                 //結點值
    Node *left,*right;
    Node():v(-1),have_value(false),left(NULL),right(NULL){}//構造函數 
};
Node* newnode(){return new Node()};        //申請新結點的函數 

b.用數組實現:

計數器cnt為已存在的節點數(編號最大值),用編號代替地址訪問結點,用數組 [編號]來訪問節點,其中left[u],right[u]都是記錄的編號,結構體中的成員變量成了全局數組。

int newnode(){
    int u=++cnt;
    left[u]=right[u]=0;
    have_value[root]=false;
    return u;
}

其中指針是利用動態內存實現,需要一直申請新內存(new),為防止內存泄漏,需要釋放內存

Node* newnode(){return new Node()};        //申請新結點的函數 

而數組是靜態內存實現,編程簡單,容易調試,不需釋放動態內存,只要重置結點計數器和根結點的左有子樹就行了.

可以用靜態數組配合空閑列表實現一個簡單的內存池,防止內存溢出(不太懂,先不學,以後再看,紫書154頁)

二叉樹的bfs要用隊列來實現

//二叉樹的bfs
bool bfs(vector<int>& ans){
    queue<Node*> q;
    ans.clear();
    q.push(root);                          
//初始時只有一個根結點 while(!q.empty()){ Node* u=q.front(); q.pop(); if(!u->have_value) return false; //有結點未被賦值,輸入有誤 ans.push_back(u->v); //增加到輸出序列的尾部 if(u->left!=NULL) q.push(u->left); //如果有左節點,放入隊列 if(u->right !=NULL) q.push(u->right);//如果有右結點,放入序列 } return true; //輸入正確 }

其他:

· 可以用new運算符申請空間並執行構造函數。如果返回值為NULL,說明空間不足,申請失敗。

· strchr

strchr是計算機編程語言的一個函數,原型為extern char *strchr(const char *s,char c),可以查找字符串s中首次出現字符c的位置。

指針實現如下:

註: u->v 其中u是結構指針;

任何指針都不能為空指針!包括結構指針 Node * root; 若無root=newnode(); root就是空指針,錯都不知道錯到哪了;

if(!strcmp(s,"()"))break;字符串比較就這樣比較

//二叉樹的動態實現與層次遍歷
//new和delete是運算符,沒有頭文件 
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=256+10;

bool failed;
struct Node{
    bool have_valued;
    int v;
    Node* left,*right;
    Node():have_valued(false),left(NULL),right(NULL){};
};
Node* root;                                           // 此時root為空指針 
Node* newnode(){return new Node;}
bool addnode(int v,char* s){
    Node* u=root;
    int n=strlen(s);
    for(int i=0;i<n;i++)
    if(s[i]==L){if(u->left==NULL)u->left=newnode();
    u=u->left;
    }
    else if(s[i]==R){if(u->right==NULL)u->right=newnode();
    u=u->right;
    }
    if(u->have_valued)failed=true;
    else u->v=v;
    u->have_valued=true;
    return true;
}
void remove(Node* u){
    if(u==NULL)return;
    if(u->right!=NULL)remove(u->right);
    if(u->left!=NULL)remove(u->left);
    delete u;
}
char s[maxn];
bool input_read(){
    failed = false;
    root = newnode();
    int v;
    for(;;){
    if(scanf("%s",s)!=1)return false;
    if(!strcmp(s,"()"))break;
    sscanf(&s[1],"%d",&v);
    addnode(v,strchr(s,,)+1);
    }
    return true;
}

bool bfs(vector<int>& ans){
    ans.clear();
    queue <Node* > q;
    Node* u=root;
    q.push(u);
    while(!q.empty()){
        if(u->have_valued)
        ans.push_back(u->v);
        else return false;
        q.pop();
        if(u->left!=NULL)q.push(u->left);
        if(u->right!=NULL)q.push(u->right);
        u=q.front();
    } 
    return true;
}


int main(){
    vector <int> ans;
    while(input_read()){
    if(!bfs(ans))failed=true;
    if(failed)printf("not complete\n");
    else {for(int i=0;i<ans.size();i++){
            if(i!=0)printf(" ");
            printf("%d",ans[i]);
         }printf("\n");
    }
    }
    return 0;
}

數組實現也差不多,用left【】right【】儲存指針域,跟鏈表似的:

//二叉樹的靜態(數組)實現與層次遍歷
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=256+10;
const int root=1; 

bool failed;
int cnt=1;
int left[maxn];
int right[maxn];
int value[maxn];
bool have_value[maxn];
int newnode(){int u=++cnt;left[u]=0;
    right[u]=0;have_value[u]=false;
    return u;}
bool addnode(int v,char* s){
    int n=strlen(s),t=root;
    for(int i=0;i<n;i++){
        if(s[i]==L){
        if(left[t]==0)left[t]=newnode();
        t=left[t];
        }
        if(s[i]==R){
        if(right[t]==0)right[t]=newnode();
        t=right[t];
        }
    }
   // printf("have value[%d]=%d\n",t,have_value[t]);
    if(have_value[t]==true)failed=true;
    else have_value[t]=true;
    value[t]=v;
    return true;
}

void newtree(){             //相當於動態裏newnode結構體拆開,因為是靜態數組,無需申請內存 
    cnt=root;
    right[root]=0;
    left[root]=0;
    have_value[root]=false;
}
char s[maxn];
bool input_read(){
    failed = false;
    newtree();
    int v;
    for(;;){
    if(scanf("%s",s)!=1)return false;
    if(!strcmp(s,"()"))break;
    sscanf(&s[1],"%d",&v);
    //printf("%s\n",strchr(s,‘,‘)+1);
    addnode(v,strchr(s,,)+1);
    }
    return true;
}

bool bfs(vector<int>& ans){
    ans.clear();
    queue <int> qcnt;
    int u=1;
    qcnt.push(u);
    while(!qcnt.empty()){
        u=qcnt.front();//printf("bfs-%d\n",u);
        if(have_value[u]==false){return false;}
        qcnt.pop();
        ans.push_back(value[u]);
        if(left[u]!=0)qcnt.push(left[u]);
        if(right[u]!=0)qcnt.push(right[u]);
    }
    return true;
}


int main(){
    memset(have_value,false,sizeof(have_value));
    memset(left,0,sizeof(left));
    memset(right,0,sizeof(right));
    vector <int> ans;
    while(input_read()){
    if(!bfs(ans))failed=true;
    if(failed)printf("not complete\n");
    else {for(int i=0;i<ans.size();i++){
            if(i!=0)printf(" ");
            printf("%d",ans[i]);
         }printf("\n");
    }
    }
    return 0;
}

uva122 二叉樹的實現和層次遍歷(bfs)