昨晚偶然看到了字典树,今天把二叉树与字典树的内容复习了一下,用C++与Java实现,发现了一些问题。
1.二叉树
C++实现
#include<iostream>
using namespace std;
typedef struct BitNode{
char value;
BitNode *lchild;
BitNode *rchild;
}BitNode,*BitTree;
//先序法建树
//*&表示对指针的引用
void build(BitNode *&root){
char ch;
ch=getchar();
if(ch=='#'){
root = NULL;
}else{
root=(BitNode*)malloc(sizeof(BitNode));
if(!root) exit(0); //分配失败,退出
root->value = ch;
build(root->lchild);
build(root->rchild);
}
}
/*
//参数要用&引用传递,否则root不会改变
void build(BitTree &root){
char ch;
ch=getchar();
if(ch=='#'){
root = NULL;
}else{
root=(BitNode*)malloc(sizeof(BitNode));
if(!root) exit(0); //分配失败,退出
root->value = ch;
build(root->lchild);
build(root->rchild);
}
}
*/
void traverse(BitNode *&root){
if(root==NULL)
return;
cout<<root->value<<" ";//根据位置不同分为先序、中序、后序
traverse(root->lchild);
traverse(root->rchild);
}
int max(int a,int b){
return a>b?a:b;
}
//depth包含了根节点
int getDepth(BitTree root,int depth){
if(root!=NULL){
depth++;
int ld = getDepth(root->lchild,depth);
int rd = getDepth(root->rchild,depth);
return max(ld,rd);
}else return depth;
}
int main(){
BitTree root;
build(root);
traverse(root);
int d = getDepth(root,0);
cout<<endl;
cout<<"The depth of the tree is "<<d<<endl;
return 0;
}
Java实现
import java.util.Scanner;
//注意值传递和引用传递
public class Tree
{
public static Scanner cin = new Scanner(System.in);
public static String line = null;
public static int i=0;
static class BitNode{
char value;
BitNode lchild;
BitNode rchild;
}
public static BitNode build(BitNode root){
char ch = line.charAt(i);
if(ch =='#'){
root = null;
i++;
}else{
root = new BitNode();
root.value = ch;
i++;
root.lchild = build(root.lchild); //note different from C++
root.rchild = build(root.rchild); //note
}
return root;
}
public static void traverse(BitNode root){
if(root!=null){
System.out.print(root.value+" ");
traverse(root.lchild);
traverse(root.rchild);
}
}
//include the root
public static int getDepth(BitNode root){
if(root==null) return 0;
int ld,rd,max;
ld = getDepth(root.lchild);
rd = getDepth(root.rchild);
max = (ld>rd?ld:rd);
return max+1;
}
public static void main(String[] args){
System.out.println("Please input the data of the tree");
//example input:53#4##6##
line = cin.nextLine();
BitNode root= null;
root = build(root);
traverse(root);
System.out.println();
System.out.println("The depth of the tree is "+getDepth(root));
}
}
2.字典树
C++实现
#include<iostream>
#include<string.h>
using namespace std;
struct node{
bool isWord;
struct node* next[26];
node(){
isWord = false;
for(int i=0;i<26;i++){
next[i] = NULL;
}
}
};
//the root of the trie
node *root;
void insert(string word){
if(word.empty()) return;
if(root==NULL) root = new node;
node *tmp = root;
int pos =0;
for(int i=0;i<word.length();i++){
pos = word[i]-'a';
if(!(tmp->next[pos]))//if is NULL
tmp->next[pos] = new node; //allocate
tmp = tmp->next[pos];
}
tmp->isWord=true;//set when the word is inserted completely
}
bool search(string word){
if(root==NULL)
return false;
node *tmp = root;
int pos=0;
for(int i=0;i<word.length();i++){
pos = word[i] - 'a';
if(!tmp->next[pos])
return false;
tmp = tmp->next[pos];
}
return tmp->isWord;
}
int main(){
insert("abcd");
insert("abc");
insert("a");
cout<<search("abcd")<<endl;
cout<<search("abc")<<endl;
cout<<search("abcde")<<endl;
return 0;
}
Java实现
import java.util.Scanner;
public class Trie
{
public static node root = null;
static class node
{
boolean isWord;
node[] next = new node[26];
node(){
isWord = false;
for(int i=0;i<26;i++){
next[i] = null;
}
}
}
public static void insert(String word){
node tmp;
if(root == null) root = new node();
tmp = root;
for(int i=0;i < word.length();i++){
int pos = word.charAt(i)-'a';
if(tmp.next[pos] == null)
tmp.next[pos] = new node();
tmp = tmp.next[pos];
}
tmp.isWord = true;
}
public static boolean search(String word){
if(word.isEmpty()) return false;
node tmp = root;
for(int i = 0;i < word.length();i++){
int pos = word.charAt(i)-'a';
if(tmp.next[pos]==null)
return false;
tmp = tmp.next[pos];
}
return tmp.isWord;
}
public static void main(String[] args){
System.out.println("Insert \"abcd\"");
insert("abcd");
System.out.println("search abc: "+search("abc"));
System.out.println("search abcd: "+search("abcd"));
System.out.println("search abccde: "+search("abcde"));
}
}
编码的过程中遇到了一些麻烦,要特别注意值传递与引用传递区别。build(BitNode *&root)这里*&表示对指针的引用。另外c++的引用传递与Java的引用传递是不同的。C++引用传递是直接对原地址进行操作,而Java的引用传递,传递的是引用的副本,函数体中可以改变它的指向,这样就与C++中的引用不同了。因此Java在创建二叉树的时候采用了如下的方式,而c++则不需要。
root.lchild = build(root.lchild); //note different from C++
root.rchild = build(root.rchild);
插入与查找可以合并为同一个函数,如下:
public class Trie{
static Node root = new Node();
static class Node{
public boolean isWord;
public Node[] next;
public Node(){
isWord = false;
next = new Node[26];
}
}
static boolean search(String word){
if(word.isEmpty()) return false;
Node root = Trie.root;
for(int i = 0;i < word.length();i++){
int pos = word.charAt(i) - 'a';
if(root.next[pos] == null) root.next[pos] = new Node();
if(i == word.length()-1){
if(root.next[pos].isWord) return true;
root.next[pos].isWord = true;
}
root = root.next[pos];
}
return false;
}
public static void main(String[] args){
String word1 = "hello";
String word2 = "world";
String word3 = "hello";
System.out.println(search(word1));
System.out.println(search(word2));
System.out.println(search(word3));
}
}
关于字典树的应用,比如对海量数据的处理等知识,可以参考网上的内容。