⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bst.cpp

📁 关于二叉排序树胡数据结构程序课程设计代码
💻 CPP
字号:
 
/***************************相关头文件和预定义*******************************/

 #include<string.h> // 字符串函数头文件
 #include<ctype.h> // 字符函数头文件
 #include<malloc.h> // malloc()等
 #include<limits.h> // INT_MAX等
 #include<stdio.h> // 标准输入输出头文件,包括EOF(=^Z或F6),NULL等
 #include<stdlib.h> // atoi(),exit()
 #include<io.h> // eof()
 #include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等
 #include<sys/timeb.h> // ftime()
 #include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表
 
 #define TRUE 1
 #define FALSE 0
 #define OK 1
 #define ERROR 0

 #define EQ(a,b) ((a)==(b))
 #define LT(a,b) ((a)<(b))
 #define LQ(a,b) ((a)<=(b))
 
 #define InitDSTable InitBiTree       // 构造二叉排序树和平衡二叉树与初始化二叉树的操作同
 #define DestroyDSTable DestroyBiTree // 销毁二叉排序树和平衡二叉树与销毁二叉树的操作同
 #define TraverseDSTable InOrderTraverse
 #define ClearBiTree DestroyBiTree
 typedef int Status; 
 typedef int Boolean; 

  /***************************相关的数据结构定义*******************************/

 typedef int KeyType; // 定义关键字类型为整型
 
 struct ElemType 
 { KeyType key; // 关键字
   int others;
   //char *name;
 };
 
 typedef ElemType TElemType; 

 typedef struct BiTNode
 { TElemType data; // 结点的值
   BiTNode *lchild,*rchild; // 左右孩子指针
 }BiTNode,*BiTree;

 typedef BiTree QElemType;

 typedef struct QNode
 { QElemType data;
   QNode *next;
 }*QueuePtr;

 struct LinkQueue
 { QueuePtr front,rear; // 队头、队尾指针
 };

 /***************************遍历二叉排序树时的函数*******************************/

 void Visit(ElemType c) 
 { printf("(%d,%d)",c.key,c.others);
 }

 /***************************从文本导入二叉排序树结点*****************************/
 
 void InputFromFile(FILE* f,ElemType &c)
 { fscanf(f,"%d%d",&c.key,&c.others);
 }

 /***************************由键盘输入关键字的函数*******************************/
 
 void InputKey(KeyType &k) 
 { scanf("%d",&k);
 }

 /***************************初始化二叉排序树*************************************/

 void InitBiTree(BiTree &T)
 { 
   T=NULL;
 }
 /***************************销毁二叉排序树***************************************/
 void DestroyBiTree(BiTree &T)
 { 
   if(T) // 非空树
   { DestroyBiTree(T->lchild); 
     DestroyBiTree(T->rchild); 
     free(T); 
     T=NULL; 
   }
 }
 /***************************前序遍历二叉排序树***********************************/
 void PreOrderTraverse(BiTree T,void(*Visit)(TElemType))
 { 
   if(T) // T不空
   { Visit(T->data); 
     PreOrderTraverse(T->lchild,Visit); 
     PreOrderTraverse(T->rchild,Visit); 
   }
 }

 /***************************中序遍历二叉排序树***********************************/
 void InOrderTraverse(BiTree T,void(*Visit)(TElemType))
 { 
   if(T)
   { InOrderTraverse(T->lchild,Visit); 
     Visit(T->data); 
     InOrderTraverse(T->rchild,Visit); 
   }
 }

 /***************************后序遍历二叉排序树***********************************/

 void PostOrderTraverse(BiTree T,void(*Visit)(TElemType))
 { 
   if(T) // T不空
   { PostOrderTraverse(T->lchild,Visit); 
     PostOrderTraverse(T->rchild,Visit); 
     Visit(T->data);
   }
 }

/***************************初始化队列********************************************/

void InitQueue(LinkQueue &Q)
 {
   Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode)); // 生成头结点
   if(!Q.front) // 生成头结点失败
     exit(OVERFLOW);
   Q.front->next=NULL; 
 }

 /***************************元素进入队列*****************************************/
   void EnQueue(LinkQueue &Q,QElemType e)
 { 
   QueuePtr p;
   p=(QueuePtr)malloc(sizeof(QNode)); // 动态生成新结点
   if(!p)
     exit(OVERFLOW); // 失败则退出
   p->data=e; 
   p->next=NULL; 
   Q.rear->next=p; 
   Q.rear=p; // 尾指针指向新结点
 }
 
/***************************弹出队头元素并删除掉*********************************/

   Status DeQueue(LinkQueue &Q,QElemType &e)
 {
   QueuePtr p;
   if(Q.front==Q.rear) // 队列空
     return ERROR;
   p=Q.front->next; // p指向队头结点
   e=p->data; // 将队头元素的值赋给e
   Q.front->next=p->next; 
   if(Q.rear==p) // 删除的是队尾结点
     Q.rear=Q.front; // 修改队尾指针指向头结点(空队列)
   free(p); 
   return OK;
 }

