1. 程式人生 > >【演算法導論】二叉排序樹

【演算法導論】二叉排序樹


具體程式實現如下:

/**************************************\
函式功能:在二叉排序樹中刪除節點
輸入:    二叉排序樹的根節點、要刪除的節點的內容
輸出:    二叉排序樹的根節點
\**************************************/
bstnode* DelBstNode(bstnode* t,int k)
{
	bstnode *p,*q,*s,*f;
	p=t;
	q=NULL;
	while(p!=NULL)//查詢要刪除的內容為k的節點
	{
		if(p->key==k) break;
		q=p;
		if(p->key<k)
			p=p->rchild;
		else
			p=p->lchild;
	}
	if(p==NULL)
	{
		printf("\n沒有找到該節點\n");
		return t;
	}
    if(p->lchild==NULL)   /* p所指結點的左子樹為空 */
    { 
	   if (q==NULL) 
		   t=p->rchild;       /* p所指結點是原二叉排序樹的根 */
       else if (q->lchild==p)   /* p所指結點是*q的左孩子 */
  		   q->lchild=p->rchild;
	   else  q->rchild=p->rchild;  	/* 將p所指右子樹連結到*q的右指標域上 */
       free(p);                      	   /* 釋放被刪結點 */
  	}	
   else     /* p所指結點有左子樹時,則按圖12.21(e)方法進行 */
    {
		f=p;  s=p->lchild; 
		while(s->rchild!=NULL )   /* 在pL中查詢最右下結點 */
        {
		  f=s; 
		  s=s->rchild;
		}
		if ( f==p ) 
			  f->lchild=s->lchild;    /* 將s所指結點的左子樹連結到*f上*/
		else f->rchild=s->lchild; 
		p->key=s->key;              /* 將s所指結點的值賦給*p */
		
		free(s);   				/* 釋放被刪結點 */
    }
   return  t; 
}    

一個完整例項如下:
#include<stdio.h>
#include<malloc.h>

#define maxsize 20

typedef struct node
{
	int key;
	struct node*lchild,*rchild;
}bstnode;//二叉排序樹的節點結構

bstnode* InsertBst(bstnode* t,bstnode* s);//二叉排序樹的插入
bstnode* CreatBst(int* arrayA,int n);//二叉排序樹的建立
void Layer(bstnode *p);//二叉排序樹的廣度優先遍歷
bstnode* DelBstNode(bstnode* t,int k);//二叉排序樹的刪除

void main()
{
	int arrayA[9]={-1,5,2,4,3,1,6,7,8};//第一個節點沒有用於儲存資料,是為了方便計算
	int n=sizeof(arrayA)/sizeof(int);

	bstnode *head=NULL;//初始化指向連結串列的頭指標
	head=CreatBst(arrayA,n);
	printf("建立的二叉排序樹的廣度優先遍歷為:\n");
    Layer(head);
	printf("\n刪除內容為5後的二叉排序樹的廣度優先遍歷為:");
	head=DelBstNode(head,5);
	printf("\n");
	Layer(head);
}
/**************************************\
函式功能:向二叉排序樹中插入節點
輸入:    二叉排序樹的根節點、要插入的節點
輸出:    二叉排序樹的根節點
\**************************************/
bstnode* InsertBst(bstnode* t,bstnode* s)
{
	bstnode *f,*p;
	p=t;
	while(p!=NULL)
	{
		f=p;
	
		if(s->key<=p->key)
			p=p->lchild;
		else
			p=p->rchild;
	}
	if(t==NULL)
		return s;
	if(s->key<f->key)
		f->lchild=s;
	else
		f->rchild=s;
	return t;

}

/**************************************\
函式功能:建立二叉排序樹
輸入:    原始陣列
輸出:    二叉排序樹的根節點
\**************************************/
bstnode* CreatBst(int* arrayA,int n)
{
	bstnode *t,*s;
	t=NULL;
	for(int i=1;i<n;i++)
	{
		s=(bstnode*)malloc(sizeof(bstnode));
		s->key=arrayA[i];//從arrayA[1]開始
		s->lchild=s->rchild=NULL;
		t=InsertBst(t,s);//呼叫插入函式
	}
	return t;
}

/**************************************\
函式功能:廣度優先遍歷二叉排序樹
輸入:    二叉排序樹的根節點
輸出:    無
\**************************************/
void Layer(bstnode *p)
{
	bstnode* queue[maxsize];//queue陣列用於儲存節點地址
	bstnode* s;
	int rear=0;  //佇列尾指標
	int front=0; //佇列頭指標

	if(p!=NULL)//輸入的樹不為空
	{
		rear=1; //初始化
		front=0;
		queue[rear]=p;
		while(front<rear)//判斷佇列是否為空
		{
			front++;
			s=queue[front];
			printf("%d ",s->key);
			if(s->lchild!=NULL) //儲存左右子節點
			{
				rear++;
				queue[rear]=s->lchild;
			}
			if(s->rchild!=NULL)
			{
				rear++;
				queue[rear]=s->rchild;
			}
		}
	}
}

/**************************************\
函式功能:在二叉排序樹中刪除節點
輸入:    二叉排序樹的根節點、要刪除的節點的內容
輸出:    二叉排序樹的根節點
\**************************************/
bstnode* DelBstNode(bstnode* t,int k)
{
	bstnode *p,*q,*s,*f;
	p=t;
	q=NULL;
	while(p!=NULL)//查詢要刪除的內容為k的節點
	{
		if(p->key==k) break;
		q=p;
		if(p->key<k)
			p=p->rchild;
		else
			p=p->lchild;
	}
	if(p==NULL)
	{
		printf("\n沒有找到該節點\n");
		return t;
	}
    if(p->lchild==NULL)   /* p所指結點的左子樹為空 */
    { 
	   if (q==NULL) 
		   t=p->rchild;       /* p所指結點是原二叉排序樹的根 */
       else if (q->lchild==p)   /* p所指結點是*q的左孩子 */
  		   q->lchild=p->rchild;
	   else  q->rchild=p->rchild;  	/* 將p所指右子樹連結到*q的右指標域上 */
       free(p);                      	   /* 釋放被刪結點 */
  	}	
   else     /* p所指結點有左子樹時,則按圖12.21(e)方法進行 */
    {
		f=p;  s=p->lchild; 
		while(s->rchild!=NULL )   /* 在pL中查詢最右下結點 */
        {
		  f=s; 
		  s=s->rchild;
		}
		if ( f==p ) 
			  f->lchild=s->lchild;    /* 將s所指結點的左子樹連結到*f上*/
		else f->rchild=s->lchild; 
		p->key=s->key;              /* 將s所指結點的值賦給*p */
		
		free(s);   				/* 釋放被刪結點 */
    }
   return  t; 
}    
參考文獻:《計算機軟體技術基礎》 劉彥明 榮政 編 、《 演算法導論》

注:如果程式出錯,可能是使用的開發平臺版本不同,請點選如下連結: 解釋說明