Time Limit: 1 Sec Memory Limit: 4 MB算法
Description數組
計算輸入有序樹的深度和有序樹轉化爲二叉樹以後樹的深度。函數
Inputspa
輸入包含多組數據。每組數據第一行爲一個整數n(2<=n<=30000)表明節點的數量,接下來n-1行,兩個整數a、b表明a是b的父親結點。指針
Outputcode
輸出當前樹的深度和轉化成二叉樹以後的深度。中間件
Sample Inputip
5input
1 5it
1 3
5 2
1 4
Sample Output
3 4
算法一 : 二叉鏈表
用孩子-兄弟表示法表示有序樹和二叉樹,這也就意味着直接用二叉樹的形式表示有序樹,只不過每一個節點的兩個指針不是左右孩子的指針,而是一個指向第一個孩子、另外一個指向下一個兄弟。
有序樹轉二叉樹在遍歷的時候,操做不同。
在形式上有序樹存成了二叉樹的樣子,看的角度不一樣,就是有序樹與二叉樹的區別。
遍歷一個存成二叉樹形式的有序樹的算法:
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系統判斷 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; ///初始化樹 int Init_CSTree(CSTree &t) { t=NULL; //static int maxn = 0; return 0; } //查找數據元素 CSNode *Traverse(CSTree t,int x) { //查找數據元素x是否在二叉樹root中 //查找到則返回該節點指針,未查找到則返回空指針 CSNode *f=NULL; if(t!=NULL) { if(t->data==x) { f=t; } else { f=Traverse(t->firstchild,x);//在左子樹中找 if(f==NULL) { f=Traverse(t->nextsibling,x); } } } return f;//返回查找標誌 } 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相等的 ///節點 有的話 在其firstchild的節點上添加兄弟節點 CSNode *p; p = Traverse(t,a); ///傳值沒問題 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) ///求二叉鏈表中節點個數 { 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++) ///建立樹 { 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); } ///再來一個對firstchild 進行計數的函數 (即 這棵樹有幾層 就是有序樹的深度) ///而後把這個孩子-兄第表示的樹 當作二叉樹 求深度便可 int a,b; a = depth_Tree(T); b = depth_BiTree(T); printf("%d %d\n",a,b); freeTree(T); } return 0; }
算法二 : 結構體數組 結構體數組的指針
以空間換時間,訪問數組而不是遍歷二叉樹。
定義一個結構體,結構體中存有指向第一個孩子的指針和指向下一個兄弟的指針,以及是否存在的標記。
定義一個結構體數組用來存儲這些結構體,而下標就表示輸入的父親孩子節點的數值。
其實若是用指針來指向結構體數組的其餘元素的話,也能夠當作二叉鏈表的形式(如上圖右邊的形式),只不過對其進行操做時是數組形式,更加簡單方便。
#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;///結構體成員指針須要初始化 //lastsibling = NULL; nextsibling=NULL; exist_status=0; } } ArTree; int Create_ArTree(struct ArTree *Ar,int a,int b,int &n)/// 檢測根結點是否發生變化 { 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) 會出現 RunTime Error,報錯結果爲:
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
算法三 : 二叉鏈表存儲、結構體數組訪問
核心:創建二叉鏈表與結構體數組間的聯繫
步驟:
1. 創建結構體和二叉樹,並進行結構體數組和樹的初始化;
2. 輸入第一對節點,創建二叉鏈表,同時對相應的數組元素進行操做,令根結點的firstchild指向其在二叉鏈表中的孩子節點,而lastsibling則指向本身(也就是根結點);
3. 接下來的輸入按照如下步驟:
判斷輸入的a是否在二叉鏈表裏且a是否有孩子,若是沒有的話,利用數組取得其地址,對其地址所在的節點加孩子,而且對相應的數組元素進行操做;
若是有孩子的話,利用數組找到其孩子的最後一個兄弟,在最後一個兄弟後再加一個兄弟,而且對其原來的最後一個兄弟和如今的最後一個兄弟所在的數組元素進行操做;
結構體數組與二叉鏈表之間的關係
#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()///默認構造函數 { firstchild_Ar =NULL;///結構體成員指針須要初始化 lastsibling = NULL; //nextsibling=NULL; exist_status=0; } } ArTree; ///初始化樹 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 是否已經在二叉鏈表裏了 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; }
還有一個現象:
若是靜態變量沒有初始化,但在函數中出現了,codeblocks不會運行。
如上。