二叉樹的序列化和反序列化


【說明】:

  本文是左程雲老師所著的《程序員面試代碼指南》第三章中“二叉樹的序列化和反序列化”這一題目的C++復現。

  本文只包含問題描述、C++代碼的實現以及簡單的思路,不包含解析說明,具體的問題解析請參考原書。

  感謝左程雲老師的支持。

【題目】:

  二叉樹被記錄成文件的過程叫作二叉樹的序列化,通過文件內容重建原來二叉樹的過程叫做二叉樹的反序列化。給定一顆二叉樹的頭節點 head,並已知二叉樹節點值的類型為32位整形。請設計一種二叉樹序列化和反序列化的方案,並用代碼實現。

 【思路】:

  解法為先序遍歷和層遍歷兩種。

【編譯環境】:

  CentOS6.7(x86_64)

  gcc 4.4.7

 【實現及測試】:

  聲明代碼:

/*
 *文件名:bt_serial.h
 *作者:
 *摘要:實現二叉樹的序列化和反序列化
 */

#include <string>

using namespace std;

class Node
{
public:
    Node(int data)
    {
        value = data;
        left = NULL;
        right = NULL;
    }
public:
    int value;
    Node *left;
    Node *right;
};

string serialByPre(Node *root); //通過先序遍歷序列化為字符串
Node* reconByPreString(string preStr); //將通過先序遍歷序列化得到的的字符串反序列化

string serialByLevel(Node *root);    //按層遍歷序列化
Node* reconByLevelString(string levelStr);//根據層遍歷反序列化
View Code

  實現及測試代碼:

/*
 *文件名:bt_serial.cpp
 *作者:
 *摘要:二叉樹序列化與反序列化的實現
 */
 

#include "bt_serial.h"
#include <queue>
#include <sstream>
#include <iostream>

//字符串轉換為整形
int strToint(string &svalue)
{
    stringstream ss;
    ss << svalue;
    int ivalue;
    ss >> ivalue;
    return ivalue;
}

//整形轉換為字符串
string intTostr(int &ivalue)
{
    stringstream ss;
    ss << ivalue;
    string svalue;
    ss >> svalue;
    return svalue;
}

string serialByPre(Node *root)
{
    if(NULL == root)
        return "#!";

    string svalue = intTostr(root->value);

    string res = svalue + "!";
    res += serialByPre(root->left);
    res += serialByPre(root->right);
    return res;
}

Node* reconPreOrder(queue<string> *q)
{
    string svalue = q->front();
    q->pop();
//    cout << svalue << endl;
    if("#" == svalue)
        return NULL;
    
    int ivalue = strToint(svalue);
    
    Node *root = new Node(ivalue);
    root->left=reconPreOrder(q);
    root->right=reconPreOrder(q);
    return root;
}

Node* reconByPreString(string preStr)
{
    size_t firPos = 0;
    size_t secPos = 0;
    queue<string>* q = new queue<string>;   //注意指針的使用
    
    secPos = preStr.find("!");
    while(secPos != string::npos)
    {
        q->push(preStr.substr(firPos, secPos - firPos));
        firPos = secPos + 1;
        secPos = preStr.find("!", firPos);
    }

    return reconPreOrder(q);
}

string serialByLevel(Node* root)
{
    if(NULL == root)    
        return "#!";
    
    string svalue = intTostr(root->value);
    
    string res = svalue + "!";
    queue<Node*> q;
    q.push(root);

    while(!q.empty())
    {
        root = q.front();
        q.pop();

        if(NULL != root->left)
        {
            svalue = intTostr(root->left->value);
            res += svalue + "!";
            q.push(root->left);
        }
        else
        {
            res += "#!";
        }
        
        if(NULL != root->right)
        {
            svalue = intTostr(root->right->value);
            res += svalue + "!";
            q.push(root->right);
        }
        else
        {
            res += "#!";
        }
    }
    return res;    
}

Node* generateNodeByString(string val)
{    
    if("#" == val)
        return NULL;
    
    return new Node(strToint(val));
}

Node* reconByLevelString(string levelStr)
{
    size_t firPos = 0;
    size_t secPos = levelStr.find("!");
    queue<string>* qStr = new queue<string>;   //注意指針的使用
    
    while(secPos != string::npos)
    {
        qStr->push(levelStr.substr(firPos, secPos - firPos));
    //    cout << qStr->back() << endl;
        firPos = secPos + 1;
        secPos = levelStr.find("!", firPos);
    }

       queue<Node*>* qNode = new queue<Node*>;   //注意指針的使用
    Node *root = generateNodeByString(qStr->front());
    qStr->pop();
    if (NULL != root)
        qNode->push(root);
    
    Node *node = NULL;
    while(!qNode->empty())
    {
        node = qNode->front();
        qNode->pop();

        if (NULL != node)
            cout << node->value << endl;
        else
            cout << "#" << endl;

        node->left = generateNodeByString(qStr->front());
        qStr->pop();
        node->right = generateNodeByString(qStr->front());
        qStr->pop();
        if(NULL != node->left)
            qNode->push(node->left);
        if(NULL != node->right)
            qNode->push(node->right);
    }    
    return root;
}


int main()
{
    string str = "12!3!#!#!#!";
    Node *root = reconByPreString(str);
    string str1 = serialByPre(root);
    cout << str1 << endl;

    root = reconByLevelString(str);
    str1 = serialByLevel(root);
    cout << str1 << endl;
    return 0;
}
View Code

說明:

  由JAVA代碼轉到C++代碼,像字符串類、隊列類的在使用上的差距比較大。但是整體的思路還是左老師在書中所提出的。

  

注:

  轉載請注明出處;

  轉載請注明源思路來自於左程雲老師的《程序員代碼面試指南》。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM