Time Limit: 1 Sec Memory Limit: 4 MB
Description
計(jì)算輸入有序樹(shù)的深度和有序樹(shù)轉(zhuǎn)化為二叉樹(shù)之后樹(shù)的深度。
Input
輸入包含多組數(shù)據(jù)吝岭。每組數(shù)據(jù)第一行為一個(gè)整數(shù)n(2<=n<=30000)代表節(jié)點(diǎn)的數(shù)量裸扶,接下來(lái)n-1行瓣戚,兩個(gè)整數(shù)a、b代表a是b的父親結(jié)點(diǎn)嘿期。
Output
輸出當(dāng)前樹(shù)的深度和轉(zhuǎn)化成二叉樹(shù)之后的深度芒澜。
Sample Input
5
1 5
1 3
5 2
1 4
Sample Output
3 4
算法一 : 二叉鏈表
用孩子-兄弟表示法表示有序樹(shù)和二叉樹(shù),這也就意味著直接用二叉樹(shù)的形式表示有序樹(shù)卧须,只不過(guò)每個(gè)節(jié)點(diǎn)的兩個(gè)指針不是左右孩子的指針,而是一個(gè)指向第一個(gè)孩子儒陨、另一個(gè)指向下一個(gè)兄弟花嘶。
有序樹(shù)轉(zhuǎn)二叉樹(shù)在遍歷的時(shí)候,操作不一樣蹦漠。
在形式上有序樹(shù)存成了二叉樹(shù)的樣子椭员,看的角度不同,就是有序樹(shù)與二叉樹(shù)的區(qū)別笛园。
遍歷一個(gè)存成二叉樹(shù)形式的有序樹(shù)的算法:
int depth_Tree(CSTree t)
{
if(t==NULL)
return 0;
int firstchild_depth = depth_Tree(t->firstchild);
int nextsibling_depth = depth_Tree(t->nextsibling);
return (firstchild_depth+1 > nextsibling_depth ? firstchild_depth+1 : nextsibling_depth);
}
完整程序: (OJ系統(tǒng)判斷 TimeLimit Exceed)
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
typedef int ElemType;
typedef int Status;
///孩子-兄弟表示法
typedef struct CSNode
{
ElemType data;
struct CSNode *firstchild,*nextsibling;
} CSNode,*CSTree;
///初始化樹(shù)
int Init_CSTree(CSTree &t)
{
t=NULL;
//static int maxn = 0;
return 0;
}
//查找數(shù)據(jù)元素
CSNode *Traverse(CSTree t,int x)
{
//查找數(shù)據(jù)元素x是否在二叉樹(shù)root中
//查找到則返回該節(jié)點(diǎn)指針隘击,未查找到則返回空指針
CSNode *f=NULL;
if(t!=NULL)
{
if(t->data==x)
{
f=t;
}
else
{
f=Traverse(t->firstchild,x);//在左子樹(shù)中找
if(f==NULL)
{
f=Traverse(t->nextsibling,x);
}
}
}
return f;//返回查找標(biāo)志
}
int Create_CSTree(CSTree &t,int a,int b)
{
if(t==NULL)
{
///t = (CSNode*)malloc(sizeof(CSNode));
t=new CSNode;
t->data = a;
t->firstchild = new CSNode;
t->nextsibling=NULL;
t->firstchild->data = b;
t->firstchild->firstchild=NULL;
t->firstchild->nextsibling=NULL;
}
else
{
/// 查找 新輸入的 a 是否在已存在的二叉鏈表中也有與a相等的
///節(jié)點(diǎn) 有的話 在其firstchild的節(jié)點(diǎn)上添加兄弟節(jié)點(diǎn)
CSNode *p;
p = Traverse(t,a); ///傳值沒(méi)問(wèn)題
if(p==NULL)
{
return -1;
//printf("input wrong!\n");
}
if(p->firstchild != NULL)
{
CSNode *q;
q = p->firstchild;
for(int i = 0; ; i++)
{
if(q->nextsibling==NULL)
{
break;
}
else
{
q = q->nextsibling;
}
}
q->nextsibling = new CSNode;
q->nextsibling->data = b;
q->nextsibling->firstchild=NULL;
q->nextsibling->nextsibling=NULL;
}
else
{
p->firstchild = new CSNode;
p->firstchild->data = b;
p->firstchild->firstchild = NULL;
p->firstchild->nextsibling = NULL;
}
}
return 0;
}
int Judge(CSTree t) ///求二叉鏈表中節(jié)點(diǎn)個(gè)數(shù)
{
if(t==NULL)
return 0;
int firstchild_num = Judge(t->firstchild);
int nextsubling_num = Judge(t->nextsibling);
int ret = firstchild_num + nextsubling_num +1;
return ret;
}
int depth_Tree(CSTree t)
{
if(t==NULL)
return 0;
int firstchild_depth = depth_Tree(t->firstchild);
int nextsibling_depth = depth_Tree(t->nextsibling);
return (firstchild_depth+1 > nextsibling_depth ? firstchild_depth+1 : nextsibling_depth);
}
int depth_BiTree(CSTree t)
{
if(t==NULL)
return 0;
int firstBiTree_depth = depth_BiTree(t->firstchild);
int siblingBiTree_depth = depth_BiTree(t->nextsibling);
if(firstBiTree_depth>siblingBiTree_depth)
return firstBiTree_depth+1;
else
return siblingBiTree_depth+1;
}
void freeTree(CSTree &root)
{
maxn = 0;
if (root!=NULL)
{
if (root->firstchild)
{
freeTree(root->firstchild);
root->firstchild= NULL;
}
if (root->nextsibling)
{
freeTree(root->nextsibling);
root->nextsibling = NULL;
}
if (root!=NULL)
{
free(root);
root=NULL;
}
}
//return 0;
}
int main()
{
int n,flag = 1;
while(scanf("%d",&n)!=EOF)
{
CSTree T;
Init_CSTree(T);
int c[2][n-1];
for(int op =0; op<n-1 ; op++) ///創(chuàng)建樹(shù)
{
int x,y;
scanf("%d %d",&c[0][op],&c[1][op]);
//Create_CSTree(T,x,y);
}
for(int w=0; w<n-1; w++)
{
int wr = c[0][w];
int wt = c[1][w];
Create_CSTree(T,wr,wt);
}
///再來(lái)一個(gè)對(duì)firstchild 進(jìn)行計(jì)數(shù)的函數(shù) (即 這棵樹(shù)有幾層 就是有序樹(shù)的深度)
///然后把這個(gè)孩子-兄第表示的樹(shù) 看成二叉樹(shù) 求深度即可
int a,b;
a = depth_Tree(T);
b = depth_BiTree(T);
printf("%d %d\n",a,b);
freeTree(T);
}
return 0;
}
算法二 : 結(jié)構(gòu)體數(shù)組 結(jié)構(gòu)體數(shù)組的指針
以空間換時(shí)間,訪問(wèn)數(shù)組而不是遍歷二叉樹(shù)研铆。
定義一個(gè)結(jié)構(gòu)體埋同,結(jié)構(gòu)體中存有指向第一個(gè)孩子的指針和指向下一個(gè)兄弟的指針,以及是否存在的標(biāo)記棵红。
定義一個(gè)結(jié)構(gòu)體數(shù)組用來(lái)存儲(chǔ)這些結(jié)構(gòu)體凶赁,而下標(biāo)就表示輸入的父親孩子節(jié)點(diǎn)的數(shù)值。
其實(shí)如果用指針來(lái)指向結(jié)構(gòu)體數(shù)組的其他元素的話逆甜,也可以看成二叉鏈表的形式(如上圖右邊的形式)虱肄,只不過(guò)對(duì)其進(jìn)行操作時(shí)是數(shù)組形式,更加簡(jiǎn)單方便交煞。
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct ArTree
{
struct ArTree *firstchild;//,*lastsibling;
struct ArTree *nextsibling;
int exist_status;
ArTree()///mo ren gou zao han shu
{
firstchild =NULL;///結(jié)構(gòu)體成員指針需要初始化
//lastsibling = NULL;
nextsibling=NULL;
exist_status=0;
}
} ArTree;
int Create_ArTree(struct ArTree *Ar,int a,int b,int &n)/// 檢測(cè)根結(jié)點(diǎn)是否發(fā)生變化
{
if((Ar+a)->exist_status == 1 && (Ar+a)->firstchild==NULL)
{
(Ar+a)->firstchild = (Ar+b);
(Ar+b)->exist_status = 1;
}
else if((Ar+a)->exist_status == 1 && (Ar+a)->firstchild!=NULL)
{
ArTree *qq=NULL;
qq = (Ar+a)->firstchild;
while((qq->nextsibling)!=NULL)
{
qq = qq->nextsibling;
}
qq->nextsibling = (Ar+b);
(Ar+b)->exist_status = 1;
///free(qq);
}
else if((Ar+b)->exist_status == 1)
{
(Ar+a)->firstchild = (Ar+b);
(Ar+a)->exist_status = 1;
n = a;
Ar = Ar+a;
}
}
///求深度
int depth_ArTree_Order(ArTree *Ar)
{
if(Ar==NULL)
return 0;
int firstchild_depth = depth_ArTree_Order(Ar->firstchild);
int nextsibling_depth = depth_ArTree_Order(Ar->nextsibling);
return (firstchild_depth+1 > nextsibling_depth ? firstchild_depth+1 : nextsibling_depth);
}
int depth_ArTree(ArTree *Ar)
{
if(Ar==NULL)
return 0;
int fir = depth_ArTree(Ar->firstchild);
int nex = depth_ArTree(Ar->nextsibling);
if(fir>nex)
return fir+1;
else
return nex+1;
}
int main()
{
int input_num;
while(scanf("%d",&input_num)!=EOF)
{
struct ArTree Ar[30010],*p;//,*pro;
p = Ar;
int flag = 0;
int n = 1;
for(int i = 0; i<input_num-1; i++)
{
int a,b;
scanf("%d %d",&a,&b);
if(flag==0)
{
(p+a)->firstchild = p+b;
n=a;
(p+a)->exist_status = 1;
(p+b)->exist_status = 1;
flag=1;
//printf("p+a = %p (p+a)->firstchild = %p p+b = %p\n",p+a,(p+a)->firstchild ,p+b);
}
else if(flag!=0)
{
Create_ArTree(p,a,b,n);
}
}
printf("%d %d\n",depth_ArTree_Order(p+n),depth_ArTree(p+n));
}
}
算法二如果使用 free(q) 會(huì)出現(xiàn) RunTime Error,報(bào)錯(cuò)結(jié)果為:
Runtime Error:[ERROR] A Not allowed system call: runid:1508674
callid:146 *** glibc detected *** ./Main: free(): invalid pointer:
0xbfaaa550 *** Runtime Error:[ERROR] A Not allowed system call:
runid:1508674 callid:146 *** glibc detected *** ./Main: free():
invalid pointer: 0xbf9d4514 ***
算法三 : 二叉鏈表存儲(chǔ)咏窿、結(jié)構(gòu)體數(shù)組訪問(wèn)
核心:建立二叉鏈表與結(jié)構(gòu)體數(shù)組間的聯(lián)系
步驟:
1. 建立結(jié)構(gòu)體和二叉樹(shù),并進(jìn)行結(jié)構(gòu)體數(shù)組和樹(shù)的初始化素征;
2. 輸入第一對(duì)節(jié)點(diǎn)集嵌,建立二叉鏈表,同時(shí)對(duì)相應(yīng)的數(shù)組元素進(jìn)行操作稚茅,令根結(jié)點(diǎn)的firstchild指向其在二叉鏈表中的孩子節(jié)點(diǎn)纸淮,而lastsibling則指向自己(也就是根結(jié)點(diǎn));
3. 接下來(lái)的輸入按照以下步驟:
判斷輸入的a是否在二叉鏈表里且a是否有孩子亚享,如果沒(méi)有的話咽块,利用數(shù)組取得其地址,對(duì)其地址所在的節(jié)點(diǎn)加孩子欺税,并且對(duì)相應(yīng)的數(shù)組元素進(jìn)行操作侈沪;
如果有孩子的話揭璃,利用數(shù)組找到其孩子的最后一個(gè)兄弟,在最后一個(gè)兄弟后再加一個(gè)兄弟亭罪,并且對(duì)其原來(lái)的最后一個(gè)兄弟和現(xiàn)在的最后一個(gè)兄弟所在的數(shù)組元素進(jìn)行操作瘦馍;
結(jié)構(gòu)體數(shù)組與二叉鏈表之間的關(guān)系
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
typedef int ElemType;
typedef int Status;
///孩子-兄弟表示法
typedef struct CSNode
{
ElemType data;
struct CSNode *firstchild,*nextsibling;
} CSNode,*CSTree;
///中間件
typedef struct ArTree
{
CSNode *firstchild_Ar,*lastsibling;
//struct ArTree *nextsibling;
int exist_status;
ArTree()///默認(rèn)構(gòu)造函數(shù)
{
firstchild_Ar =NULL;///結(jié)構(gòu)體成員指針需要初始化
lastsibling = NULL;
//nextsibling=NULL;
exist_status=0;
}
} ArTree;
///初始化樹(shù)
int Init_CSTree(CSTree &t)
{
t=NULL;
//static int maxn = 0;
return 0;
}
int Create_ArTree_BiTree(CSTree &T,struct ArTree *Ar,int a,int b)
{
if(T==NULL)
{
///create artree
T = new CSNode;
T->data = a;
T->nextsibling=NULL;
T->firstchild = new CSNode;
T->firstchild->data =b;
T->firstchild->firstchild = NULL;
T->firstchild->nextsibling=NULL;
///中間件
(Ar+a)->firstchild_Ar = T->firstchild;
//n=a;
(Ar+a)->lastsibling=T;
(Ar+b)->lastsibling = T->firstchild;
(Ar+a)->exist_status = 1;
(Ar+b)->exist_status = 1;
}
else
{
///判斷輸入的a 是否已經(jīng)在二叉鏈表里了
if((Ar+a)->exist_status==1 && (Ar+a)->firstchild_Ar == NULL)
{
if((Ar+a)->lastsibling->data == a)
{
CSNode *lq;
lq= (Ar+a)->lastsibling;///zi shen
lq->firstchild= new CSNode;
lq->firstchild->data = b;
lq->firstchild->firstchild=NULL;
lq->firstchild->nextsibling=NULL;
(Ar+a)->firstchild_Ar=lq->firstchild;
(Ar+b)->lastsibling=lq->firstchild;
(Ar+b)->exist_status =1;
}
else if((Ar+a)->lastsibling->data != a)
{
CSNode *haha;
haha = (Ar+a)->lastsibling;
int y;
y = haha->data;
(Ar+y)->lastsibling->firstchild=new CSNode;
(Ar+y)->lastsibling->firstchild->data=b;
(Ar+y)->lastsibling->firstchild->firstchild=NULL;
(Ar+y)->lastsibling->firstchild->nextsibling=NULL;
(Ar+a)->firstchild_Ar=(Ar+y)->lastsibling->firstchild;
(Ar+b)->lastsibling=(Ar+y)->lastsibling->firstchild;
(Ar+b)->exist_status=1;
}
}
else if((Ar+a)->exist_status ==1 && (Ar+a)->firstchild_Ar != NULL)
{
//CSNode *lq;
int n;
n = (Ar+a)->firstchild_Ar->data;
if((Ar+n)->lastsibling == (Ar+a)->firstchild_Ar)
{
CSNode *qll;
qll=new CSNode;
qll->data=b;
qll->firstchild=NULL;
qll->nextsibling=NULL;
(Ar+n)->lastsibling->nextsibling=qll;
(Ar+n)->lastsibling=qll;
(Ar+b)->lastsibling= (Ar+a)->firstchild_Ar;///指回去
(Ar+b)->exist_status=1;
}
else
{
CSNode *qll;
qll = (Ar+n)->lastsibling;
qll->nextsibling=new CSNode;
qll->nextsibling->data=b;
qll->nextsibling->firstchild=NULL;
qll->nextsibling->nextsibling=NULL;
(Ar+n)->lastsibling=qll->nextsibling;
int m;
m=qll->data;
(Ar+m)->lastsibling=qll;
(Ar+b)->lastsibling=(Ar+a)->firstchild_Ar;
(Ar+b)->exist_status=1;
}
}
}
return 0;
}
///求深度
void freeTree(CSTree &root)
{
if (root!=NULL)
{
if (root->firstchild)
{
freeTree(root->firstchild);
root->firstchild= NULL;
}
if (root->nextsibling)
{
freeTree(root->nextsibling);
root->nextsibling = NULL;
}
if (root!=NULL)
{
free(root);
root=NULL;
}
}
}
void InOrder(CSTree T)
{
if(T)
{
InOrder(T->firstchild);
printf("%d ",T->data);
InOrder(T->nextsibling);
}
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
///first create bitree
CSTree T;
Init_CSTree(T);
struct ArTree Ar[31000];//,*p;
//p=Ar;
///input data
for(int i =0; i<n-1; i++)
{
int a,b;
scanf("%d %d",&a,&b);
Create_ArTree_BiTree(T,Ar,a,b);
//InOrder(T);
//printf("\n");
}
printf("%d %d\n",depth_Tree(T),depth_BiTree(T));
//freeTree(T);
}
return 0;
}
還有一個(gè)現(xiàn)象:
如果靜態(tài)變量沒(méi)有初始化,但在函數(shù)中出現(xiàn)了应役,codeblocks不會(huì)運(yùn)行情组。
如上。