1. 程式人生 > >字典樹的建立、刪除、查詢

字典樹的建立、刪除、查詢

package arithmetic;
import java.util.*;
class DicNode
{
	int count;//當前字元在這個位置出現的次數
	int next[] = new int[26];//其下一個字元的指標 ,next[i] 中, i 表示字元 ch , next[i] 表示地址
	public String toString()
	{
		StringBuffer s = new StringBuffer();
		s.append(count+" |");
		for(int i =0;i<26;i++)
		{
			if(next[i]==0)
				s.append(" | ");
			else
				s.append((char)(i+'a')+"| ");
		}
		return s.toString();
	}
}

public class DicTree {

	static DicNode tree[] = new DicNode[10000];
	public static void main(String args[])
	{
		for(int i =0;i<tree.length;i++)
			tree[i]= new DicNode();
		create("abcdefg");
		create("ab");
		create("google");
		for(int i =0;i<7;i++)
			{
				System.out.print(i+" ");
				System.out.println(tree[i].toString());
			}
		System.out.println(find("google"));
		del("google");
		System.out.println(find("google"));
		
	}
	
	public static void create(String str)
	{
		
		 int treepos =1;
		 int index = 0;
		 for(int i = 0;i<str.length();i++)
		 {
			 int ch = str.charAt(i)-'a';
 			if(tree[tree[index].next[ch]].count==0)   //表明 字元 ch 還不在樹中
			{
				tree[index].next[ch]=treepos;// tree[index].next[ch] 表示指向 ch 結點的孩子指標,裡面存放的是 ch 在樹中的位置,其值為索引
				tree[treepos++].count=1;
			}else
			{
				tree[tree[index].next[ch]].count++;
			}
			index = tree[index].next[ch];  //當前結點變為其孩子結點
	 }
	}
	public static int find(String str)//找出有沒有以str 為引數的單詞,如果有,在檔案中出現幾次,沒有返回0
	{
		int index = 0;
		for(int i =0;i<str.length();i++)
		{
			int ch = str.charAt(i)-'a';
			if(tree[tree[index].next[ch]].count!=0)  //表示出現過
				index = tree[index].next[ch];
			else
				return 0;
		}
		return tree[index].count;
	}
	public static void del(String str)
	{
		int index =0 ;
		if(find(str)==0)
			{
				System.out.println("this word not find...");
				return ;
			}
		for(int i=0;i<str.length();i++)
		{
			int ch = str.charAt(i)-'a';
			tree[tree[index].next[ch]].count--;
			index=tree[index].next[ch];
			
		}
	}
	
	
}

			/*
			 * 				字典樹建立
			 * 	1.定義一個字典樹的結點,最簡單的是裡面有兩個變數,count 表示出現次數,next[i] i 可以直接表示字元,next[i]裡面儲存是地址,是孩子結點的地址,其實就是孩子結點在tree[] 數組裡面的索引變數
			 *  2.迴圈單詞的所有字元,建立樹進,對於一個單詞,只可能向下走,不能向回走
			 *  3.treepos 表示已經插入的結點的個數,index 表示在插入一個單詞的字元時,走到當前結點在tree[] 裡面的位置,也就是當前結點的位置
			 *  4.tree[index].next[ch] 表示當前結點的孩子結點中,儲存字元 ch 的孩子結點的索引,靠,有點不好表達,要插入字元 b,
			 *  		tree[index].next[b-'a'] 表示的就是 當前所有結點中 字元為b 的結點, 那麼 tree[index].next[b-'a'] 裡面存放的值就是其孩子結點在tree[] 中的索引
			 *  5.如果其孩子結點中的count 值為0,那麼就表示這個字元還沒有插入樹中,所以就要插入,
			 *  6.如果其孩子結點的count 值不為0,那就就直接count ++ 就可以了
			 *  7.無論存不存在,插入操作還是要繼續下一個字元的,所以 index = tree[index].next[ch]
			 *  		記住 tree[n].next[i] 中,i 表示的字元,next[i]是指標,指向其孩子結點為i 的指標,其值就是字元i 結點在tree[] 中的索引值 	
			 * 
			 * 
			 *			字典樹的查詢 
			 *
			 *	1. 遍歷單詞,對於第一個字元從樹根開始查詢 ,檢視當前結點的  ch 孩子結點裡面count 是否為1 ,即 tree[tree[index].next[ch]].count 是否為1
			 *	2. 如果為1 ,則表明此字元存在,向下遍歷,如果為1,則表示不存在,返回
			 *	3. 向下遍歷為  index = treee[index].next[ch] ,這樣會指向其孩子結點 
			 *
			 *
			 *
			 *	字元樹的刪除
			 *	1. 如果單詞在樹中,那麼遍歷單詞,如果於單詞的每個字元找到在樹中的位置 ,將其對應結點中的count--
			 *	2. index = tree[index].next[ch];
			 * */