数据结构-二叉排序树

二叉排序树(BinarySortTree):

具有下列性质的二叉树:

(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;

(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;

(3)左、右子树也分别为二叉排序树;

#include<iostream>
#include<stdio.h>
using namespace std;

typedef struct node        	//记录类型
{	
  int key;            	//关键字项
  struct node *lchild,*rchild;	//左右孩子指针
} BSTNode,*BSTree;

void InsertBST(BSTree *t,int k)
{
 BSTNode *f,*p=*t;
 while(p)
 {
     if(p->key==k) return;//去掉重复的元素
     f=p;
     p=(k<p->key)?p->lchild:p->rchild;
 }
 p=(BSTree)malloc(sizeof(BSTNode));
 p->key=k;
 p->lchild=p->rchild=NULL;
 if(*t==NULL) *t=p;
 else if (k<f->key) f->lchild=p;
      else f->rchild=p;
}

BSTree SearchBST(BSTree t, int k)
{ 
  BSTree p;
  p=t;
  while((p!=NULL)&&(p->key!=k))
      if(k<p->key)  p=p->lchild;
      else  p=p->rchild;
   return(p);
}

BSTree InsertBST2(BSTree t,int k)//插入关键字k,非递归
{
	//若二叉排序树 t 中没有关键字k,则插入,否则直接返回
	
	BSTree p=t;//p的初值指向根结点
	BSTree f;//f保存当前查找的结点
	while(p)//查找插入位置,插入位置一定是一个叶子结点
	{
		if(p->key==k)//树中已有k,无需插入
		{
			cout<<"树中存在"<<k<<",插入失败"<<endl;
			return t;
		}
		f=p;
       //若k<p->key,在左子树上查找,否则在右子树上查找
		p=(k<p->key)?p->lchild:p->rchild;
	}
	p=(BSTree)malloc(sizeof(BSTNode));
	p->key=k;
	p->lchild=p->rchild=NULL;
	if(t==NULL)t=p;//插入结点为新的根结点
	else if(k<f->key)f->lchild = p;//插入结点为左孩子
	else f->rchild = p;//插入结点为右孩子
	return t;
}

void DelBST(BSTree *t,int k)
{
/*在二叉排序树*t中删除关键字为k的结点*/
 BSTree p,f,q,s,root;
 root=*t;
 p=*t;  f=NULL;
 while(p)
    {if(p->key==k) break;                        /*找到关键字为k的结点*/
     f=p;
     p=(k<p->key)?p->lchild:p->rchild;
   /*   分别在*p的左、右子树中查找*/
    }
 if(!p) return;                     /*二叉排序树中无关键字为k的结点*/
 if(p->lchild==NULL&&p->rchild==NULL)
   {if(p==*t) *t=NULL;
    else if(p==f->lchild) f->lchild=NULL;
	 else f->rchild=NULL;
    free(p);
    }
 else
   if(p->lchild==NULL&&p->rchild!=NULL)                    /* *p无左子树*/
       { if(f->lchild==p)
	       f->lchild=p->rchild;  /*将*p的右子树链接到其父结点的左链上*/
	     else
	       f->rchild=p->rchild;  /*将*p的右子树链接到其父结点的右链上*/
	 free(p);
       }
   else if(p->rchild==NULL&&p->lchild!=NULL)              /**p有左子树*/
	   { if (f->lchild==p)              /*用*p的左子树代替*p*/
		  f->lchild=p->lchild;
		else
		  f->rchild=p->lchild;
	      free(p);
	    }
	 else if(p->lchild!=NULL&&p->rchild!=NULL)
		{q=p;s=p->lchild;
		 while(s->rchild) {q=s;s=s->rchild;}
		 p->key=s->key;
		 if(q!=p) q->rchild=s->lchild;
		 else q->lchild=s->lchild;
		 free(s);
		 }
}

void InorderBSTree(BSTree p)
{
  if(p)
  {
   InorderBSTree(p->lchild);
   printf("%d ",p->key);
   InorderBSTree(p->rchild);}
 }
void operation()
{	
	cout<<"\t0,操作结束"<<endl;
	cout<<"\t1,初始化一棵二叉排序树"<<endl;
	cout<<"\t2,在二叉排序树上查找一个元素"<<endl;
	cout<<"\t3,在二叉排序树上插入一个元素"<<endl;
	cout<<"\t4,在二叉排序树上删除一个元素"<<endl;
	cout<<"\t5,中序遍历二叉排序树"<<endl;
}
int main()
{
	BSTree t=NULL,p;
	int k,key;
	operation();
	while(true)
	{
	   printf("\t请输入操作序号:\n");
	   scanf("%d",&k);
	   switch(k)
	   {
	   case 0: exit(0); 
	   case 1: printf("请输入关键字的值,以0结束:\n");
		       scanf("%d",&key);
               while(key)
			   {
				  InsertBST(&t,key);
				  scanf("%d",&key);
			   }
			  printf("二叉排序树建立完成:\n");
			  break;
	   case 2: printf("请输入要查找的结点的关键字的值:\n");
		       scanf("%d",&key);
			   p=SearchBST(t,key);
			   if(p==NULL) printf("没有查找到该结点\n");
               else printf("查找到该结点\n");
	           break;
	   case 3: printf("请输入插入元素的值:\n");
			   scanf("%d",&key);
			   InsertBST2(t,key);
			   printf("该点插入成功\n");
			   break;
	   case 4: printf("请输入要删除的结点的关键字的值:\n");
		        scanf("%d",&key);
                DelBST(&t,key);
				printf("该点删除成功\n");
				break;
	   case 5: printf("中序遍历建立的二叉排序树的序列为:\n");
		       InorderBSTree(t);
			   break;
		default:printf("你没有选择排序方式");break;

	   }

	}
	return 0;
}


 

1. 顺序存储结构中数据中数据元素之间逻辑关系是由( )表示的,链接存储结构中的数据元素之间的逻辑关系是由( )表示的。 A.线性结构 B.非线性结构 C.存储位置 D.指针 2. 线性表是( )。 A.一个有限序列,可以为空 B. 一个有限序列,不能为空 C. 一个无限序列,可以为空 D. 一个无限序列,不能为空 3. 已知一维数组A采用顺序存储结构,每个元素占用4个存储单元,第9个元素的地址为144,则第一个元素的地址是( )。 A. 108 B. 180 C. 176 D. 112 4. 在单链表中删除指针p所指结点的后继结点,则执行( )。 A. p->next= p->next->next B. p->next= p->next C. p= p->next->next D. p= p->next; p->next= p->next->next 5. 若某链表最常用的操作是在最后一个结点之后插入一个结点删除最后一个结点,则采用( )存储方式最节省时间。 A. 单链表 B. 双链表 C. 带头结点的双循环链表 D. 单循环链表 6.二维数组A[7][8]以列序为主序的存储, 计算数组元素A[5][3] 的一维存储空间下标 k=( )。 A. 38 B. 43 C. 26 D. 29 二、完成下列填空题(每空3分,共9分)。 1.在顺序表L中第i个位置上插入一个新的元素e: Status ListInsert_Sq(SqList &L , int i , ET e){ if ( iL.length+1) return ERROR; if(L.length >= L.listsize){ p=(ET*)realloc(L.elem,(L.listsize+10)*sizeof(ET)); if (p==NULL) exit(OVERFLOW); L.elem=p; } for( j=L.length ; j>=i ; --j ) L.elem[j]=L.elem[j-1] ; L.elem[j]=e ; ++L.length ; return OK; } 2. 删除双向链表中p所指向的节点算法: status delete(DuLinkList L, DuLinkList p) { if (p= =L) return ERROR; else { p->prior->next=p->next; p->next->prior=p->prior ; } free(p); return OK; } 三、编程题(共27分)。 1. (共12分)用顺序表表示集合,设计算法实现集合的求差集运算,要求不另外开辟空间。 顺序表的存储结构定义如下: #define Maxsize 100 typedef struct { ElemType data[MaxSize]; // ElemType表示不确定的数据类型 int length; // length表示线性表的长度 }SqList; 将如下函数,伪码补充完整(8分),代码前先用文字描述自己的算法思想(4分)。 文字描述算法:略(4分) void Difference(SqList A, SqList B) {//参考代码如下如下(8分) for (i=0;i<A.length;i++) for(j=0;j<B.length;j++) if(A.data[i]==B.data[j]) { A.data[i]=’#’; break; } for (k=0,i=0;inext == L) return; p = L; while (p->next != L)   { if (p->next->data != e) P = p->next; else { q = p->next;p->next = q->next; free(q);} } } 时间复杂度分析:(2分) 时间复杂度为O(n)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值