/***************************判断队列是否为空*************************************/

  Status QueueEmpty(LinkQueue Q)
 { 
   if(Q.front->next==NULL)
     return TRUE;
   else
     return FALSE;
 }

/***************************层次遍历二叉排序树***********************************/

void LevelOrderTraverse(BiTree T,void(*Visit)(TElemType))
 { 
   LinkQueue q;
   QElemType a;
   if(T) // T不空
   { InitQueue(q); 
     EnQueue(q,T); 
     while(!QueueEmpty(q)) 
     { DeQueue(q,a); 
       Visit(a->data);
       if(a->lchild!=NULL) 
         EnQueue(q,a->lchild);
       if(a->rchild!=NULL) 
         EnQueue(q,a->rchild); 
     }
     printf("\n");
   }
 
 }

/***************************查找二叉排序树的关键字*******************************/


BiTree SearchBST(BiTree T,KeyType key)
 { 
   if(!T||EQ(key,T->data.key)) 
     return T; // 查找结束,返回指针T
   else if LT(key,T->data.key) 
     return SearchBST(T->lchild,key); 
   else 
     return SearchBST(T->rchild,key); 
 }

/***********************查找二叉排序树关键字并确定插入结点指针********************/

Status SearchBST(BiTree &T,KeyType key,BiTree f,BiTree &p) 
 { 
   if(!T) // 查找不成功
   { p=f; // p指向查找路径上访问的最后一个结点
     return FALSE;
   }
   else if EQ(key,T->data.key) // 查找成功
   { p=T; // p指向该数据元素结点
     return TRUE;
   }
   else if LT(key,T->data.key) // key小于T所指结点的关键字
     return SearchBST(T->lchild,key,T,p); // 在左子树中继续递归查找
   else                       // key大于T所指结点的关键字
     return SearchBST(T->rchild,key,T,p); // 在右子树中继续递归查找
 }

/***************************在二叉排序树中插入关键字*******************************/


 Status InsertBST(BiTree &T,ElemType e)
 { 
   BiTree p,s;
   if(!SearchBST(T,e.key,NULL,p)) // 查找不成功,p指向查找路径上访问的最后一个叶子结点
   { s=(BiTree)malloc(sizeof(BiTNode)); // 生成新结点
     s->data=e; 
     s->lchild=s->rchild=NULL; 
     if(!p) // 树T空
       T=s; 
     else if LT(e.key,p->data.key) // 树T不空,*s的关键字小于*p的关键字
       p->lchild=s; 
     else // 树T不空,*s的关键字大于*p的关键字
       p->rchild=s; 
     return TRUE;
   }
   else
     return FALSE; 
 }

/***************************删除树中的某个结点*************************************/

 void Delete(BiTree &p)
 { 
   BiTree s,q=p; 
   if(!p->rchild) 
   { p=p->lchild;
     free(q); 
   }
   else if(!p->lchild) 
   { p=p->rchild; 
     free(q); 
   }
   else 
   { s=p->lchild; 
     while(s->rchild) 
     { q=s; 
       s=s->rchild; 
     } // s向右到尽头(s指向待删结点的前驱结点,q指向s的双亲结点)
     p->data=s->data; 
     if(q!=p) // 情况①,待删结点的左孩子有右子树
       q->rchild=s->lchild; 
     else // 情况②,待删结点的左孩子没有右子树
       q->lchild=s->lchild; 
     free(s); 
   }
 }

/***************************删除二叉排序树中的结点*********************************/

 Status DeleteBST(BiTree &T,KeyType key)
 {
   if(!T) // 树T空
     return FALSE;
   else // 树T不空
   { if EQ(key,T->data.key) // 关键字等于树T根结点的关键字
       Delete(T); 
     else if LT(key,T->data.key) 
       DeleteBST(T->lchild,key); // 在T的左孩子中递归查找
     else 
       DeleteBST(T->rchild,key); // 在T的右孩子中递归查找
     return TRUE;
   }
 }

/************************实现二叉排序树各个操作的主模块****************************/

