提到存儲結(jié)構(gòu),可以很自然的想到順序存儲結(jié)構(gòu)和鏈?zhǔn)酱鎯Y(jié)構(gòu)兩種。樹這種數(shù)據(jù)結(jié)構(gòu)類型,它是由結(jié)點(diǎn)和聯(lián)接結(jié)點(diǎn)的邊構(gòu)成。這些邊,聯(lián)接了樹中的任意兩個結(jié)點(diǎn),從計(jì)算機(jī)內(nèi)存中的存儲方式來看,其實(shí),就是通過指針保存了地址,從而實(shí)現(xiàn)了兩個結(jié)點(diǎn)間的聯(lián)接。
察布查爾錫伯網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián),察布查爾錫伯網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為察布查爾錫伯近1000家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站建設(shè)要多少錢,請找那個售后服務(wù)好的察布查爾錫伯做網(wǎng)站的公司定做!
那么關(guān)于樹的表示方式,先講一下最簡單的,就是雙親表示法,我把它稱之為父節(jié)點(diǎn)表示法。畢竟,在樹中,雙親結(jié)點(diǎn)其實(shí)就是父節(jié)點(diǎn)。既然,鏈表也是有結(jié)點(diǎn)構(gòu)成,那么,這個結(jié)點(diǎn)中,必然的必須得有能夠存放數(shù)據(jù)的變量,以及存放下一個結(jié)點(diǎn)的地址的變量,如果沒有這個變量,如何建立兩個結(jié)點(diǎn)間的聯(lián)接呢?但是,此時(shí),這個存放的地址的變量,并不是存放下一個結(jié)點(diǎn)的地址,存放的是它的父節(jié)點(diǎn)的地址,也就是父節(jié)點(diǎn)在數(shù)組中的下標(biāo)位置。然后還得再定義一個樹結(jié)構(gòu),這個數(shù)結(jié)構(gòu)中,必須得包含一個數(shù)組,因?yàn)閿?shù)組就是用來表示結(jié)點(diǎn)的,還得有一個根節(jié)點(diǎn)的位置變量以及結(jié)點(diǎn)數(shù)的變量。那么,該結(jié)構(gòu)定義如下:
#define MAX_TREE_SIZE 100 typedef int TElemType; typedef struct PTNode{ TElemType data; int parent; }PTNode; typedef struct{ PTNode nodes[MAX_TREE_SIZE]; int r, n; }PTree;
因?yàn)?,根?jié)點(diǎn)就是祖先,所以它沒有父類,所以,約定,根節(jié)點(diǎn)的位置域設(shè)置為-1。
如上圖所示,結(jié)點(diǎn)A就是根結(jié)點(diǎn)。
下標(biāo) data parent 0 A -1 1 B 0 2 C 0 3 D 0 4 E 1 5 F 1 6 G 1 7 H 2 8 I 3 9 J 3
因?yàn)锽的父親是A,所以B中存放了A的下標(biāo)0,C和D的父親都是A,所以都存放了下標(biāo)0,E、F和G的父親是B,所以它們存放了B的下標(biāo)1;H的父親是C,所以H存放了下標(biāo)2;I和J的父親是D,所以它們存放了D的下標(biāo)3。這種方式可以知道哪個結(jié)點(diǎn)是哪個結(jié)點(diǎn)的父親,哪個結(jié)點(diǎn)是哪個結(jié)點(diǎn)的兒子,但是卻無法確定順序,也就是說,一個結(jié)點(diǎn)可能擁有多個子節(jié)點(diǎn),但是卻無法確定這些子節(jié)點(diǎn)哪個在前哪個在后。雙親表示法求父節(jié)點(diǎn)方便,因?yàn)槊總€結(jié)點(diǎn)中都保存了其父節(jié)點(diǎn)的下標(biāo)。
第二種方式。孩子表示法。依然采用連續(xù)存儲,也就是數(shù)組存儲,不過,一個結(jié)點(diǎn)分為兩部分,一部分放數(shù)據(jù),另一部分放其子節(jié)點(diǎn)的指針(地址)。若是一個結(jié)點(diǎn)有多個孩子,假設(shè)A有三個孩子,B、C和D。那么,A中就存放B的指針域,在B中則存放C的指針域,C中則存放D的指針域,也就是A的孩子采用了鏈?zhǔn)酱鎯Φ姆绞?,串?lián)了起來。孩子表示法,求其子節(jié)點(diǎn)比較方便,而求其父節(jié)點(diǎn)就比較麻煩。
孩子表示法結(jié)構(gòu)代碼如下:
#define MAXZ_TREE_SIZE 100 typedef struct CTNode{ int child; struct CTNode *next; }*ChildPtr; typedef struct{ TElemType data; ChildPtr firstchild; }CTBox; typedef struct{ CTBox nodes[MAX_TREE_SIZE]; int r, n; //存放樹的根和結(jié)點(diǎn)數(shù) }CTree;
第三種方式。父親孩子表示法。顧名思義,就是將前兩種方式結(jié)合了。也就是說,一個結(jié)點(diǎn)不止存放數(shù)據(jù),還存放該該節(jié)點(diǎn)的父節(jié)點(diǎn)的下標(biāo),還存放該節(jié)點(diǎn)子節(jié)點(diǎn)的指針,那為什么父節(jié)點(diǎn)可以存放下標(biāo),存放子節(jié)點(diǎn)就只能存放子節(jié)點(diǎn)的指針?因?yàn)?,一個結(jié)點(diǎn)只有一個父節(jié)點(diǎn),卻有多個子節(jié)點(diǎn),或者是沒有子節(jié)點(diǎn),所以沒有辦法確定子節(jié)點(diǎn)的個數(shù),于是,就只能通過鏈?zhǔn)酱鎯α恕?/p>
二叉樹法(孩子兄第表示法)就是將一般樹轉(zhuǎn)化為二叉樹。具體轉(zhuǎn)化方式為:左指針指向它的第一個孩子結(jié)點(diǎn),右指針指向它的第一個兄弟結(jié)點(diǎn)。
二叉樹法結(jié)構(gòu)代碼定義如下:
typedef struct CSNode{ TElemType data; struct CSNode *firstchild, *rightsib; }CSNode, *CSTree;