用C语言实现二叉排序的建立。查询。删除。插入

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用C语言实现二叉排序的建立。查询。删除。插入相关的知识,希望对你有一定的参考价值。

求高手,注意是用C语言不是C++。
最好有简单的说明,满意的话还有分加

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

#define TRUE 1
#define OK 1
#define FALSE 0
#define ERROR 0
typedef int Status;
typedef int ElemType;

#define EQ(a,b) ((a)== (b))
#define LT(a,b) ((a) <= (b))
#define LQ(a,b) ((a) >= (b))

typedef struct //静态表的定义

ElemType *elem;
int Length;
SSTable;

typedef struct BStNode //动态表的定义

ElemType data;
struct BStNode *lchild,*rchild;
BStNode, *BSTree;

void Creat_Table(SSTable &S) //建立静态表

int i;
printf("请输入要建静态表的长度: ");
scanf("%d",&S.Length);
S.elem = (int *) malloc (S.Length * sizeof(int));
printf("请输入要建静态表的元素: ");
for(i = 1; i <= S.Length; i++)

scanf("%d",&S.elem[i]);



int Search_Seq(SSTable ST,int Key) //静态表的查找


for(int i = ST.Length; !EQ(ST.elem[i],Key) ; --i);
return i;


void Creat_BinTable(SSTable &S) //创建有序的静态表

int i;
printf("请输入要建静态表的长度:");
scanf("%d",&S.Length);
S.elem = (int *) malloc (S.Length * sizeof(int));
printf("请输入要建静态表的有序表:");
for(i = 1; i <= S.Length; i++)

scanf("%d",&S.elem[i]);



int Search_Bin(SSTable ST,int Key) //有序表的二分查找

int low,high,mid;
low = 1; high = ST.Length;
while(low <= high )

mid = (low + high)/2;
if(EQ(Key , ST.elem[mid]))
return mid;
else if (LT(Key , ST.elem[mid]))
high = mid - 1;
else
low = mid + 1;

return ERROR;


Status InitDSTable(BSTree *DT) /* 操作结果: 构造一个空的动态查找表DT */

*DT=NULL;
return OK;


void print(int key) /* 遍历数的时候调用的函数 */

printf("%d ", key);


void DestroyDSTable(BSTree *DT) /* 初始条件: 动态查找表DT存在。操作结果: 销毁动态查找表DT */

if(*DT) /* 非空树 */

if((*DT)->lchild) /* 有左孩子 */
DestroyDSTable(&(*DT)->lchild); /* 销毁左孩子子树 */
if((*DT)->rchild) /* 有右孩子 */
DestroyDSTable(&(*DT)->rchild); /* 销毁右孩子子树 */
free(*DT); /* 释放根结点 */
*DT=NULL; /* 空指针赋0 */



BSTree SearchBST(BSTree DT,int key)
/* 在根指针T所指二叉排序树中递归地查找某关键字等于key的数据元素, */
/* 若查找成功,则返回指向该数据元素结点的指针,否则返回空指针*/
if((!DT)||EQ(key,DT->data))
return DT; /* 查找结束 */
else if (LT(key,DT->data)) /* 在左子树中继续查找 */
return SearchBST(DT->lchild,key);
else
return SearchBST(DT->rchild,key); /* 在右子树中继续查找 */


void SearchBST1(BSTree *DT,int key,BSTree f,BSTree *p,Status *flag)
/* 在根指针T所指二叉排序树中递归地查找其关键字等于key的数据元素,若查找 */
/* 成功,则指针p指向该数据元素结点,并返回TRUE,否则指针p指向查找路径上 */
/* 访问的最后一个结点并返回FALSE,指针f指向T的双亲,其初始调用值为NULL */
if(!*DT) /* 查找不成功 */

*p=f;
*flag=FALSE;

else if (EQ(key,(*DT)->data)) /* 查找成功 */

*p=*DT;
*flag=TRUE;

else if (LT(key,(*DT)->data))
SearchBST1(&(*DT)->lchild,key,*DT,p,flag); /* 在左子树中继续查找 */
else
SearchBST1(&(*DT)->rchild,key,*DT,p,flag); /* 在右子树中继续查找 */


