2017-07-11 2 views
0

En C++ je travaille sur deux arbres, 1 est alphabétique a-z avec nums et caractères 0-9,. ?Parcours de précommande traversant le code Morse BST

L'autre arbre est l'équivalent de ces caractères en code Morse. Je dois avoir les différents arbres dans les fichiers texte qui devraient déjà être dans le bon ordre pour insérer. Dans mon alphabet normal, je travaillais mon fichier texte équilibré en pré-commande traversal ressemble

P 
H 
D 
B 
A 
C 
F 
E 
G 
L 
J 
I 
K 
N 
M 
O 
2 
X 
T 
R 
Q 
S 
V 
U 
W 
0 
Y 
Z 
1 
9 
5 
4 
3 
7 
6 
8 
, 
. 
? 

Ce fichier texte imprime précommande traversal

, 
. 
0 
1 
2 
3 
4 
5 
6 
7 
8 
9 
? 
A 
B 
C 
D 
E 
F 
G 
H 
I 
J 
K 
L 
M 
N 
O 
P 
Q 
R 
S 
T 
U 
V 
W 
X 
Y 
Z 

Le problème que je rencontre est avec le code Morse textfile. Je comprends que les caractères pour le code Morse ne sont pas les mêmes pour l'alphabet normal. De peur au plus grand, c'est le code Morse

- T 
-- M 
--- O 
----- 0 
----. 9 
---.. 8 
--. G 
--.- Q 
--.. Z 
--..-- , 
--... 7 
-. N 
-.- K 
-.-- Y 
-.-. C 
-.. D 
-..- X 
-... B 
-.... 6 
. E 
.- A 
.-- W 
.--- J 
.---- 1 
.--. P 
.-. R 
.-.. L 
.. I 
..- U 
..--- 2 
..--.. ? 
..-. F 
... S 
...- V 
...-- 3 
.... H 
....- 4 
..... 5 

appliquant la même formule pour l'arbre (il a la même séquence que celle alphabétique ci-dessus, mon fichier texte ressemble

-.. D 
--.- Q 
----- 0 
-- M 
- T 
--- O 
---.. 8 
----. 9 
--. G 
-. N 
--..-- , 
--.. Z 
--... 7 
-.-- Y 
-.- K 
-.-. C 
.. I 
.---- 1 
. E 
-... B 
-..- X 
-.... 6 
.-- W 
.- A 
.--- J 
.-.-.- . 
.--. P 
.-. R 
.-.. L 
...-- 3 
..--.. ? 
..--- 2 
..- U 
... S 
..-. F 
...- V 
....- 4 
.... H 
..... 5 

Mais cette aussi n'imprime pas l'arbre dans l'ordre alphabétique pour le code Morse en pré-commande.

Voilà comment je suis insérer dans l'arbre

void BST::insert(BSTNode *&pTree, string morse) 
{ 
    if (pTree == NULL) 
    { 
     BSTNode *pMem = new BSTNode(morse); 
     pTree = pMem; 
    } 
    else if (morse < (pTree)->getMorse()) 
    { 
     insert((pTree)->getLeft(), morse); 
    } 
    else if (morse > (pTree)->getMorse()) 
    { 
     insert((pTree)->getRight(), morse); 
    } 
} 

Et voilà comment je suis en train d'imprimer les résultats

void BST::print(BSTNode *&pTree, string id) 
{ 
    if (pTree != nullptr) 
    { 
     //cout << pTree->getMorse() << endl; // processed 
     print(pTree->getLeft(), id); 
     cout << pTree->getMorse() << endl; // processed 
     print(pTree->getRight(), id); 
    } 

} 

