Here's a dictionary structured as a binary tree.  
Note that the tree will have very different shapes depending on what order the words are added in - best is a random order.
This issue is called "balancing"; the version here doesn't try to worry about that.

The printTree[] and countTree[] methods apply a function to each element of the tree.

Is the printing done depth first or breadth first ?

topWord[
          tree_] := tree[[1]][[1]];
topDefinition[
          tree_] := tree[[1]][[2]];
left[tree_] := tree[[2]];
right[tree_] := tree[[3]];
newTree[name_, 
          definition_] := { {name, 
            definition},  {},  {}};
isEmpty[tree_] := 
        Length[tree] == 0;
isSame[a_, b_] := 
        Order[a, b] == 0;
isAlpha[a_, b_] := 
        Order[a, b] == 1;
isNotAlpha[a_, b_] := 
        Order[a, b] == -1;
appendLeft[name_, definition_, tree_] := 
        ReplacePart[tree,  put[name, definition, tree[[2]]],  
          2   ];
appendRight[name_, definition_, tree_] := 
        ReplacePart[tree,  put[name, definition, tree[[3]]],  
          3   ];

    
put[name_, definition_, tree_] := 
        Module[{}, 
If[   isEmpty[tree],  
            Return[newTree[name, 
                definition]]   ]; 
If[   isAlpha[
              name, topWord[tree]],    Return[ 
              appendLeft[name, definition, 
                tree]]]; 
If[   isNotAlpha[name, 
              topWord[tree]],    Return[ 
              appendRight[name, definition, 
                tree]]]; 
Return[tree];     
];
get[name_, tree_] := 
        Module[{}, 
If[ isEmpty[tree],  
            Return[" - not found - "]]; 
If[ 
            isSame[name, topWord[tree]],  
            Return[tree[[1]][[2]]]]; 
If[ 
            isAlpha[name, topWord[tree]],  
            Return[ get[name,  left[tree]]] ]; 
If[ 
            isNotAlpha[name, topWord[tree]],  
            Return[ get[name,  
                right[tree]]] ]; 
Return[" oops - error \
"];
];

    
applyTree[f_, tree_] := 
        Module[{}, 
  
If[ 
            isEmpty[tree],  Return[]]; 
f[
            topWord[tree]]; 
applyTree[f,  
            left[tree]]; 
applyTree[f,  
            right[tree]];
];

depth[d_, tree_] := 
        Module[{dLeft, dRight}, 
If[ isEmpty[tree],  
            Return[d]]; 
dLeft  =  
            depth[d + 1, left[tree]]; 
dRight = 
            depth[d + 1, right[tree]]; 
Return[
            Max[dLeft, 
              dRight]];
];

printTop[word_] := 
        Print[ToString[word]];
printTree[tree_] := 
        applyTree[printTop, 
          tree];

incN[word_] := n++;
countTree[tree_] := 
        Module[{}, 
n = 0; 
applyTree[
            incN,  tree]; 
Return[
            n];
];

\(\(randomWord[] := 
        Module[{word}, 
word\  = \ ""; 
Do[\ 
            word = word <> 
                FromCharacterCode[Random[Integer, {97, 122}]], \ {Random[
                Integer, {3, 6}]}]; 
Return[
            word];
];\)

 (*\ 
      see\ ToCharacterCode\ and\ FromCharacterCode\ *) \)
randomSentence[]  :=  
        FromCharacterCode[Random[Integer, {65, 90}]] <> 
          randomWord[] <> " " <> randomWord[] <> " " <> 
          
          randomWord[] <> ".";

addWord[word_, definition_] := dict = 
          put[word, definition, dict];
lookup[word_] := get[word, dict];
\(\(populate[] := 
        Module[{}, 
dict = {}; 
addWord[
            cat, "lands on its feet"]; 
addWord[
            dog, "might play frisbee"]; 
addWord[
            fish, "Jacque's friend"]; 
addWord[
            snow, "frozen fluffy stuff"]; 
Do[\ 
            addWord[ToExpression[randomWord[]], 
              randomSentence[]], {100}];
];\)
\)
populate[];

lookup[cat]

lookup[shark]

Length[tree]

countTree[dict]

printTree[dict]

lookup[wqou]

lookup[snazzle]

bad = {};
bad = put[a, "1", bad];
bad = put[b, "2", bad];
bad = put[c, "3", bad];
bad = put[d, "4", bad];

bad

bad // TreeForm

bad = {};
Do[ bad = put[i, i, bad], {i, 1, 10}]

bad

better = {};
Do[ better = put[Random[], Random[], better], {i, 1, 10}]

better

bad

depth[0, bad]

depth[0, better]

depth[0, dict]