Status InsertBST(BSTree *DT, ElemType e)
/* 当二叉排序树T中不存在关键字等于e.key的数据元素时,插入e并返回TRUE, */
/* 否则返回FALSE。 */
BSTree p,s;
Status flag;
SearchBST1(DT,e,NULL,&p,&flag);
if(!flag) /* 查找不成功 */

s=(BSTree)malloc(sizeof(BStNode));
s->data = e;
s->lchild = s->rchild = NULL;
if(!p)
*DT=s; /* 被插结点*s为新的根结点 */
else if (LT(e,p->data))
p->lchild=s; /* 被插结点*s为左孩子 */
else
p->rchild=s; /* 被插结点*s为右孩子 */
return TRUE;

else
return FALSE; /* 树中已有关键字相同的结点,不再插入 */


void Delete(BSTree *p)
/* 从二叉排序树中删除结点p,并重接它的左或右子树。 */
BSTree q,s;
if(!(*p)->rchild) /* 右子树空则只需重接它的左子树(待删结点是叶子也走此分支) */

q=*p;
*p=(*p)->lchild;
free(q);

else if(!(*p)->lchild) /* 只需重接它的右子树 */

q=*p;
*p=(*p)->rchild;
free(q);

else /* 左右子树均不空 */

q=*p;
s=(*p)->lchild;
while(s->rchild) /* 转左,然后向右到尽头(找待删结点的前驱) */

q=s;
s=s->rchild;

(*p)->data=s->data; /* s指向被删结点的"前驱"(将被删结点前驱的值取代被删结点的值) */
if(q!=*p)
q->rchild=s->lchild; /* 重接*q的右子树 */
else
q->lchild=s->lchild; /* 重接*q的左子树 */
free(s);



Status DeleteBST(BSTree *T,int key)
/* 若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素结点, */
/* 并返回TRUE;否则返回FALSE。*/
if(!*T) /* 不存在关键字等于key的数据元素 */
return FALSE;
else

if EQ(key,(*T)->data) /* 找到关键字等于key的数据元素 */
Delete(T);
else if LT(key,(*T)->data)
DeleteBST(&(*T)->lchild,key);
else
DeleteBST(&(*T)->rchild,key);
return TRUE;



void TraverseDSTable(BSTree DT,void(*Visit)(ElemType))
/* 初始条件: 动态查找表DT存在,Visit是对结点操作的应用函数 */
/* 操作结果: 按关键字的顺序对DT的每个结点调用函数Visit()一次且至多一次 */
if(DT)

TraverseDSTable(DT->lchild,Visit); /* 先中序遍历左子树 */
Visit(DT->data); /* 再访问根结点 */
TraverseDSTable(DT->rchild,Visit); /* 最后中序遍历右子树 */



void Creat_BSTTable(BSTree &T)

int data,length;
int i;
printf("请输入要建动态表的长度: ");
scanf("%d",&length);
printf("请输入要建动态表: ");
for(i = 0; i < length; i++)

scanf("%d",&data);
InsertBST(&T,data);

printf ("\n");



#include "Head.h"
int main()

SSTable ST;
SSTable SS;
BSTree DT;
int Key,e,i;
printf("******************建立一个无序静态线性表**********************: \n");
Creat_Table(ST);
printf("请输入你要查找的元素: ");
scanf("%d", &Key);

i = Search_Seq(ST,Key);
if(i)
printf("恭喜你查找成功该元素是%d为第%d个记录的关键字\n",ST.elem[i],i);
else
printf("没找到\n");

printf("*******************建立一个有序表用二分查找*********************: \n");
Creat_BinTable(SS);
printf("请输入你要查找的元素: ");
scanf("%d",&Key);
i = Search_Bin(SS,Key);
if(i)
printf("恭喜你查找成功该元素是%d为第%d个记录的关键字\n",SS.elem[i],i);
else
printf("没找到\n");

printf("******************建立一个二叉排序树**********************: \n");
InitDSTable(&DT);
Creat_BSTTable(DT);