(le même code est pour l'alphabet sauf qu'il utilise les caractères et getLetter() mais autre que celui qu'elle est identique)

Si je J'approcher juste ceci incorrectement, je pourrais utiliser n'importe quelle aide dans la bonne direction.

Répondre

0

Avez-vous remarqué que votre méthode insert() ne gère pas le cas de "collision de clé" (en raison de la branche else manquante pour la dernière if). Cela peut être utilisé pour détecter si une clé doit être insérée dans l'arborescence. Comme il est, ces insertions dupliquées sont simplement ignorées (ce qui est à mon humble avis pas le pire comportement possible).

Dans mon exemple ci-dessous, j'ai opté pour une option différente: soit insert() retourne une valeur booléenne qui rapporte le succès de l'insertion.

Malheureusement, vous n'avez pas fourni de MCVE.

Ainsi, j'ai rempli les lacunes avec le code propre où (pour ma joie personnelle) j'ai impliqué des modèles. J'espère que cela n'entraînera pas trop de confusion.

Cependant, après avoir joué avec vos données d'échantillon, je suis arrivé à la conclusion que votre code ne peut probablement pas le bon –, ce que vous attendiez. Finalement, vous avez une fausse attente. Ou, vous avez résolu correctement le faux problème. J'ai relu votre question plusieurs fois mais je n'ai pas eu d'idée claire à ce sujet ...

J'utilisé votre dernier fichier exemple en entrée (pour construire l'arbre de recherche binaire) et que ma pré-commande de sortie de l'application et afinde:

  • sortie Précommande correspond à votre dernier fichier.

  • La sortie Inorder correspond à votre 3e fichier.

La sortie inorder fournit une sortie triées selon l'ordre défini de l'arbre – dans ce cas, l'ordre lexicographique des séquences Morse (où - précède . en raison de leurs valeurs ASCII respectifs).

Mais cela n'imprime pas non plus l'arborescence dans l'ordre alphabétique pour le code Morse en pré-commande.

