標籤:
廣義表是線性表的推廣,也有人稱其為列表。 那麼它和線性表有什麼區別呢?線性表中每個成員只能是單個元素,而廣義表中的成員可以是單個元素,也可以是廣義表,分別稱為廣義表的原子和子表。下面舉幾個廣義表的例子。
A=();
B=(e);
C=(a,(b,c,d));
D=((),(e),(a,(b,c,d)));
E=(a,E);
由於廣義表中的資料元素可以具有不同的結構(原子或列表),因此難以用順序儲存結構表示,通常採用鏈式儲存結構。由於列表中的元素可以是原子也可以是列表,所以需要兩種結構的節點,一種是表節點,一種是原子節點。
一個表節點由三個域組成,標誌域、指向表頭的指標域、指向表尾的指標域。而原子節點只需要兩個域,標誌域和值域。如:
上面講到的五個列表的儲存結構如:
我們用javascript來實現廣義表及其基本操作吧。
首先需要定義廣義表的儲存結構:
var ATOM=0;var LIST=1;//廣義表的儲存結構function ListNode(){//標識位this.tag=undefined;//原子結點的範圍this.atom=null;//列表結點的範圍this.ptr={hp:null,tp:null};}
然後是建立廣義表的過程:
//建立廣義表ListNode.prototype.createList=function(string){string=string.trim();//建立單原子廣義表var q;if(/^[\w-]+$/.test(string)){//含有單字元this;tag=ATOM;this.atom=string;}else{this.tag=LIST;var p =this;//去掉最外層括弧(和)var sub=string.substr(1,string.length-2);do{var h,i=0,k=0,n=sub.length,ch;do{ch=sub[i++];if(ch=='('){++k;}else if(ch==')'){--k;}}while(i<n&&(ch!=','||k!=0));//i為第一個逗號分隔索引if(i<n){h=sub.substr(0,i-1);//每次遍曆取出第一個結點,無論是原子還是列表sub=sub.substr(i,n-i);}else{//最後一組h=sub;sub='';}if(h==='()'){//空子表無表頭結點p.ptr.hp=null;}else{//建立表頭結點this.createList.call((p.ptr.hp=new ListNode()),h);}q=p;//建立表尾結點if(sub){p=new ListNode();p.tag=LIST;q.ptr.tp=p;}}while(sub);q.ptr.tp=null;}}; 接下就是求廣義表的深度,深度的定義為廣義表中括弧的重數,是廣義表的一種量度。例如,多元多項式廣義表的深度為多項式中變元的個數。設LS=(a1,a2,a3,…,an),求LS的深度可以分解為n個之問題,每個子問題為求ai的深度。如果ai是原子,則定義其深度為0,如果ai是廣義表,則LS的深度為最大ai的深度+1。空表也是廣義表,所以深度為1。實現代碼如下:
//求廣義表的深度ListNode.prototype.depth=function(){return getDepth(this);}function getDepth(list){//深度為括弧的重數,也可理解為左括弧出現的個數if(!list){return 1;}else if(list.tag===ATOM){return 0;}else {var m=getDepth(list.ptr.hp)+1;var n=getDepth(list.ptr.tp);return m>n?m:n;}}
最後我們建立測試案例:
var node=new ListNode();node.createList('((),(a),(b,(c,d,e)))');alert(node.depth());//5
node結點詳細如:
完整代碼如下:
由於廣義表的應用多在於數學領域的公式推導和演算上,這裡就不再詳解了。
廣義表的表示javascript