printf("中序遍历这颗二叉排序树的结果为: \n");
TraverseDSTable(DT,print);
printf ("\n");

printf("请输入你要查找的元素: ");
scanf("%d", &Key);
if (SearchBST(DT,Key))
printf("恭喜你查找成功: \n");
else
printf("查找不成功: \n");

printf("请输入你要插入的元素: ");
scanf("%d", &e);

if(InsertBST(&DT,e))
printf("成功插入一个元素后中序遍历这颗二叉树结果为: \n");
else
printf("插入不成功: \n");

TraverseDSTable(DT,print);
printf ("\n");

printf("请输入你要删除的元素: ");
scanf("%d", &Key);

if(DeleteBST(&DT,Key))
printf("成功删除一个元素后中序遍历这颗二叉树结果为: \n");
else
printf("删除不成功: \n");

TraverseDSTable(DT,print);
printf ("\n");
DestroyDSTable(&DT);
return 0;

参考技术A #include <stdio.h>
#include <stdlib.h>
typedef struct node

int key;
struct node *LChild,*RChild; //孩子指针
BSTNode,*BSTree; //定义二叉树

void CreatBST(BSTree *bst);
BSTree SearchBST(BSTree bst,int key) ;
void InsertBST(BSTree *bst,int key) ;
BSTNode * DelBST(BSTree t,int k) ;//以上是函数的声明
void print_bst(BSTree t) //打印

if (!t)

print_bst(t->LChild);
printf("\t%d\t", t->key);
print_bst(t->RChild);



const int n = 10;

/*创建树*/
void CreatBST(BSTree *bst)

int i;
int key;
*bst=NULL;
for(i=1;i <=n;i++)

scanf("%d",&key);
InsertBST(bst,key); //创建
;


/*寻找*/
BSTree SearchBST(BSTree bst,int key)

if(!bst)
return NULL; //bst为空
else
if(bst->key==key)
return bst; //找到
else
if(key <bst->key)
return SearchBST(bst->LChild, key); //左孩子递归调用查找
else
return SearchBST(bst->RChild, key); //右孩子递归


/*插入*/
void InsertBST(BSTree *bst,int key)

BSTree t;
if(*bst==NULL)

t=(BSTree)malloc(sizeof(BSTNode)); //树为空,申请空间
t->key=key;
t->LChild=NULL;
t->RChild=NULL;
*bst=t; //插入

else
if(key <(*bst)->key)
InsertBST(&((*bst)->LChild),key); //插到左子树
else
if(key>(*bst)->key)
InsertBST(&(*bst)->RChild,key); //插到右子树


/*删除*/
BSTNode * DelBST(BSTree t,int k)

BSTNode *p,*f,*s,*q;
p=t;
f=NULL;
while(p) //树非空

if(p->key==k) //根节点等于K
break;
f=p;
if(p->key>k) //向左子树方向
p=p->LChild;
else
p=p->RChild; //右

if(p==NULL) //为空
return t;
if(p->LChild==NULL)//左 ,下边就是删除过程

if(f==NULL)
t=p->RChild;
else
if(f->LChild==p)
f->LChild=p->RChild;
else
f->RChild=p->LChild;
free(p); //释放空间

else //右,下边就是删除过程

q=p;
s=s->LChild;
while(s->RChild)

q=s;
s=s->RChild;

if(q==p)
q->LChild=s->LChild;
else
q->RChild=s->LChild;
p->key=s->key;
free(s); //释放空间

return t;


int main()

BSTNode * root;
int loop,i,data;
loop=true;
while(loop)

printf("\n***************二叉树操作菜单**************\n");
printf(" 1.创建\n");
printf(" 2.查找\n");
printf(" 3.插入\n");
printf(" 4.删除\n");
printf(" 5.打印\n");
printf(" 0.退出\n");
scanf("%d",&i);
switch(i)

case 0:
loop=false;
break;

case 1:

CreatBST(&root);
break;
case 2:

printf("Please input the data you want search.\n");
scanf("%d",&data);
SearchBST(root,data);
break;
case 3:

printf("Please input the data you want insert.\n");
scanf("%d",&data);
InsertBST(&root,data);
break;
case 4:

printf("Please input the data you want delete.\n");
scanf("%d",&data);
root=DelBST(root,data);
break;
case 5:
printf("\n");
if (root!=NULL)
printf("The BSTree's root is:%d\n",root->key);
print_bst(root);
break;




追问

有错误,修改一下好吗

参考技术B 可以去电驴网站查一下,里面的资源很多

c语言 建立一个链表,实现增删改查

下面是以前写的一个关于链表的综合操作,你可以看看,应该可以满足你的要求。
/********************************************************************
created: 2009/09/15
created: 16:9:2009 17:20
filename: E:\dd\lianbiao\lianbiao.cpp
author:
purpose: 一个win32 的控制台程序
实现单项链表的数据删除、插入、排序等功能
*********************************************************************/
#include <stdio.h>
#include "windows.h"
#include "malloc.h"

#define LEN sizeof(struct student)
#define NULL 0
#define N 5 //N为所要创建的链表的长度

int n = 0; //定义全局变量n,表示链表的节点个数
/*******************************************************************
Author/data: /2009/09/15
Description: 声明一个结构体作为链表的节点.
tip: student 只是一个标签,是不能声明变量的
*********************************************************************/
struct student

int num;
float cj;
struct student *Pnext;
;

/*******************************************************************
Author/data: /2009/09/15
Description: 创建一个动态链表
参数: 返回链表的第一个节点的地址
x 为链表的长度
*********************************************************************/
struct student *pa(int x)

struct student *head;
struct student *p1,*p2;

// n = 0;
p1 = p2 = (struct student *)malloc(LEN); //开辟一个结构体内存
fflush(stdin); // 清除缓冲区数据 避免直接读入缓冲区数据
scanf("%d,%f",&p1->num,&p1->cj);
head = NULL;
while(p1->Pnext != NULL)

n = n+1;
if(n == 1)

head = p1; // 链表的头地址

else

p2->Pnext = p1; //链接链表数据

/* 判断是否最后一个 */
if(n >= x)

p1->Pnext = NULL;

else

p2 = p1;
p1 = (struct student *)malloc(LEN);
fflush(stdin);
scanf("%d,%f",&p1->num,&p1->cj);


return(head);

/*******************************************************************
Author/data: /2009/09/15
Description: 输出一个链表
参数: head为第一个节点的地址
*********************************************************************/
void print(struct student *head)

struct student *p;

int i = 0;
printf("\nNow,These %d records are:\n",n);
p = head;
if(head != NULL) // 如果链表不是空的,则进行数据输出

do

printf("%d\t",i++);
printf("%5d %5.1f\n",p->num,p->cj); // 输出链表数据
p = p->Pnext;
while(p != NULL);


/*******************************************************************
Author/data: /2009/09/16
Description: 释放动态链表的地址空间
参数: 链表的头地址head
无返回值
*********************************************************************/
void freelinkspace(struct student *head)

struct student Ltemp;
Ltemp.Pnext = head->Pnext; // Ltemp 用来存放->next,避免空间被
// 释放后,找不到下一个结点的地址
while(head->Pnext != NULL) // 判断是否已经空间释放到最后一个

free(head);
head = Ltemp.Pnext;
Ltemp.Pnext = head->Pnext;

free(head); // 释放最后一个结点空间


/*******************************************************************
Author/data: /2009/09/15
Description: 删除链表链表中的一个结点
参数: head 为第一个节点的地址
num 为要删除结点的序号(head->num)
*********************************************************************/
struct student *del(struct student *head,int num)

struct student *p1,*p2;
p1 = head;
while(p1->num!=num && p1->Pnext!=NULL) // 寻找要删除的结点

p2 = p1; // p2 存放删除结点的前一个结点地址
p1 = p1->Pnext; // p1 存放要删除的结点

if(num == p1->num) // 是否找到要删除结点

if(p1 == head) // 删除的是第一个结点

head = p1->Pnext;

else if(p1->Pnext == NULL) // 删除的是最后一个结点

p2->Pnext = NULL;

else // 删除中间的结点

p2->Pnext = p1->Pnext;
p1->Pnext = NULL;

