文章目錄
- 一、C語言能干大事
- 1. C語言下Huffman樹的計算過程分析
- 2. C語言下Huffman樹的編程
- 二、C#語言也不賴
- 1. C#下Huffman類的設計
- 2. C#中界面設計
- 3. 建立測試數據并顯示Huffman樹
- 4. 輸入任意一組數據,完成構造Huffman樹
- 三、JavaScript語言不愛聽了
- 1. JavaScript下Huffman類的設計
- 2. 把權重數據顯示在一個表格里
- 3. 為表格添加命令按鈕
- 4. 編寫添加一行的程序
- 5. 編寫刪除一行的程序
- 6. 用表格中的數據生成Huffman樹表
- 7. 顯示Huffman樹表中的樹
一、C語言能干大事
1. C語言下Huffman樹的計算過程分析
例1 有權重集合分別是:5、29、7、8、14、23、3、11,計算Huffman樹。
這個題目的計算過程如下:
(1)首先是把數據填寫在以下表格里:
這個在編程中一定注意:空白格子里是NULL,這點不要搞錯。
首先是尋找到兩個最小權重的結點,找到的是第7、1號結點,權重合計是8,我們先標記這兩個結點s=1(代表已經處理過了),并生成第9號結點,權重是8,并讓第7、1號結點的父結點是9,第9號結點的左、右孩子分別是第7、1結點,就是如下表:
重復上面的過程,從頭尋找s=0的結點里、權重最小的兩個結點、就是第3、4號結點,權重合計是15,這樣,標記這兩個結點s=1,并生成第10號結點,權重是15,而第7、8的父結點是第10號結點,第10號結點的左右孩子是第3、4號結點,就是下表:
重復這個過程,處理到第15個結點,使其權重合計為100,就是:
最終這個樹的計算到此結束,在這樣的表中計算出的過程以及結果,就是我們下面編程的主要依據。
2. C語言下Huffman樹的編程
針對前面介紹的表格,用C語言描述這樣的表就是:
struct Huffman
{int W,Parent,lChild,rChild,S;
};
對Huffman樹,由于它是正則二叉樹,所以有n個權重數據則必然有2*n-1個樹結點。
有了表的C語言定義,則首先是尋找未標記的、權重最小的結點,如果這個表是H,則全部代碼就是:
int FindMinNode(struct Huffman *H,int N)
{int i,W,Node;W=100;Node=0;if(H==NULL) return -1;for(i=0;i<N;i++){if(H[i].W>0&&H[i].W<W&&H[i].S==0){W=H[i].W;Node=i;}}H[Node].S=1;return Node;
}
第6至第12行,是一個典型的數組中求最小值的算法,在第13行,則必須標記這個結點的S=1,說明該結點已經使用過,最后則返回這個結點的編號。
有了這個函數后,首先要對H表進行兩次求最小值的操作,就是:
min1=FindMinNode(H,N); min2=FindMinNode(H,N);
如第i行是新增的一個結點,則讓該表第i行的權重為:
H[i].W=H[min1].W+H[min2].W;
然后,就是設置這個結點的左右孩子結點為min1、min2,就是:
H[i].Parent=-1; H[i].lChild=min1; H[i].rChild=min2;
最后,就是設置編號min1、min2的結點的父結點是第i個結點。
H[min1].Parent=i; H[min2].Parent=i;
全部就是:
int ConstructHuffmanTree(struct Huffman *H,int n)
{int i;int min1,min2,N;if(n==0) return -1;if(H==NULL) return -2;N=2*n-1;for(i=n;i<N;i++){min1=FindMinNode(H,N);min2=FindMinNode(H,N);H[i].W=H[min1].W+H[min2].W;H[min1].Parent=i;H[min2].Parent=i;H[i].Parent=-1;H[i].lChild=min1;H[i].rChild=min2;}return 0;
}
注意這個函數第8行,它是從第n個結點開始循環的。
有了這兩個函數后,用一個測試的main()來測試它們:
main()
{int n,N,i,*D;struct Huffman *H;n=8;//組織scanf()輸入N=2*n-1;D=(int *)malloc(sizeof(int)*n);//組織scanf()輸入。D[0]=5;D[1]=29;D[2]=7;D[3]=8;D[4]=14;D[5]=23;D[6]=3;D[7]=11;H=(struct Huffman *)malloc(sizeof(struct Huffman)*N);for(i=0;i<N;i++) {H[i].W=0;H[i].Parent=0;H[i].lChild=0;H[i].rChild=0;H[i].S =0;}for(i=0;i<n;i++)H[i].W =D[i];ConstructHuffmanTree(H,n);printf("ID\tW\tP\tL\tR\n");for(i=0;i<N;i++)printf("%d\t%d\t%d\t%d\t%d\n",i,H[i].W,H[i].Parent,H[i].lChild,H[i].rChild);
}
運行結果如下圖所示:
Huffman樹的C語言程序到此為止。
二、C#語言也不賴
1. C#下Huffman類的設計
僅僅針對前面C語言中的計算方法,設計一個類來完成計算過程,這個類就是:
class Huffman{public int W, pChild, lChild, rChild, s;public Huffman(){W = pChild = lChild = rChild = -1;s =0; }public Huffman(int Weight, int PChild, int LChild, int RChild, int Select){W = Weight; PChild = pChild; lChild = LChild; rChild = RChild; s = Select; }}
2. C#中界面設計
有了這個類以后,我們可以在界面設計上拖進兩個命令按鈕button1,button2,然后再拖進一個treeView1控件和imageList1控件,然后開始以下設置:
(1) 選擇imageList1控件,找到屬性images,加入文件夾MyIcon中的兩個小圖標;
(2) 選擇treeView1控件,讓imageList屬性選中imageList1控件;
(3) 選擇treeView1控件,讓SelectImageIndex=1(打開書的圖標);
(4) 選擇treeView1控件,讓ImageIndex=0(關閉書的圖標);
(5) 選擇button1控件,修改text屬性為:”簡單測試”;
(6) 選擇button2控件,修改text屬性為:”結束”
3. 建立測試數據并顯示Huffman樹
設有權重數據為:5,29,7,8,14.23.3.11,注意權重數據和必須是100。首先是編寫從Huffman類數組中取得最小權重結點的函數,這個函數編寫在Form1程序中,鼠標雙擊button1,注意在button1_click()前面補充這樣的函數,就是:
在這個函數中,H是Huffman結點對象數組,而N是這個數組的數據個數,如果是上例,則N=15。
現在開始補充代碼如下:
int FindMinNode(Huffman[] H,int N){ int i,W,Node;W=100;Node=0;if(H==null) return -1;for(i=0;i<N;i++){if(H[i].W>0&&H[i].W<W&&H[i].s==0){W=H[i].W;Node=i;}}H[Node].s=1;return Node;}
這個函數同C的幾乎沒什么差別,同樣返回這個結點的下標。有這個函數后,就可以構造Huffman樹,跟隨著上面的函數,繼續輸入就是:
int ConstructHuffmanTree(Huffman[] H,int n){int i;int min1,min2,N;if(n==0) return -1;if(H==null) return -2;N=2*n-1;for(i=n;i<N;i++){min1=FindMinNode(H,N);min2=FindMinNode(H,N);H[i].W=H[min1].W+H[min2].W;H[min1].pChild=i;H[min2].pChild=i;H[i].pChild=-1;H[i].lChild=min1;H[i].rChild=min2;}return 0;}
其基本算法和C語言的也沒什么差別。
但這個Huffman類的樹是不能顯示在treeView1中的,控件treeView1只能顯示TreeNode類型的樹,所以要按這個表格的內容構造TreeNode類對象的樹。
在treeView1控件中,顯示的結點個數同Huffman類的結點個數是一致的,而每個TreeNode類結點的Text內容則是權重,于是緊跟著上面的函數,寫以下函數就是:
void dTree(Huffman[] H){int i,n,a,b;n = H.Count();TreeNode[] T = new TreeNode[n];for(i=0;i<n;i++)T[i]=new TreeNode(H[i].W.ToString());for (i = 0; i <n; i++){a = H[i].lChild;
b = H[i].rChild;if (a >= 0) T[i].Nodes.Add(T[a]);if (b >= 0) T[i].Nodes.Add(T[b]);}treeView1.Nodes.Add(T[n-1]); }
最后,就是補充button1下的程序,按實驗數據有:
這組數據一共8個,所以Humman樹一共將有2*8-1=15個結點,鼠標雙擊button1,寫進以下程序:
private void button1_Click(object sender, EventArgs e){Huffman[] H = new Huffman[15];H[0] = new Huffman(5, -1, -1, -1, 0);H[1] = new Huffman(29, -1, -1, -1, 0);H[2] = new Huffman(7, -1, -1, -1, 0);H[3] = new Huffman(8, -1, -1, -1, 0);H[4] = new Huffman(14, -1, -1, -1, 0);H[5] = new Huffman(23, -1, -1, -1, 0);H[6] = new Huffman(3, -1, -1, -1, 0);H[7] = new Huffman(11, -1, -1, -1, 0);for (int i = 8; i < 15; i++) H[i] = new Huffman();ConstructHuffmanTree(H, 8);dTree(H);}
到此,簡單的Huffman樹的測試程序設計完成。最后在button2_click()中補充代碼:this.close()
;讓程序能正常結束。
4. 輸入任意一組數據,完成構造Huffman樹
為完成這個要求,首先要在界面設計中再補充控件,有:
(1) 補充listBox1控件;
(2) 補充button3控件,修改Text屬性為:“輸入確認”;
(3) 補充button4控件,修改Text屬性為:”生成Huffman樹”;
(4) 補充button5控件,修改Text屬性為:”清除”;
(5) 補充textBox1控件;
有了上述控件后,我們首先設計操作過程是:
在textBox1控件中輸入數據,按下button3按鈕“輸入確認”,則輸入的數據顯示在listBox1控件中,直到所有數據輸入完成,于是這樣的操作要求的程序就是:
private void button3_Click(object sender, EventArgs e){listBox1.Items.Add(textBox1.Text); }
listBox1控件是個數據容器,你可以不斷追加進很多數據,這些數據全部可以保存在這個控件中。直到按下button4”生成Huffman樹”,才開始計算。所以button4的程序就是:
private void button4_Click(object sender, EventArgs e){int n = listBox1.Items.Count;Huffman[] H = new Huffman[2*n-1];for (int i = 0; i < 2 * n - 1; i++)H[i] = new Huffman();for(int i=0;i<n;i++){int w=int.Parse( listBox1.Items[i].ToString()) ;H[i].W = w; }ConstructHuffmanTree(H, n);dTree(H);}
表7中第3行,相當于從listBox1控件中獲得數據項的個數,在第9行,就是逐個取得每個數據項,并轉換成int類型、賦值給Huffman類對象數組中每個對象的權重W。最后按同樣的方式計算并顯示在treeView1中。
注意這個程序實際很不理想,沒判斷輸入的數據是否有負值、是否是非數字的字符串、是否和為100等等,這些詳細的判斷留給同學們自己去完成。
對于button5”清除”的編程非常簡單,就是:
private void button5_Click(object sender, EventArgs e)
{listBox1.Items.Clear();treeView1.Nodes.Clear();textBox1.Text = "";
}
程序運行效果:
三、JavaScript語言不愛聽了
1. JavaScript下Huffman類的設計
針對前面C語言中的計算方法,設計一個類來存儲數據,如果你使用的Ext系統,則強烈建議直接使用Ext.data.ArrayStore類對象直接構造它,這樣的好處是顯示在表格里非常方便,于是說明對象tstore為:
var tstore = new Ext.data.ArrayStore({data:[[0,5 ,-1, -1,-1,0],[1,29,-1, -1,-1,0],[2,7 ,-1, -1,-1,0],[3,8 ,-1, -1,-1,0],[4,14,-1, -1,-1,0],[5,23,-1, -1,-1,0],[6,3 ,-1, -1,-1,0],[7,11,-1, -1,-1,0]],fields: [{name: 'id' ,type:'int'},{name: 'w' ,type:'int'},{name: 'pChild',type:'int'},{name: 'lChild',type:'int'},{name: 'rChild',type:'int'},{name: 's' ,type:'int'}]});
運行效果:
這個程序非常直觀,它說明有一個表名稱是tstore,其中右6列,data下說明了數據,在field下說明了各個列的名稱、分別是id,w,pChild,lChild,rChild,s這樣的6列,如同下表:
2. 把權重數據顯示在一個表格里
但這個表用來顯示在界面上則非常不好看,我們需要一個友好的界面,所謂友好的界面就是說用漢字顯示、而不是奇怪符號顯示的界面,如:
我們一般把表2成為邏輯表,表3稱為顯示表,它們兩者之間的關系應該是一一對應的,唯獨列名稱不一樣。造成這樣的結果,主要原因是程序計算過程中,我們期望變量名都是英語字符,這樣非常方便編程,但顯示,則必須是漢字的表頭。
把這兩者統一起來:就是說讓“結點編號”指向邏輯表的“id”列,要用到Ext.grid.ColumnModel類型的對象,如該對象的名稱是colM,則定義如下:
var colM=new Ext.grid.ColumnModel([
{列對象1屬性},
{列對象2屬性},
…
{列對象n屬性}
]);
注意JavaScript中、一旦出現[ ]則代表是數組,所以這些個列對象也就相當于數組中的各個元素。
一個典型的設置就是:如將表格第1列顯示為“結點編號”、并和數據邏輯表tstore中的id關聯起來、并在該列上提供排序、而且該列可以編輯,則就是:
{header:"結點編號",dataIndex:'id',sortable:true,editor:new Ext.form.TextField()
}
實際就是設置了列對象的4個屬性。這僅僅是為第一列,如果是所有列,則:
var colM=new Ext.grid.ColumnModel([{header:"結點編號",dataIndex:'id',sortable:true,editor:new Ext.form.TextField()},{header:"結點權重",dataIndex:'w',sortable:true,editor:new Ext.form.TextField()},{header:"父結點編號",dataIndex:'pChild',sortable:true,editor:new Ext.form.TextField()},{header:"左結點編號",dataIndex:'lChild',sortable:true,editor:new Ext.form.TextField()},{header:"右孩子編號",dataIndex:'rChild',sortable:true,editor:new Ext.form.TextField()},{header:"選擇狀態",dataIndex:'s',sortable:true,editor:new Ext.form.TextField()}]);
注意在最后一個列對象定義完后、第37行后沒有”,”,這點初學者一定要記著。
有了數據、有了列定義以后,就可以顯示表格了,顯示表格用的是Ext.grid.EditorGridPanel類對象,就是按下面的語句:
var grid=new Ext.grid.EditorGridPanel({表對象屬性});
含義是定義了一個表對象grid,而該表的顯示屬性則由表對象屬性中說明。如:
var grid=new Ext.grid.EditorGridPanel({renderTo:"hello",title:"Huffman樹",height:400,width:620,cm:colM,store:tstore});
其中屬性:
- renderTo:說明這個表格顯示在哪里,在表5中是在”hello”中,這個hello實際是用HTML語言定義的一個分區,就是,有了這個分區,grid就將顯示在該區域里;
- title:表示該表格的標題;
- height:表示該表格的高度;
- width:表示該表格的寬度;
- cm:表的列定義,需要一個列對象來說明各個列,如表4;
- store:表示該表顯示的數據來自哪里,在我們的程序中,數據來自表1定義的tstore。
將上述程序代碼合并到一個函數里就是:
function fun(){var tstore = new Ext.data.ArrayStore({data:[[0,5 ,-1, -1,-1,0],[1,29,-1, -1,-1,0],[2,7 ,-1, -1,-1,0],[3,8 ,-1, -1,-1,0],[4,14,-1, -1,-1,0],[5,23,-1, -1,-1,0],[6,3 ,-1, -1,-1,0],[7,11,-1, -1,-1,0]],fields: [{name: 'id' ,type:'int'},{name: 'w' ,type:'int'},{name: 'pChild',type:'int'},{name: 'lChild',type:'int'},{name: 'rChild',type:'int'},{name: 's' ,type:'int'}]});//表格上列名稱顯示、以及表格上數據處理方式。var colM=new Ext.grid.ColumnModel([{header:"結點編號",dataIndex:'id',sortable:true,editor:new Ext.form.TextField()},{header:"結點權重",dataIndex:'w',sortable:true,editor:new Ext.form.TextField()},{header:"父結點編號",dataIndex:'pChild',sortable:true,editor:new Ext.form.TextField()},{header:"左結點編號",dataIndex:'lChild',sortable:true,editor:new Ext.form.TextField()},{header:"右孩子編號",dataIndex:'rChild',sortable:true,editor:new Ext.form.TextField()},{header:"選擇狀態",dataIndex:'s',sortable:true,editor:new Ext.form.TextField()}]);//表格開始顯示數據。var grid=new Ext.grid.EditorGridPanel({renderTo:"hello",title:"Huffman樹",height:400,width:620,cm:colM,store:tstore});}
Ext.onReady(fun);
有了表7的程序,我們打開m.html,這個程序是一個調用Ext類庫的模板程序,把表7的程序補充到這個程序里的fun()函數里即可執行,結果將顯示一個表。
注意第72行不是這個函數中的語句,而是一條獨立的JavaScript語句。現在就可以以m.html為模板文件,加入表7的程序。
3. 為表格添加命令按鈕
如果一個程序僅僅能計算一組數據,那么這個程序實際沒什么意義,為此,我們要給表格上加入三個命令按鈕,就是:添加、刪除、生成Huffman樹,使其能添加一行、刪除一行,并能根據新的數據生成Huffman樹。
給表格上添加三個命令按鈕,就是給grid對象上再說明一個工具條、并顯示出三個命令按鈕。也就是說給該對象的tbar屬性說明命令按鈕對象的屬性說明,就是:
tbar:[{按鈕對象1屬性},{按鈕對象2屬性},…{按鈕對象n屬性} ]
對一個命令按鈕屬性,比如產生一個叫”新增”的命令按鈕,則可以是這樣來說明:
{ text: "新增", iconCls: "add", handler: function(){ //以下寫進新增加一行的代碼} }
text:表明這個按鈕上顯示的字符,如VB6中Command控件上的Caption屬性;
iconCls:這個按鈕上要顯示的圖標;
handler:function() { }:就是按下這個按鈕后的響應程序;
同VB6的設計思路是一致的,但這里完全沒有VB6那樣的編程環境,所以逐個屬性只能自己在鍵盤上輸入。
現在,我們要在表格對象grid上的工具欄tbar中說明三個按鈕,則就是一下的程序:
var grid=new Ext.grid.EditorGridPanel({renderTo:"hello",title:"Huffman樹",height:400,width:620,cm:colM,store:tstore,tbar: [ { text: "新增", //iconCls: "add", handler: function(){ //以下寫進新增加一行的代碼} }, { text: "生成Huffman樹", //iconCls: "refresh", handler: function(){ //以下寫進生成新Huffman樹的代碼} }, { text: "刪除一行", //iconCls: "delete", handler: function(){ //以下寫進表格中刪除一行的代碼} } ]});
注意同表5的對比。新增加的三個命令按鈕,在執行h1.html的時候則就會看到。當然,它們目前是什么都不會執行,僅僅是有三個命令按鈕。
運行效果:
執行h0.html和h1.html,看看這兩個網頁的差異。
4. 編寫添加一行的程序
編寫這個程序,實際就是為表8的第15行處補充代碼,補充這樣的代碼,首先要獲得表格中當前有幾行,這個數據要從tstore中去獲得,就是:
var n=tstore.getCount();
然后構造一個默認的數據行,用的是:
var defData={id:n,pChild:-1,lChild:-1,rChild:-1,s:0};
就是說id的值是n,pChild=lChild=rChild=-1,s=0,讓權重w為空白。
最后,構造一個第n行的記錄,并插入到tstore中去,就是:
var r=new tstore.recordType(defData,n);
tstore.insert(tstore.getCount(),r);
一旦數據插入tstore,則在grid中會自動顯示結果。完整的函數就是:
Handler: function(){ var n=tstore.getCount();var defData={id:n,pChild:-1,lChild:-1,rChild:-1,s:0};var r=new tstore.recordType(defData,n);tstore.insert(tstore.getCount(),r);}
運行效果:
5. 編寫刪除一行的程序
刪除一行數據,首先要選中表中的一行,如果沒有選中,則要給出提示。
var record = grid.getSelectionModel().selection.record;
如果正常獲得了選中的行,則要找到這一行數據是在tstore中的哪一行,就是在對象tstore中按record來查找:
var index = tstore.indexOf(record);
這樣,index就是表格中對應的行號,有了行號,就可以:
tstore.removeAt(index);
來刪除這一行。
但一定要注意:假如你沒有選中表格中的任何一行,執行上面的過程則會發生錯誤,這個是非常重要的事情,否則刪除操作會讓程序經常崩潰。為此,這段程序要加入到JavaScript語言的try過程中,就是
try
{
//這里加入要嘗試著做的程序段落
}
catch(err)
{
//如果嘗試著做的程序段無法正常執行,則在這里給出錯誤的提示, err對象中有
//錯誤的描述。
}
注意這個語句,在C#中也有同樣的語句,這個語句非常重要,經常會出現在一些需要嘗試著做的工作中,諸如在涉及到硬件訪問、用戶操作不確定的場合下,按這個語句的過程來執行程序,則是必須的。有了這個過程,則完整的刪除程序就是:
handler: function(){ try{var record = grid.getSelectionModel().selection.record; var index = tstore.indexOf(record); tstore.removeAt(index); }catch(err){Ext.MessageBox.alert("刪除錯誤提示","未選中任何行,不能刪除.");return;}
}
注意表10的程序是添加在表8的第32行處,這個程序在這里是完整的,但它是對象grid說明的一個組成部分。
現在運行h2.html,則可以測試加入一行數據、并刪除一行數據了。
6. 用表格中的數據生成Huffman樹表
要生成一個Huffman樹,則首先要從表格中計算各個結點的權重值,為此,又首先要獲得表格中未用過結點的最小權重結點,為此,編寫函數如下:
function FindMinNode(astore){var i,n,w=100,m=-1;n=astore.getCount();for(i=0;i<n;i++){if(astore.getAt(i).get('s')==0&&w>astore.getAt(i).get('w')){w=astore.getAt(i).get('w');m=i;}}astore.getAt(m).set('s',1);return m;}
這個函數的參數是astore,函數是逐行讀這個對象中s=0的那些行,找到最小權重行的下標值、并存在m中,查找完后,在第12行,把該行的s列修改為1,然后返回這個下標值。這個算法的原理和C#是一致的。
有這個函數后,就可以在“生成Huffman樹”按鈕下的響應程序里補充這些代碼,構造一個Huffman樹,就是:
handler: function(){ var n=tstore.getCount();for(i=n;i<2*n-1;i++) {var min1=FindMinNode(tstore);var min2=FindMinNode(tstore);tstore.getAt(min1).set('pChild',i);tstore.getAt(min2).set('pChild',i);var nw=tstore.getAt(min1).get('w')+tstore.getAt(min2).get('w');var newNode={id:i,w:nw,pChild:-1,lChild:min1,rChild:min2,s:0};var r=new tstore.recordType(newNode,i);tstore.insert(tstore.getCount(),r);}dTree(tstore);}
在第6、7行,每次獲得對象tstore中兩個最小權重結點;
在第8、9行,修改tstore表中第min1、min2兩行的pChild列,使這兩個行的父結點等于新的這一行(第i行);
在第10行,則是讀第min1、min2行的權重求和、結果在nw中;
在第11行,按新的權重nw構造一個結點,其左孩子是min1,右孩子是min2,s=0;
在第12、13行,則是把這一行新的記錄插入到tstore中,同時也會顯示在grid對象中;
最后,在第15行調用dTree(tstore)函數,顯示在一個treeView對象中。
注意這個函數實際是在表9的第23行處補充的。
7. 顯示Huffman樹表中的樹
顯示一個樹,在Ext系統中首先要構造Ext.tree.TreeNode類型的結點,這里和C#中的概念是一樣的,Ext.tree.TreeNode類型的結點個數和Huffman表tstore中的行數是一致的,為此,就是這樣的過程來構造這些Ext.tree.TreeNode類型的結點并顯示出來:
function dTree(astore)
{var i,n;var TA=new Array();n=astore.getCount();for(i=0;i<n;i++)TA[i]=new Ext.tree.TreeNode({id:astore.getAt(i).get('id'),text:astore.getAt(i).get('w')}); for(i=0;i<n;i++){var a = astore.getAt(i).get('lChild'); var b = astore.getAt(i).get('rChild');if (a >= 0) TA[i].appendChild(TA[a]);if (b >= 0) TA[i].appendChild(TA[b]);}treeView1=new Ext.tree.TreePanel({renderTo:"Tree",root:TA[n-1],width:300,height:400});
}
這個函數的算法和C#中的完全一致,沒有差別,只不過一些語句修改成JavaScript語句而已。
到這里,一個完整的Huffman樹生成、顯示程序完成了。
一定保留好這個程序的所有代碼,這樣的代碼在隨后的數據庫課程中使用的非常廣泛,它不僅僅是一個簡單的樹的問題,很多應用都需要類似的界面。而這個程序里最關鍵的數據對象tstore,在數據庫中則要用Ajax技術來從數據庫服務器中、通過一種叫WebServices的程序系統來獲得,其中,相當多數的WebServices程序是由C#來編寫的,由Ext執行結果也要通過C#的WebServices作用到數據庫服務器中去。一個華麗的數據庫應用系統,必須是在華麗的外觀下實現的,而C#、Ext系統則是這個系統中最重要的組成部分。
隨后,在數據庫的課程中,我們將在VS2008中、使用C#、JavaScript Ext、SQLServer系統來完成這樣的開發,所以這樣的基礎知識是非常關鍵的。