【劍指offer】從上向下列印二叉樹

蘭亭風雨發表於2014-05-18

轉載請註明出處:http://blog.csdn.net/ns_code/article/details/26089165


    劍指offer上的第23題,實際上就是考察二叉樹的層序遍歷,具體思想可以參考這裡

題目描述:

從上往下列印出二叉樹的每個節點,同層節點從左至右列印。

輸入:

輸入可能包含多個測試樣例,輸入以EOF結束。
對於每個測試案例,輸入的第一行一個整數n(1<=n<=1000, :n代表將要輸入的二叉樹元素的個數(節點從1開始編號)。接下來一行有n個數字,代表第i個二叉樹節點的元素的值。接下來有n行,每行有一個字母Ci。
Ci=’d’表示第i個節點有兩子孩子,緊接著是左孩子編號和右孩子編號。
Ci=’l’表示第i個節點有一個左孩子,緊接著是左孩子的編號。
Ci=’r’表示第i個節點有一個右孩子,緊接著是右孩子的編號。
Ci=’z’表示第i個節點沒有子孩子。

輸出:

對應每個測試案例,
按照從上之下,從左至右列印出二叉樹節點的值。

樣例輸入:
7
8 6 5 7 10 9 11
d 2 5
d 3 4
z
z
d 6 7
z
z
樣例輸出:
8 6 10 5 7 9 11
    AC程式碼:

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

/*
二叉樹的儲存結構
*/
typedef struct BTNode
{
	int data;
	int rchild;
	int lchild;
}BTNode;

/*
佇列的儲存結構
*/
typedef struct Node
{
	BTNode data;
	struct Node *pNext;
}NODE,*PNODE;

typedef struct Queue
{
	PNODE front;  //隊頭指標
	PNODE rear;   //隊尾指標
}QUEUE,*PQUEUE;


/*
建立一個空佇列,隊頭指標和隊尾指標都指向頭結點,
頭結點中不存放資料,只存放指標
*/
PQUEUE create_queue()
{
	PQUEUE pS = (PQUEUE)malloc(sizeof(QUEUE));
	pS->front = (PNODE)malloc(sizeof(NODE));
	if(!pS || !pS->front)
	{
		printf("pS or front malloc failed!!");
		exit(-1);
	}
	else
	{
		pS->rear = pS->front;
		pS->front->pNext = NULL;
	}
	return pS;
}

/*
判斷佇列是否為空
*/
bool is_empty(PQUEUE pS)
{
	if(pS->front == pS->rear)
		return true;
	else
		return false;
}

/*
進隊函式,從隊尾進隊,隊頭指標保持不變
*/
void en_queue(PQUEUE pS, BTNode e)
{
	PNODE pNew = (PNODE)malloc(sizeof(NODE));
	if(!pNew)
	{
		printf("pNew malloc failed");
		exit(-1);
	}
	else
	{
		pNew->data = e;
		pNew->pNext = NULL;
		pS->rear->pNext = pNew;
		pS->rear = pNew;
	}
	return;
}

/*
出隊函式,從隊頭出隊,隊尾指標保持不變,但當最後一個元素出隊時,
需要對隊尾指標重新賦值,使其指向頭結點
*/
bool de_queue(PQUEUE pS,BTNode *pData)
{
	if(is_empty(pS))
		return false;
	else
	{
		PNODE p = pS->front->pNext;
		*pData = p->data;
		pS->front->pNext = p->pNext;

		//這裡是佇列頭元素出隊的特殊情況,一般情況下,刪除隊頭元素時
		//僅需修改頭結點中的指標,但當佇列中最後一個元素被刪除時,
		//佇列尾指標也丟失了,因此需對隊尾指標重新賦值(指向頭結點)。
		if(pS->rear == p)         
			pS->rear = pS->front;
		free(p);
	}
	return true;
}

/*
銷燬佇列,頭結點也被銷燬,最後也將pS節點銷燬,並將其指向為空,避免垂直指標的產生
*/
void destroy_queue(PQUEUE pS)
{
	if(is_empty(pS))
		return;
	else
	{
		while(pS->front)
		{
			pS->rear = pS->front->pNext;
			free(pS->front);
			pS->front = pS->rear;
		}
	}
	free(pS);
	pS = 0;
	return;
}

/*
層序遍歷二叉樹
*/
void LevelTraverse(BTNode *pTree,int index,int *LevTraverse,int n)
{
	if(pTree == NULL)
		return;
	if(index == -1)
		return;

	BTNode pBTNode;
	PQUEUE pS = create_queue();
	en_queue(pS, pTree[0]);
	int i = 0;
	while(!is_empty(pS) && i<n)
	{
		de_queue(pS,&pBTNode);
		//同樣,先把元素按層序遍歷的順序儲存起來
		LevTraverse[i++] = pBTNode.data;
		if(pBTNode.lchild != -1)
			en_queue(pS, pTree[pBTNode.lchild]);
		if(pBTNode.rchild != -1)
			en_queue(pS, pTree[pBTNode.rchild]);
	}

	destroy_queue(pS);
}


int main()
{
	int n;
	while(scanf("%d",&n) != EOF)
	{
		//輸入樹pTree各節點的值
		BTNode *pTree = NULL;
		if(n>0)
		{
			pTree = (BTNode *)malloc(n*sizeof(BTNode));
			if(pTree == NULL)
				exit(EXIT_FAILURE);
			int i,data;
			//輸入n個節點的data
			for(i=0;i<n;i++)
			{
				scanf("%d",&data);
				pTree[i].data = data;
				pTree[i].rchild = -1;
				pTree[i].lchild = -1;
			}

			//輸入n行節點連線關係
			for(i=0;i<n;i++)
			{
				char ci;
				//這兩行的作用是為了跳過緩衝區中的換行符
				//這裡不能用fflush(stdin),gcc不支援,這只是一些編譯器自加的,
				//如果用了,測試系統會報RE。
				while(getchar() != '\n')
					continue;
				scanf("%c",&ci);
				if(ci == 'z')
					continue;
				else if(ci == 'l')
				{
					int lindex;
					scanf("%d",&lindex);
					pTree[i].lchild = lindex-1;
				}
				else if(ci == 'r')
				{
					int rindex;
					scanf("%d",&rindex);
					pTree[i].rchild = rindex-1;
				}
				else if(ci == 'd')
				{
					int lindex,rindex;
					scanf("%d",&lindex);
					scanf("%d",&rindex);
					pTree[i].lchild = lindex-1;
					pTree[i].rchild = rindex-1;
				}
			}
		}
		
		
		//先將遍歷的元素依次儲存到preTraverse陣列中
		int *LevTraverse = (int *)malloc(n*sizeof(int));
		if(LevTraverse == NULL)
			exit(EXIT_FAILURE);
		LevelTraverse(pTree,0,LevTraverse,n);
		int i;
		for(i=0;i<n;i++)
		{
			//使輸出符合測試系統要求的格式
			if(i == n-1)
				printf("%d\n",LevTraverse[i]);
			else
				printf("%d ",LevTraverse[i]);	
		}

		free(LevTraverse);
		LevTraverse = NULL;

		free(pTree);
		pTree = NULL;
	}
	return 0;
}

/**************************************************************
    Problem: 1523
    User: mmc_maodun
    Language: C
    Result: Accepted
    Time:0 ms
    Memory:916 kb
****************************************************************/

相關文章