printf("delete: %d\n",num);
n = n-1; // 链表长度 - 1

else

printf("%d not been found! \n",num);

delete(p1);
return(head);

/*******************************************************************
Author/data: /2009/09/16
Description: 添加一个结点到链表中
参数: head 为第一个结点的地址指针
stud 为要插入的结点的地址指针
*********************************************************************/
struct student *insert(struct student *head,struct student *stud)

struct student *p0,*p1,*p2;
p0 = stud;
p1 = head;
while(p0->num>p1->num && p1->Pnext!=NULL) // 找到添加结点的位置

p2 = p1; // p2 存放要添加的前一个结点的地址
p1 = p1->Pnext; // p1 存放要添加的后一个结点的地址

if(p0->num<=p1->num && p1->Pnext!=NULL)

if(p1 == head) // 添加结点到第一个位置

p0->Pnext = p1;
head = p0;

else

p2->Pnext = p0;
p0->Pnext = p1;


else // 添加结点到最后一个位置


p1->Pnext = p0;
p0->Pnext = NULL;

n = n+1; // 结点数目 + 1
return(head);

/*******************************************************************
Author/data: /2009/09/16
Description: 链表的重新排序===按照.num(不能重复)的大小从小到大排
列链表数据
参数: head 接收链表第一个节点的地址指针
返回值为新生成链表的第一个节点的地址指针
*********************************************************************/
struct student *linkpaix(struct student *head)

struct student *stemp,*ltemp,*shead,*head_h; /* */
struct student *p,*q; /* 申请两个链表指针,用来储存链表交换过
程的中间值 */
head_h = head;
ltemp = head;

p = (struct student *) malloc(LEN);
q = (struct student *) malloc(LEN); /* 为p,q开辟动态存储空间 */

/* -==== 先将链表的第一个数据与其他数据比较 ====- */
while(head->Pnext != NULL)

shead = head;
head = head->Pnext;
if(ltemp->num > head->num)

if(ltemp == shead)

ltemp ->Pnext = head ->Pnext;
head ->Pnext = ltemp;

else

p->Pnext = head ->Pnext;
q->Pnext = ltemp ->Pnext;
head ->Pnext = q->Pnext;
shead ->Pnext = ltemp;
ltemp ->Pnext = p->Pnext;

head_h = head;
head = ltemp;
ltemp = head_h;



/* -==== 先将链表的第一个数据与其他数据比较 ====- */

/* -==== 比较链表第一个以外的数据 ====- */
while(ltemp ->Pnext != NULL)

stemp = ltemp;
ltemp = ltemp ->Pnext;
head = ltemp;
while(head->Pnext != NULL)

shead = head;
head = head->Pnext;
if(ltemp->num > head->num)

if(ltemp == shead)

p->Pnext = head ->Pnext;
stemp ->Pnext = head;
head ->Pnext = ltemp;
ltemp ->Pnext = p->Pnext;

else

p->Pnext = head ->Pnext;
q->Pnext = ltemp ->Pnext;
stemp ->Pnext = head;
head ->Pnext = q->Pnext;
shead ->Pnext = ltemp;
ltemp ->Pnext = p->Pnext;

head = ltemp;
ltemp = stemp ->Pnext;




/* -==== 比较链表第一个以外的数据 ====- */

free(p);
free(q); // 释放p,q的动态存储空间
return(head_h);


/*******************************************************************
Author/data: /2009/09/15
Description: 主函数
参数:
*********************************************************************/
void main()

struct student *phead,*pins; // 定义2个链表指针
int delnum, selflog,flog_a = 1,Nf = 1; // 要删除的对象id
char delflog ; // 删除标志y/n
char insflog, flog_nx = 'n';
char flog_free ; // 释放标志
/* === 输入N个数据 === N 为定值
printf("please input %d numbers:\n",N);
phead = pa(N); // 创建一个动态链表,并赋值
print(phead); // 输出链表数据
*/

/* === 输入Nx个数据 === Nx 为输入值 === */
int Nx; // Nx 想要输入的链表长度
printf("How long do you want establish? \t");
fflush(stdin);
scanf("%d",&Nx);
/* -== 判断创建的是否是一个空链表 ==- */
while(Nx == 0)

