1. 程式人生 > >廣度優先遍歷(BFS)例題

廣度優先遍歷(BFS)例題

二叉樹的層次遍歷     UVa122

題目:

一、輸入資料的處理:

此處兩次用到的c語言字串的靈活性——可以把任何指向字元的指標看成一個字串,從該位置開始直到‘\0’結束的字串。例如,若讀到的字串節點是“(11,LL)”,則‘&s[1]’代表的含義是字串“11,LL)”。函式strchr(s,’,’)返回字串中從左往右第一個‘,’字元的指標,因此strchr(s,’,’)所對應的字串為“LL)”。這樣實際呼叫的是addnode(11,”LL”)。  

二、二叉樹基本結構的定義:

struct Node{   bool have_value;   int v;   Node* left, *right;   Node():have_value(false),left(NULL),right(NULL){} };

三、新增節點操作

四、層序遍歷(BFS)、

 

五、遞迴釋放二叉樹(防止記憶體洩漏)

 

最後貼上完整程式原始碼:

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;

//樹結點 
struct Node{
    int v ;
    Node* left,*right ;
    int have_value ;
    Node():have_value(false),left(NULL),right(NULL){} ;
} ;

Node* root ;//根節點

Node* newnode(){
    return new Node() ; //返回一個新結點 
} 

bool failed ;

void addnode(int v,char* s){//新增新結點 
    int n = strlen(s);
    Node* u = root ;
     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_value) failed = true ;//是否已經被訪問過;
     u->v = v;
     u->have_value = true; 
} 

void freetree(Node* u){ //釋放記憶體 
    if(u == NULL) return ;
    freetree(u->left);
    freetree(u->right);
    delete u;
}

char s[1005];
bool read_input(){
    failed = false ;
    freetree(root) ;
    root = newnode();
    while(true){
        if(scanf("%s", s) != 1) return false;
        if(!strcmp(s,"()")) break;
        int v ;
        sscanf(&s[1],"%d",&v);
        addnode(v,strchr(s,',')+1);
    } 
    return true ;
} 

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 ;
}

int main(int argc, char *argv[])
{
    vector<int> ans;
    while(read_input()){
        if(!bfs(ans)) failed = 1;
        if(failed) printf("not complete\n");
        else{
            for(int i = 0;i < ans.size();i++)
            {
                if(i != 0) cout << " " ;
                   cout << ans[i];
            }
            cout << endl ;
        }    
    }
    return 0;
}

上面的程式碼寫的比我的好些,但還是習慣性貼上自己的程式碼:

#include<iostream>
#include<string>
#include<queue>
#include<vector>
using namespace std;

struct node//構造樹的節點,下面的建構函式是非常好的 
{
	bool value;
	int v;
	node *left;
	node *right;
	node():value(false),v(0),left(NULL),right(NULL){}

};

node *root=new node;//建立一個根節點,便於建立和遍歷 
                    //一定要開闢空間 
int v;
string com_s;

/* 
void print(node *u)
{
	cout<<endl<<u->value;
	cout<<" "<<u->v;
	if(u->left)
		cout<<" "<<"left exit";
	if(u->right)
	 	cout<<" "<<"right exit";
}
*/



void extract(string &in_s)//提取命令 
{
	int i;
	v=0;
	com_s.clear();//清空是clear,不是empty()。大爺的,查這麼長時間查不出 
	for(i=1;isdigit(in_s[i]);i++)//s[0]為( 
		v=v*10+(in_s[i]-'0');
	//跳出迴圈時,讀取的是,的位置
	i++; 
	for(i;in_s[i]!=')';i++)
		com_s.push_back(in_s[i]); 
}


void creat_node()
{
	node *u=root;
	for(int i=0;com_s[i];i++)
	{	
		if(com_s[i]=='L')
		{	
			if(u->left==NULL)
				u->left=new node;
			u=u->left; 
		}
		else if(com_s[i]=='R')//如果右子樹的空間已經存在
		{
			if(u->right==NULL)
				u->right=new node;
			u=u->right; 
		} 
	}
	
	u->v=v;
	if(!u->value) 
		u->value=true;
} 


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


void remove_tree(node *u)
{
	if(u==NULL) return;
	remove_tree(u->left);
	remove_tree(u->right);
	delete u;
}

int main()
{
	string in_s;
	vector<int> ans;
	
	/*輸入資訊,建立樹*/ 
	while(cin>>in_s) 
	{
		if(in_s=="()") break;
		extract(in_s);//從中提取命令放入v和com_s中
		
	//	cout<<v;
		//cout<<com_s;
	
		
		creat_node();//建立節點,生成樹 
		//system("pause");
	}
	
	/*廣度遍歷樹*/
	if(bfs(ans))
	{
		int n=ans.size();
		for(int i=0;i<n;i++) 
			cout<<ans[i]<<" ";
	}
	else
		cout<<-1;
				
	remove_tree(root);
		
	return 0;
}