博弈樹的建立以及節點刪除出現的錯誤
描述
對于一間公司來說,它成立之時所做的第一件事恐怕就是任命CEO了。之后,CEO就會開始雇用員工,也會有員工離職去別的公司。假設公司中的每一個員工(包括 CEO在內)都可以直接雇用新的員工,而公司中的所有員工(包括CEO)也都可能會跳槽離開,則某公司在成立一段時間之后的的組織結構如圖1
VonNeumann是公司的CEO,他直接雇用了兩個人,分別是Tanenbaum和Dijkstra。在公司中,某員工的幾個直接下屬,他們的職位是由員工們的工齡決定的,在圖中即表現為從從左至右職位越來越低,譬如Tanenbaum的職位就比Dijkstra要高。
當一個員工雇用了新的下屬時,該下屬在該員工雇傭的所有下屬中,職位是最低的。假設VonNeumann又雇用了Shannon,則VonNeumann的三名下屬職位從高到低分別是Tanenbaum、Dijkstra和Shannon。
當公司中的員工離職,則有兩種情況。若他沒有雇用任何下屬,則他會被從公司的組織結構中拿掉。若他有直接的下屬,則他的直接下屬中職位較高的人,會升職并補上缺位。而該下屬若也有下屬,則他的下屬中職位最高的,會補上他升值后空出的位子。以此類推,直到某個尚未雇用下屬的員工升職。
假設圖1中的Tanenbaum跳槽離開了,則Stallings會補上它的位置,而Knuth會補上Stallings的位置。圖2圖3分別展示了基于圖1的兩種的操作的結果。圖2: VonNeumann雇用了Shannon。圖3: Tanenbaum跳槽。
輸入
輸入的第一行是 CEO 的姓名。題目中所有的人名的長度都在2-20之間,且由大小寫字母、數字和短線(減號)組成。每個名字都包含至少一個大寫和一個小寫字母。
在第一行后會有很多行內容,他們由如下的規則構成:
- [老員工] hires [新員工]
- fire [老員工]
- print
[老員工] 是已經在公司工作的人的名字,而[新員工]是即將被雇用的員工的名字。以上三種規則組成的內容可能會按照任何順序出現。但公司中會至少有一名員工(CEO),且公司的規模最大不會超過 1000 人。
輸出
對于每一個打印命令,按照如下規則輸出當前公司的結構信息:
- 每一行包含一個人名
- 第一行是CEO的名字,從第一列開始
- 對于圖4形式的樹

學長代碼鏈接:1. 點擊打開鏈接
2. 點擊打開鏈接
這個題我花了很長時間,其實錯誤對我而言確實是不明顯:
我的正確代碼如下:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
void print(NODE *ptr,int dep)
-
-
-
-
-
-
printf("%s\n",ptr->name);
-
-
-
-
-
-
-
-
void Build(NODE **ptr,char *s)
-
-
-
-
(*ptr)=(NODE*)malloc(sizeof(NODE));
-
-
-
-
-
int Hire(NODE **ptr,char *p,char *q)
-
-
-
if(strcmp(p,(*ptr)->name)==0)
-
-
-
-
(*ptr)->left=(NODE*)malloc(sizeof(NODE));
-
-
(*ptr)->left->right=NULL;
-
strcpy((*ptr)->left->name,q);
-
-
-
-
Build(&((*ptr)->left),q);
-
-
-
-
-
-
-
Hire(&((*ptr)->left),p,q);
-
-
-
Hire(&((*ptr)->right),p,q);
-
-
-
-
-
void Search(NODE **ptr, char *s)
-
-
-
if((*ptr)->left!=NULL&&strcmp((*ptr)->left->name,s)==0)
-
-
-
-
-
-
if((*ptr)->right!=NULL&&strcmp((*ptr)->right->name,s)==0)
-
-
-
-
-
-
-
Search(&((*ptr)->left),s);
-
-
Search(&((*ptr)->right),s);
-
-
-
-
-
-
-
-
if(strcmp(s,CEO->name)==0 && CEO->left!=NULL)
-
-
-
-
strcpy(CEO->name,CEO->left->name);
-
strcpy(CEO->left->name,str);
-
-
else if(strcmp(s,CEO->name)==0 && CEO->right!=NULL)
-
-
-
-
strcpy(CEO->name,CEO->right->name);
-
strcpy(CEO->right->name,str);
-
-
-
Father=NULL; Delete=NULL;
-
-
-
-
-
-
-
-
if((*Father)->left== *Delete)
-
-
if((*Delete)->left==NULL)
-
-
(*Father)->left=(*Delete)->right;
-
-
-
-
-
-
strcpy(str,(*Delete)->name);
-
strcpy((*Delete)->name,(*Delete)->left->name);
-
strcpy((*Delete)->left->name,str);
-
-
-
-
else if((*Father)->right== *Delete)
-
-
if((*Delete)->left==NULL)
-
-
(*Father)->right=(*Delete)->right;
-
-
-
-
else if((*Delete)->right==NULL)
-
-
(*Father)->right=(*Delete)->left;
-
-
-
-
-
-
strcpy(str,(*Delete)->name);
-
strcpy((*Delete)->name,(*Delete)->left->name);
-
strcpy((*Delete)->left->name,str);
-
-
-
-
-
-
-
-
-
-
CEO=(NODE*)malloc(sizeof(NODE));
-
-
-
-
char inputs[100],prase1[20],prase2[20],prase3[20];
-
-
while(gets(inputs)!=NULL)
-
-
input=sscanf(inputs,"%[^ ] %[^ ] %[^ ]",prase1,prase2,prase3);
-
-
-
-
printf("------------------------------------------------------------\n");
-
-
-
-
-
Hire(&CEO,prase1,prase3);
-
-
-
錯誤的地方是Fire函數,錯誤代碼如下:
-
-
-
if(strcmp(s,CEO->name)==0 && CEO->left!=NULL)
-
-
-
-
strcpy(CEO->name,CEO->left->name);
-
strcpy(CEO->left->name,str);
-
-
else if(strcmp(s,CEO->name)==0 && CEO->right!=NULL)
-
-
-
-
strcpy(CEO->name,CEO->right->name);
-
strcpy(CEO->right->name,str);
-
-
-
Father=NULL; Delete=NULL;
-
-
-
-
-
-
-
-
if((*Father)->left== *Delete)
-
-
if((*Delete)->left==NULL)
-
-
(*Father)->left=(*Delete)->right;
-
-
-
-
-
-
strcpy(str,(*Delete)->name);
-
strcpy((*Delete)->name,(*Delete)->left->name);
-
strcpy((*Delete)->left->name,str);
-
-
-
-
if((*Father)->right== *Delete)
-
-
if((*Delete)->left==NULL)
-
-
(*Father)->right=(*Delete)->right;
-
-
-
-
else if((*Delete)->right==NULL)
-
-
(*Father)->right=(*Delete)->left;
-
-
-
-
-
-
strcpy(str,(*Delete)->name);
-
strcpy((*Delete)->name,(*Delete)->left->name);
-
strcpy((*Delete)->left->name,str);
-
-
-
-
-
錯誤之處在于程序進入*1*處的 if語句塊中,將節點已經刪除,但是程序依舊進行 *2* 處條件判斷,但此時Delete指針所指的區域已經被刪除,所以程序會提示內存訪問沖突。
這件事提示我如果已經刪除了一個節點,就不能再對它進行判斷或者操作,否則會有內存訪問沖突的錯誤。