printf("您要创建的是一个空链表,是否确定?y/n \t");
fflush(stdin);
scanf("%c",&flog_nx);
if(flog_nx == 'n')

printf("How long do you want input?\t");
fflush(stdin);
scanf("%d",&Nx);

else if(flog_nx == 'y') goto endl;
else

printf("wrong input!\n");
printf("How long do you want input?\t");
fflush(stdin);
scanf("%d",&Nx);



printf("please input %d numbers: ",Nx);
printf("如:1,3 两个数中间以,隔开\n");
phead = pa(Nx); // 创建一个动态链表,并赋值
print(phead); // 输出链表数据

/* -== 链表操作 ==- */
while(flog_a)

if(phead == NULL) printf("链表已空,无法操作\n"); flog_a = 0; break;
printf("\n操作\n1:\t插入数据\n2:\t删除数据\n3:\t排序\n4:\t清屏\n5:\t输出现在的链表数据\n0:\texit\n");
printf("\nPlease input:\t");
fflush(stdin);
if(scanf("%d",&selflog)) // select flog 选择项
switch(selflog)

case 1 :
/* ====== 插入数据到链表 ====== */
printf("insert someone? y/n\t");
fflush(stdin);
scanf("%c",&insflog);
while(insflog != 'n')

while(insflog != 'y'&& insflog != 'n')

printf("wrnong input,please input again. \n");
printf("another one? y/n\t");
fflush(stdin);
scanf("%c",&insflog);

printf("please input the date:\n");
pins = (struct student *)malloc(LEN);
fflush(stdin);
scanf("%d,%f",&pins->num,&pins->cj);
phead = insert(phead,pins);
print(phead);

printf("another one? y/n\t");
fflush(stdin);
scanf("%c",&insflog);
while(insflog != 'y'&& insflog != 'n')

printf("wrnong input,please input again. \n");
printf("another one? y/n\t");
fflush(stdin);
scanf("%c",&insflog);


/* ====== 插入数据到链表 ====== */
break;

case 2 :
/* ====== 删除链表中的数据 ====== */
printf("del someone? y/n\t");
fflush(stdin);
scanf("%c",&delflog);
while(delflog != 'n' && phead != NULL)

while(delflog != 'y'&& delflog != 'n')

printf("wrnong input,please input again. \n");
printf("del someone? y/n\t");
fflush(stdin);
scanf("%c",&delflog);

printf("please input the student what you want del:\n");
fflush(stdin);
scanf("%d",&delnum);
phead = del(phead,delnum);
print(phead);

printf("another one? y/n\t");
fflush(stdin);
scanf("%c",&delflog);
if((n+1)==0)

printf("There is no more num could be del!\n");
break;


/* ====== 删除链表中的数据 ====== */
break;

case 3 :
/* ====== 排列链表数据 ====== */
printf("\n排序之后:");
phead = linkpaix(phead);
print(phead); // 排序该数据链表
/* ====== 排列链表数据 ====== */
break;
case 4 :// clrscr();
system("cls");
break;

case 5 : print(phead); break;
case 0 : flog_a = 0 ; break; /* 退出 */

default : printf("wrong input\nPlease input again");
break;

else printf("非法输入!\n");

endl: while(1)

if(Nx == 0)

printf("Can't establish the link!\n");
break;

printf("\n保留数据?y/n\t"); // 是否释放地址空间
fflush(stdin);
scanf("%c",&flog_free);
if(flog_free == 'y')

break;

else if(flog_free == 'n')

freelinkspace(phead);
break;

else

printf("wrong input!\n");



printf("OVER!\nGOOD LUCK!\n");
参考技术A LZ的很好。。。

以上是关于用C语言实现二叉排序的建立。查询。删除。插入的主要内容,如果未能解决你的问题,请参考以下文章

二叉排序树(BST)的思路及C语言实现

c语言 建立一个链表,实现增删改查

大话数据结构C语言56 二叉排序树的查找插入和删除

C语言高手请进!!!

二叉排序树的实现(c语言)

C语言: 链表查询