Hmmm. Si vous vous attendiez à un ordre alphabétique, voulez-vous dire un ordre qui considère les caractères alphanumériques (auxquels correspondent les codes Morse)? Si tel est le cas, cela peut difficilement être fait par un tel arbre (car je ne vois pas comment un ordre possible de codes Morse correspond à un ordre possible d'alpha-numériques). C'est à dire. pour obtenir des "codes morse triés par les alpha-numériques associés", la méthode évidente (et à mon humble avis seulement) consiste à construire un arbre pour la cartographie inverse. Vous pouvez facilement créer un autre arbre (par exemple à partir du premier) où les valeurs alphanumériques affectées sont utilisées comme clés à la place. (En fait, vous avez déjà fait d'abord un arbre de recherche binaire pour les caractères alphanumériques.)

Cela me laisse perplexe. Peut-être, je raté quelque chose et n'a pas obtenu votre problème réel ...

Cependant, au-dessous est le résultat de mon violon:

// forward template declaration: 
template <typename KEY, typename VALUE, typename COMP> 
class BSTreeT; 

/* provides a class template for a node in a binary search tree. 
* 
* KEY ... C++ type of the key values of nodes 
* VALUE ... C++ type of the other values of nodes 
*/ 
template <typename KEY, typename VALUE> 
class BSTreeNodeT { 

    /* This friend shall ensure that the corresponding 
    * BSTreeT template class may access private _pLeft and _pRight. 
    */ 
    template <typename KEY_, typename VALUE_, typename COMP_> 
    friend class BSTreeT; 

    public: 
    // the key value of node (used to define an order) 
    const KEY key; 
    // other values of node 
    VALUE value; 
    private: 
    // pointers to left and right child nodes 
    BSTreeNodeT *_pLeft, *_pRight; 

    public: 
    // constructor. 
    BSTreeNodeT(const KEY &key, const VALUE &value): 
     key(key), value(value), _pLeft(nullptr), _pRight(nullptr) 
    { } 
    // destructor. 
    ~BSTreeNodeT() { delete _pLeft; delete _pRight; } 
    // disabled: 
    BSTreeNodeT(const BSTreeNodeT&) = delete; 
    BSTreeNodeT& operator=(const BSTreeNodeT&) = delete; 

    public: 
    // returns pointer to left child node (or nullptr if there is none). 
    const BSTreeNodeT* getLeft() const { return _pLeft; } 
    // returns pointer to right child node (or nullptr if there is none). 
    const BSTreeNodeT* getRight() const { return _pRight; } 
}; 

/* provides a less functor which simply wraps operator < for a certain 
* type 
* 
* VALUE ... C++ type of value to less-compare 
* 
* Note: 
* This is actually, what std::less provides. 
* I involved this functor for illustration. 
*/ 
template <typename VALUE> 
struct lessFunc { 
    bool operator()(const VALUE &value1, const VALUE &value2) const 
    { 
    return value1 < value2; 
    } 
}; 

/* provides a class template for a binary search tree. 
* 
* KEY ... C++ type of the key values of nodes 
* VALUE ... C++ type of the other values of nodes 
* COMP ... C++ type of the less comparator 
*   to define an order of tree nodes 
*/ 
template <typename KEY, typename VALUE, typename COMP = lessFunc<KEY> > 
class BSTreeT { 
    public: 
    const COMP &comp; 
    private: 
    BSTreeNodeT<KEY, VALUE> *_pRoot; 

    public: 
    /* constructor. 
    * 
    * comp ... a less comparator to define order of nodes 
    */ 
    explicit BSTreeT(const COMP &comp = COMP()): 
     comp(comp), _pRoot(nullptr) 
    { } 
    // destructor. 
    ~BSTreeT() { delete _pRoot; } 
    // disabled: 
    BSTreeT(const BSTreeT&) = delete; 
    BSTreeT& operator=(const BSTreeT&) = delete; 

    public: 
    /* inserts a node. 
    * 
    * key ... the key value of node 
    * value ... the other value of node 
    * return: true ... key/value inserted 
    *   false ... Error! Possible reasons: 
    *   - duplicated key 
    *   - allocation of node failed. 
    */ 
    bool insert(const KEY &key, const VALUE &value) 
    { 
     return insert(_pRoot, key, value); 
    } 
    /* provides a functor-like type which is applied to every node 
    * in traverse(). 
    * 
    * If an instance of this class is provided the traverse() does nothing 
    * else than the pure traversal. 
    */ 
    struct Apply { 
     // pre-order access to node 
     virtual void preNode(BSTreeNodeT<KEY, VALUE> &node) { } 
     // in-order access to node 
     virtual void inNode(BSTreeNodeT<KEY, VALUE> &node) { } 
     // post-order access to node 
     virtual void postNode(BSTreeNodeT<KEY, VALUE> &node) { } 
    }; 
    /* traverses the tree and applies the provided object to every node. 
    * 
    * apply ... the action object applied to every node 
    */ 
    void traverse(Apply &apply) 
    { 
     if (_pRoot) traverse(_pRoot, apply); 
    } 

    private: 
    // inserts a node. 
    bool insert(
     BSTreeNodeT<KEY, VALUE> *&pTree, const KEY &key, const VALUE &value) 
    { /* Every if-branch ends with return. 
     * Thus, no explict else is needed. 
     */ 
     if (!pTree) { /* (!pTree) ... (pTree == nullptr) */ 
     return !!(pTree = new BSTreeNodeT<KEY, VALUE>(key, value)); 
     } 
     if (comp(key, pTree->key)) return insert(pTree->_pLeft, key, value); 
     if (comp(pTree->key, key)) return insert(pTree->_pRight, key, value); 
     return false; 
    } 
    // traverses the tree. 
    void traverse(BSTreeNodeT<KEY, VALUE> *pTree, Apply &apply) 
    { 
     apply.preNode(*pTree); 
     if (pTree->_pLeft) traverse(pTree->_pLeft, apply); 
     apply.inNode(*pTree); 
     if (pTree->_pRight) traverse(pTree->_pRight, apply); 
     apply.postNode(*pTree); 
    } 
}; 

// sample code: 

#include <ctype.h> 
#include <iostream> 
#include <string> 

using namespace std; 

// template instances (for convenience) 
typedef BSTreeNodeT<string, string> BSTNode; 
typedef BSTreeT<string, string> BST; 

/* a helper function to split a string into tow at the first occurence of 
* (a sequence of) whitespaces. 
* 
* line ... input 
* first ... returns first sub-string (might become empty) 
* second ... returns second sub-string (might become empty) 
*/ 
void split(const string &line, string &first, string &second) 
{ 
    size_t i0 = 0, n = line.length(), i; 
    for (i = i0; i < n && !isspace(line[i]); ++i); 
    first = line.substr(i0, i - i0); 
    for (i0 = i; i0 < n && isspace(line[i0]); ++i0); 
    for (i = i0; i < n && !isspace(line[i]); ++i); 
    second = line.substr(i0, i - i0); 
} 

/* a derived tree-traversal action 
* for graphical (i.e. ASCII-art) output of tree 
*/ 
struct PrintGraph: public BST::Apply { 
    string indent; 
    PrintGraph(): indent(" ") { } 
    virtual void preNode(BSTNode &node) 
    { 
    indent.pop_back(); char c = indent.back(); indent.pop_back(); 
    cout << indent << "+-" 
     << (node.getLeft() || node.getRight() ? '+' : '-') 
     << "- [" 
     << node.key << ": " << node.value 
     << ']' << endl; 
    indent += c; indent += ' '; 
    indent += node.getRight() ? "| " : " "; 
    } 
    virtual void inNode(BSTNode &node) 
    { 
    indent.pop_back(); indent.pop_back(); 
    indent += " "; 
    } 
    virtual void postNode(BSTNode &node) 
    { 
    indent.pop_back(); indent.pop_back(); 
    } 
}; 

/* a derived tree-traversal action 
* for pre-order output of nodes 
*/ 
struct PrintPreOrder: public BST::Apply { 
    virtual void preNode(BSTNode &node) 
    { 
    cout << node.key << ": " << node.value << endl; 
    } 
}; 

/* a derived tree-traversal action 
* for in-order output of nodes 
*/ 
struct PrintInOrder: public BST::Apply { 
    virtual void inNode(BSTNode &node) 
    { 
    cout << node.key << ": " << node.value << endl; 
    } 
}; 

/* a derived tree-traversal action 
* to fill another tree with key and value of nodes swapped 
*/ 
struct FillRevTree: public BST::Apply { 
    BST &tree; // destination tree to fill 
    FillRevTree(BST &tree): tree(tree) { } 
    virtual void preNode(BSTNode &node) 
    { 
    tree.insert(node.value, node.key); 
    } 
}; 

// main function 
int main() 
{ 
    BST tree; 
    // read tree from input 
    cout << "Read contents from input:" << endl; 
    for (string line; getline(cin, line);) { 
    string key, value; split(line, key, value); 
    if (!tree.insert(key, value)) { 
     cerr << "Error! Couldn't store the line:" << endl 
     << "->" << line << endl; 
    } 
    } 
    cout << "End of input." << endl 
    << endl; 
    // show tree 
    cout << "The tree:" << endl; 
    { PrintGraph print; tree.traverse(print); } 
    cout << endl; 
    // print tree by pre-order traversal 
    cout << "Pre-Order Output:" << endl; 
    { PrintPreOrder print; tree.traverse(print); } 
    cout << endl; 
    // print tree by in-order traversal 
    cout << "In-Order Output:" << endl; 
    { PrintInOrder print; tree.traverse(print); } 
    cout << endl; 
    // re-built tree with keys and values swapped 
    BST treeRev; 
    { FillRevTree fill(treeRev); tree.traverse(fill); } 
    // show reverse tree 
    cout << "The Rev. Tree:" << endl; 
    { PrintGraph print; treeRev.traverse(print); } 
    cout << endl; 
    // print tree by in-order traversal 
    cout << "In-Order Output of Rev. Tree:" << endl; 
    { PrintInOrder print; treeRev.traverse(print); } 
    cout << endl; 
    // done 
    cout << "That's it." << endl; 
    return 0; 
} 

Compilez et exécutez:

$ g++ -std=c++11 -o binary-search-tree binary-search-tree.cc 

$ ./binary-search-tree <morse.txt 
Read contents from input: 
End of input. 

The tree: 
+-+- [-..: D] 
    +-+- [--.-: Q] 
    | +-+- [-----: 0] 
    | | +-+- [--: M] 
    | | | +--- [-: T] 
    | | | +--- [---: O] 
    | | +-+- [---..: 8] 
    | | +--- [----.: 9] 
    | | +--- [--.: G] 
    | +-+- [-.: N] 
    | +-+- [--..--: ,] 
    | | +--- [--..: Z] 
    | | +--- [--...: 7] 
    | +-+- [-.--: Y] 
    |  +--- [-.-: K] 
    |  +--- [-.-.: C] 
    +-+- [..: I] 
    +-+- [.----: 1] 
    | +-+- [.: E] 
    | | +-+- [-...: B] 
    | | | +--- [-..-: X] 
    | | | +--- [-....: 6] 
    | | +-+- [.--: W] 
    | | +--- [.-: A] 
    | | +--- [.---: J] 
    | +-+- [.-.-.-: .] 
    | +-+- [.--.: P] 
    | | +--- [.-.: R] 
    | +--- [.-..: L] 
    +-+- [...--: 3] 
     +-+- [..--..: ?] 
     | +-+- [..---: 2] 
     | | +--- [..-: U] 
     | +-+- [...: S] 
     | +--- [..-.: F] 
     | +--- [...-: V] 
     +-+- [....-: 4] 
     +--- [....: H] 
     +--- [.....: 5] 

Pre-Order Output: 
-..: D 
--.-: Q 
-----: 0 
--: M 
-: T 
---: O 
---..: 8 
----.: 9 
--.: G 
-.: N 
--..--: , 
--..: Z 
--...: 7 
-.--: Y 
-.-: K 
-.-.: C 
..: I 
.----: 1 
.: E 
-...: B 
-..-: X 
-....: 6 
.--: W 
.-: A 
.---: J 
.-.-.-: . 
.--.: P 
.-.: R 
.-..: L 
...--: 3 
..--..: ? 
..---: 2 
..-: U 
...: S 
..-.: F 
...-: V 
....-: 4 
....: H 
.....: 5 

In-Order Output: 
-: T 
--: M 
---: O 
-----: 0 
----.: 9 
---..: 8 
--.: G 
--.-: Q 
--..: Z 
--..--: , 
--...: 7 
-.: N 
-.-: K 
-.--: Y 
-.-.: C 
-..: D 
-..-: X 
-...: B 
-....: 6 
.: E 
.-: A 
.--: W 
.---: J 
.----: 1 
.--.: P 
.-.: R 
.-.-.-: . 
.-..: L 
..: I 
..-: U 
..---: 2 
..--..: ? 
..-.: F 
...: S 
...-: V 
...--: 3 
....: H 
....-: 4 
.....: 5 

The Rev. Tree: 
+-+- [D: -..] 
    +-+- [0: -----] 
    | +-+- [,: --..--] 
    | | +--- [.: .-.-.-] 
    | +-+- [8: ---..] 
    | +-+- [7: --...] 
    | | +-+- [1: .----] 
    | | +-+- [6: -....] 
    | |  +-+- [3: ...--] 
    | |  +--- [2: ..---] 
    | |  +-+- [4: ....-] 
    | |   +--- [5: .....] 
    | +-+- [9: ----.] 
    |  +-+- [C: -.-.] 
    |  +-+- [B: -...] 
    |   +-+- [A: .-] 
    |   +--- [?: ..--..] 
    +-+- [Q: --.-] 
    +-+- [M: --] 
    | +-+- [G: --.] 
    | | +-+- [E: .] 
    | | | +--- [F: ..-.] 
    | | +-+- [K: -.-] 
    | | +-+- [I: ..] 
    | | | +--- [H: ....] 
    | | | +--- [J: .---] 
    | | +--- [L: .-..] 
    | +-+- [O: ---] 
    | +--- [N: -.] 
    | +--- [P: .--.] 
    +-+- [T: -] 
     +-+- [R: .-.] 
     | +--- [S: ...] 
     +-+- [Z: --..] 
     +-+- [Y: -.--] 
      +-+- [X: -..-] 
      +-+- [W: .--] 
       +-+- [U: ..-] 
       +--- [V: ...-] 

In-Order Output of Rev. Tree: 
,: --..-- 
.: .-.-.- 
0: ----- 
1: .---- 
2: ..--- 
3: ...-- 
4: ....- 
5: ..... 
6: -.... 
7: --... 
8: ---.. 
9: ----. 
?: ..--.. 
A: .- 
B: -... 
C: -.-. 
D: -.. 
E: . 
F: ..-. 
G: --. 
H: .... 
I: .. 
J: .--- 
K: -.- 
L: .-.. 
M: -- 
N: -. 
O: --- 
P: .--. 
Q: --.- 
R: .-. 
S: ... 
T: - 
U: ..- 
V: ...- 
W: .-- 
X: -..- 
Y: -.-- 
Z: --.. 

That's it. 

$ 

Remarque :

Je viens de reconnaître que l'arbre "inversé" n'est plus bien équilibré. Ainsi, la complexité temporelle optimale du pire cas de O (ld (n)) ne peut pas être atteinte.