void main()
 {
   BiTree dt,p;
   int i,n;
   KeyType j,m;
   ElemType r,x;
   Status k;
   char ch;
   FILE *f;
   f=fopen("wenjian.txt","r"); 
   fscanf(f,"%d",&n); 
   InitDSTable(dt); 
   for(i=0;i<n;i++) // 依次在二叉排序树dt中插入n个数据元素
   { InputFromFile(f,r); 
     k=InsertBST(dt,r); // 依次将数据元素r插入二叉排序树dt中
     if(!k) // 插入数据元素r失败
       printf("二叉排序树dt中已存在关键字为%d的数据,故(%d,%d)无法插入到dt中。\n",
       r.key,r.key,r.others); 
	}
   printf("\n") ;
   
   fclose(f); 
   printf("*****                   选择需要执行的操作                 ***********\n"); 
   printf("*****  S—查找关键字(查找成功选择是否删除失败选择是否插入) ***********\n");
   printf("*****                   T—中序遍历二叉排序树              ***********\n");
   printf("*****                   P—前序遍历二叉排序树              ***********\n") ;
   printf("*****                   L—层次遍历二叉排序树              ***********\n") ;
   printf("*****                   B—后序遍历二叉排序树              ***********\n") ;
   printf("*****                   #—退出                            ***********\n") ;
   printf("\n") ;
   printf("\n") ;
   
while( ch=getchar(),ch=='P'||'T'||'S'||'#'||'L'||'B')
   {//printf("*****                   选择需要执行的操作                 ***********\n"); 
	   switch(ch)
	 {  case 'T':
		case 't':
		  { printf("\n中序遍历二叉排序树dt:\n");
			TraverseDSTable(dt,Visit); 
	    	printf("\n");
			printf("\n");	
			break;
		  }	
	    case 'P':
	    case 'p':
		  { printf("\n先序遍历二叉排序树dt:\n");
            PreOrderTraverse(dt,Visit);
			printf("\n");
			printf("\n");	
			break;
		  }
        case 'l':
	    case 'L':
		  { printf("\n层次遍历二叉排序树dt:\n");
            LevelOrderTraverse(dt,Visit);
			printf("\n");
			printf("\n");	
			break;
		  }

        case 'b':
	    case 'B':
		  { printf("\n后序遍历二叉排序树dt:\n");
            PostOrderTraverse(dt,Visit);
			printf("\n");
			printf("\n");
			break;
		  }
	    case 'S':
	    case 's':
		  { printf("\n请输入待查找的关键字的值:");
            printf("\n");
			InputKey(j); // 由键盘输入关键字j,在wenjian.cpp中
			p=SearchBST(dt,j); 
			if(p) // 找到,p指向该结点
			 { 
			   printf("dt中存在关键字为%d的结点!\n",j);
               int sh;
                printf("*****************  选择需要执行的操作   ********\n"); 
                printf("*****************  1—删除该结点%d        ********\n", j);
                printf("*****************  2—不删除该结点%d      ********\n", j);
               printf("\n");
               while(InputKey(m),sh=m)
			  {
				switch(sh)
                 
				{ case 1:
					 { 
						 DeleteBST(dt,j);
					     n--;	 
				         printf("\n中序遍历二叉排序树dt:\n");
				         TraverseDSTable(dt,Visit); // 中序遍历二叉排序树dt
			             printf("\n先序遍历二叉排序树dt:\n");
				         PreOrderTraverse(dt,Visit); // 先序遍历二叉排序树dt
                         printf("\n后序遍历二叉排序树dt:\n");
				         PostOrderTraverse(dt,Visit); // 后序遍历二叉排序树dt
                         printf("\n层次遍历二叉排序树dt:\n");
				         LevelOrderTraverse(dt,Visit); // 层次遍历二叉排序树dt
						 printf("\n");
                         printf("*********         n=%d       **************\n",n);
				        
						 break;
					 }
                
		         case 2:
					 {
						 printf("不删除此结点!\n");
					     break;
					 }
				default:
					printf("输入有误!");
				}//switch
		 break;	   }//while
             
			}//if
	      
			
			else // 未找到,p为空
			{
				printf("dt中不存在关键字为%d的结点。\n",j);	
                printf("*****************  选择需要执行的操作     ********\n"); 
                printf("*****************  1—插入该结点%d        ********\n",j);
                printf("*****************  2—不插入该结点&d      ********\n",j);
			    int mh;
               while(InputKey(m),mh=m)
			   {
					switch(mh)
                 {
		             case 1:
					  {
						x.key=j;
				       	x.others=++n;
					//	x.name="newname";
				        InsertBST(dt, x); 
						 printf("\n中序遍历二叉排序树dt:\n");
				         TraverseDSTable(dt,Visit); // 中序遍历二叉排序树dt
			             printf("\n先序遍历二叉排序树dt:\n");
				         PreOrderTraverse(dt,Visit); // 先序遍历二叉排序树dt
						 printf("\n后序遍历二叉排序树dt:\n");
				         PostOrderTraverse(dt,Visit); // 后序遍历二叉排序树dt
                         printf("\n层次遍历二叉排序树dt:\n");
				         LevelOrderTraverse(dt,Visit); // 层次遍历二叉排序树dt
						 printf("\n");
                         printf("*************           n=%d        ***************\n",n);
				         printf("\n");
						break;
					  }
				     case 2:
						 { 
						  printf("不插入!"); 
						  break;
						 }
                     default :
						 printf("输入有误!");
					
					}//switch

				    printf("\n");
			     	
			break;	}//while
			   
			}//else
			
		                break;
		 }//case
     
		case '#':exit(0);
	
   }//switch
 
  }//while
           DestroyDSTable(dt); // 销毁二叉排序树dt
		   
 }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -