【数据结构实验(c语言版)】

线性表及其应用

实验内容:

 1. 【问题描述】设计一个实现任意长的整数进行加法运算的演示程序 。
 2. 【基本要求】 利用双向循环链表实现长整数的存储,每个结点含一个整形变量。输入和输出形式:按中国对于长整数的表示习惯,每四位一组,组间用逗号隔开。
 3. 【测试数据】
(1)0;0;应输出“0”。
(2)-2345,6789;-7654,3211;应输出“-1,0000,0000”。
(3)-9999,9999;1,0000,0000,0000;应输出“9999,0000,0001”。
(4)1,0001,0001;-1,0001,0001;应输出“0”。
(5)1,0001,0001;-1,0001,0000;应输出“1”。
(6)-9999,9999,9999;-9999,9999,9999;应输出“-1,9999,9999,9998”。
(7)1,0000,9999,9999;1;应输出“1,0001,0000,0000”。 

实现思路:

1.用一个头节点储存符号位 
2.用双向循环链表储存输入数据采用头插法输入数据:先用getchar()检查输入的是正数还是负数然后用isdigit()检查是否为数字,如果是用ungetc()返回数字用dowhile 循环输入 
3.打印数据:while循环打印,首先打印首组数字和“-”在打印时用%04确保0的足够。
4.计算:加法和减法;从最后一组数字向前计算 
5.再用一个链表储存计算结果,使用尾插法来匹配计算结果的输入。
用一个计算模块来包含加法和减法,并且通过判断输入的两个数的正负来判断使用

实现代码:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct node{
    int data;
    struct node *next;
    struct node *prior;
}Node,*List;

List InitList();
void InsertList();//头插法 储存数据输入 方便输出时从头部输入且储存方式符合阅读方式
List InputData();//输入数据
void PrintList();//打印结果 从头部开始打印
void InsertResult();//尾插法 计算结果的输入
void AddList();
void SubList();
List CalList();//判断加减法并计算
void Del();

void Del(List L,Node *p){
    p->prior->next = p->next;
    p->next->prior = p->prior;
    free(p);
}
List InitList(int sign){
    //符号位,头节点存放
    List L;
    L = (List)malloc(sizeof(Node));
    L -> next = L -> prior = L;
    L ->data = sign;
    return L;
}
void InsertList(List L,int data){
    Node *p;
    p = (List)malloc(sizeof(Node));
    p ->data = data;
    p ->next = L;
    p ->prior = L ->prior;
    L ->prior ->next = p;
    L ->prior = p;
}
List InputData(){
    int firstnum = 1, data;
    char c;
    List L;
    L =(List)malloc(sizeof(Node));
    L ->next = L ->prior = L;
    if((c = getchar())=='-'){//判断首输入 是否为负
        L = InitList(-1);
    }else{
        L = InitList(1);
    }
    if (isdigit(c))//是否为数字
        ungetc(c,stdin);//退回首个数字
    do{
        scanf("%d",&data);
        InsertList(L,data);
    }while((c = getchar())!= '\n');
    return L;
}
void PrintList(List L){
    Node *p = L;
    int firstg = 1;//第一组数字
    if(p->data == -1&&p->next->data != 0){
        printf("-");
    }
    p = p->next;
    while(p != L){
        if(firstg){
            firstg = 0;
            printf("%d",p->data);
        }else{
            printf(",%04d",p->data);
        }
        p = p->next;
    }
    printf("\n");
}
void InsertResult(List L,int data){
    Node *p;
    p = (List)malloc(sizeof(Node));
    p ->data = data;
    p -> next = L ->next;
    p ->prior = L ;
    L ->next ->prior = p;
    L ->next = p;
}
void AddList(List a,List b,List c)//从后往前加{
    List pa,pb;
    int carry = 0;/**进位**/
    int temp;
    /**循环列表 第一个的前驱就是最后一个*/
    pa = a -> prior;
    pb = b -> prior;
    while((pa!=a)&&(pb!=b)){
        temp = pa->data + pb -> data + carry;
        if(temp >= 10000){
            carry = 1;
            temp -= 10000;
        }else{
            carry = 0;
         }
        InsertResult(c,temp);
        pa = pa ->prior;
        pb = pb ->prior;
    }
    while(pa != a){//pb已经到头了
        temp = pa ->data + carry;
        if(temp >= 10000){
            carry  =1;
            temp -= 10000;
        }else{
            carry = 0;
         }
        InsertResult(c,temp);
        pa = pa ->prior;
    }
    while(pb != b){//pa已经到头了
        temp = pb ->data + carry;
        if(temp >= 10000){
            carry  = 1;
            temp -= 10000;
        }else{
            carry = 0;
         }
        InsertResult(c,temp);
        pb = pb ->prior;
    }
    if(carry != 0)//向前进1
        InsertResult(c,1);
}
void SubList(List a,List b,List c){
    List pa, pb, pc;
    int borrow = 0,tmp;
    pa = a->prior;
    pb = b->prior;
    while((pa != a) && (pb != b)){                //判断a>b还是a<b
        if (pa->data >= pb->data + borrow)
            borrow = 0;
        else
            borrow = 1;
        pa = pa->prior;
        pb = pb->prior;
    }
    if (pa != a || (pa == a && pb == b && borrow == 0)){    //判断a>b还是a<b
    
       // a >= b
        c->data = a->data;
    }
     pa = a->prior;
     pb = b->prior;
     if(c->data!=b->data){//a>b情况
        borrow=0;
        while((pa != a) && (pb != b)){        //将b中与a等大的相减导入c
            if (pa->data >= pb->data + borrow){   //不存在借位
                tmp = pa->data - pb->data - borrow;
                borrow = 0;
            }else{
                tmp = 10000 + pa->data - pb->data - borrow;
                borrow = 1;
             }
            InsertResult(c, tmp);
            pa = pa->prior;
            pb = pb->prior;
        }
        while(pa != a){                  //把a中剩余导入c
            if (pa->data >= borrow){
                tmp = pa->data - borrow;
                borrow = 0;
            }else{
                tmp = 10000 - pa->data - borrow;
                borrow = 1;
             }
            InsertResult(c, tmp);
            pa = pa->prior;
        }
      } else{   //c<b
        c->data=b->data;
        borrow=0;
     while((pa != a) && (pb != b)){          //将a中与b等大导入c
        if (pb->data >= pa->data + borrow){
            tmp = pb->data - pa->data - borrow;
            borrow = 0;
        }else{
            tmp = 10000 + pb->data - pa->data - borrow;
            borrow = 1;
         }
        InsertResult(c, tmp);
        pa = pa->prior;
        pb = pb->prior;
     }
     while(pb != b){           //导入b中剩余
        if (pb->data >= borrow){
            tmp = pb->data - borrow;
            borrow = 0;
        }else{
            tmp = 10000 - pb->data - borrow;
            borrow = 1;
         }
        InsertResult(c, tmp);
        pb = pb->prior;
     }
    }
    pc = c->next;
    while(pc->next !=c && pc->data == 0){     //为了防止头因借位变为0的情况
        pc = pc->next;
        Del(c, pc->prior);
    }
}
List CalList(List a, List b){
    List c;
    if(a->data * b ->data > 0){
        c = InitList(a->data);
        AddList(a,b,c);
    }else{
        c = InitList(b->data);
        SubList(a,b,c);
     }
    return c;
}
void int main(){
    while(1)
    {List a,b,c;
    printf("第一个数:\n");
    a = InputData();
    printf("第二个数:\n");
    b = InputData();
    c = CalList(a,b);
    printf("运算结果:");
    PrintList(c);
    printf("*********************************************\n");
    }
    return 0;
}

栈与马踏棋盘

实验内容:

【问题描述】设计一个国际象棋的马踏遍棋盘的演示程序。
【基本要求】将马随机放在国际象棋的8×8棋盘Board[0~7][0~7]的某个方格中,马按走棋规则进行移动。要求每个方格只进入一次,走遍棋盘上全部64个方格。编制非递归程序,求出马的行走路线,并按求出的行走路线,将数字1,2,…,64依次填入一个8×8的方阵,输出之。
【测试数据】自行指定马的初始位置。
【实现提示】
     马在棋盘上走“日”字型,比如初始马在第2行第3列,可行走的八个位置见下图。

	0	1	2	3	4	5	6	7
0			8		1			
1		7				2		
2				H				
3		6				3		
4			5		4			
5								
6								
7						

实现思路:

1.踏棋盘就是将1至64填入8*8的矩阵中,要求相邻的两个数按照“马”移动规则放置在矩阵中。这样在矩阵中从1遍历到64,就得到了马踏棋盘的行走路线。这个过程是一个重复性操作的递归过程。
2.“马”的行走过程,实际上就是一个深度探索的过程。“探索树”的根结点为“马”在棋盘中的初始位置,接下来“马”有两种行走方式,于是根结点派生出两个分支。再往下进行相同的步骤又会得到两条不同了路径,如此派生下去,就得到“马”的所有有可能的走步状态。
3.为了题目要求的程序功能,可以采用顺序栈或者链栈来存储它的数据,因为所需要的存储空间不是很大,不需动态的开辟很多空间,所以采用相对简单的顺序栈来存储数据,既方便有简单,而用链栈在实现上相对比顺序栈复杂的一点。
4.因此构建代码分为三个模块:起始坐标函数模块——马儿在棋盘上的起始位置;探寻路径函数模块——马儿每个方向进行尝试,直到试完整个棋盘;输出马
儿行走的路径函数模块——输出马儿行走的路径;

实现代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define X 8
#define Y 8
#define STACK_INIT_SIZE 100
#define STACKINCREMENT
typedef int ElemType;
typedef struct {
    ElemType *top;
    ElemType *base;
    int stacksize;
}sqStack;

int chess[X][Y];
int travel();
int nextlocation(int *x,int *y,int count);
void initstack();
void push();
void pop();
void print();

int nextlocation(int *x,int *y,int count){
    switch(count){
    case 0:
        if(*x+2<=X-1 && y-1>=0 && chess[*x+2][*y-1]==0){
            *x+=2;
            *y-=1;
            return 1;
        }
        break;
    case 1:
        if( *x+2 <=X-1 && *y+1<=Y-1 && chess[*x+2][*y+1]==0){
            *x+=2;
            *y+=1;
            return 1;
        }
        break;
    case 2:
        if( *x+1<=X-1 && *y-2 >=0 && chess[*x+1][*y-2]==0){
            *x+=1;
            *y+=2;
            return 1;
        }
        break;
    case 3:
        if(*x+1<=X-1 && *y+2 <= Y-1 && chess[*x+1][*y+2]==0){
            *x+=1;
            *y+=2;
            return 1;
        }
        break;
    case 4:
        if(*x-2>=0 && *y-1>=0 && chess[*x-2][*y-1]==0){
            *x-=2;
            *y+=1;
            return 1;
        }
    case 5:
        if(*x-2>=0 && *y+1<=Y-1 && chess[*x-2][*y+1]==0){
            *x-=2;
            *y+=1;
            return 1;
        }
        break;
    case 6:
        if( *x-1>=0 && *y-2 >= 0 && chess[*x-1][*y-2]==0){
            *x-=1;
            *y-=2;
            return 1;
        }
        break;
    case 7:
        if(*x-1>=0 && *y+2<=Y-1 && chess[*x-1][*y+2]==0){
            *x-=1;
            *y+=2;
            return 1;
        }
        break;
    default:
        break;
    }
    return 0;
}
int travel(int x,int y,int tag)//x,y为坐标,tag为标记变量 非递归弄成全局变量,每走一步,tag+{
    chess[x][y]=tag;
    int x1 = x,y1=y,flag = 0,count = 0;
    if(X*Y == tag){
        return 1;
    }
    flag = nextlocation(&x1,&y1,count);
    while(0 == flag && count < 7){
        count++;
        flag = nextlocation(&x1,&y1,count);
    }
    while(flag){
     if(travel(x1,y1,tag+1)){
             return 1;
         }
        x1=x;
        y1=y;
        count++;
        flag=nextlocation(&x1,&y1,count);
    }
    if(0==flag){
        chess[x][y]= 0;
    }
}
void print(){
    int i,j;
    for(i=0;i<X;i++){
        for(j = 0;j<Y;j++){
            printf("%2d\t",chess[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}
void initstack(sqStack *s){
    s->base = (ElemType*)malloc(STACK_INIT_SIZE*sizeof(ElemType));
    if(!s->base){
        exit(0);
    }
    s->top = s->base;
    s->stacksize = STACK_INIT_SIZE;

}
void push(sqStack *s,ElemType *e){
    if(s->top - s->base >= s->stacksize ){
        s->base = (ElemType*)realloc(s->base,(s->stacksize + STACK_INIT_SIZE)*sizeof(ElemType));
        if(!s->base){
            exit(0);
        }
    }
    *(s->top)++ = e;
}
void pop(sqStack *s,ElemType *e){
    if(s->top = s->base){
        return;
    }
    *(--s->top) = e;
}
void int main(){
    int i,j;
    clock_t start,finish;
    start= clock();
    for(i=0;i<X;i++){
        for(j=0;j<Y;j++){
            chess[i][j]=0;
        }
    }
    if(!travel(2,0,1)){
        printf("fail");
    }
    print();
    finish=clock();
    printf("\ntime is :%d second",(double)(finish-start)/CLOCKS_PER_SEC);
    return 0;
}

二叉树的层次遍历

实验内容:

【问题描述】设计一个能够对链式存储的二叉树进行层次遍历的演示程序。
【基本要求】从键盘输入数据,创建一棵二叉树,然后将层次编历的结果输出。
【测试数据】输入的二叉树见教材(教材为严为民数据结构C语言版)127页图6.8(b),输出为ABCDEFG。

实现思路:

1.建立二叉树,前序遍历输入
2.建立队列
3.层序遍历输出:
根节点进入队列,根节点出队列,本根节点的左右儿子进队列,以此类推

实现代码:

/*
    【问题描述】设计一个能够对链式存储的二叉树进行层次遍历的演示程序。
    【基本要求】从键盘输入数据,创建一棵二叉树,然后将层次编历的结果输出。
    【测试数据】输入的二叉树见教材127页图6.8(b),输出为ABCDEFG。
*/
#include <stdio.h>
#include <stdlib.h>
#define MAX_LENGTH  50
typedef char ElemType;
typedef struct {
   ElemType *base;
   int front;
   int rear;
}SqQueue;
void initqueue(SqQueue *a){
	a->base=(ElemType *)malloc(sizeof(ElemType)* MAX_LENGTH);
	a->front=a->rear=0;
}
int SqQueueempty(SqQueue *a){
	if(a->rear==a->front) return 1;
	else return 0;
}
void enqueue(SqQueue *a, ElemType e){
	if((a->rear+1)%MAX_LENGTH==a->front) printf("full now!\n");
        else{
		a->base[a->rear]=e;
		a->rear=(a->rear+1)%MAX_LENGTH;

	}

}
void dequeue(SqQueue *a, ElemType *e){
	if(a->rear==a->front) printf("NULL!\n");
	else{
		*e=a->base[a->front];
		a->front=(a->front+1)%MAX_LENGTH;
	}

}
/**二叉树建立*/
typedef struct BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
void CreateBiTree(BiTree *T){//建立二叉树,前序遍历输入

    char c;
    scanf("%c",&c);
    if(c == ' '){
        *T = NULL;
    }else{
        *T = (BiTNode*)malloc(sizeof(BiTNode));
        (*T)->data=c;
        CreateBiTree(&(*T)->lchild);
        CreateBiTree(&(*T)->rchild);
    }
}
void visit(char c,int level){
    printf("%c,位于%d层\n",c,level);
}
void PreOrderTraversal(BiTree T,int level){
    if(T)
    {
        visit(T->data,level);
        PreOrderTraversal(T->lchild,level+1);
        PreOrderTraversal(T->rchild,level+1);
    }
}
void LevelQrderTraversal(BiTree T){
    SqQueue q;
    BiTree B;
    initqueue(&q);
    B = T;
    enqueue(&q,B);
    while(!SqQueueempty(&q)){
        dequeue(&q,&B);
        printf("%c",B->data);
        if(B->lchild)
            enqueue(&q,B->lchild);}
        if(B->rchild)
            enqueue(&q,B->rchild);
    }
}

void int main(){
    int level = 1;
    BiTree T = NULL;
    CreateBiTree(&T);
    PreOrderTraversal(T,level);
    LevelQrderTraversal(T);
    return 0;
}

图的存储和遍历

实验内容:

【问题描述】根据用户的输入建立一个以邻接矩阵存储的无向图,然后转换为邻接表存	储,最后进行深度优先搜索生成森林。
【基本要求】
	1.编写一个子程序创建邻接矩阵。它从键盘输入数据。
	2.编写一个子程序,将邻接矩阵转换为邻接表。
	3.通过深度优先搜索遍历该邻接表,形成的森林用二叉链表存储。
	4.用凹入法打印森林。
【测试数据】创建教材P159页无向图 G3,输出见教材171页图7.15(c)

实现思路:

1.如果邻接矩阵结构存储图的话,当图的节点较多,但边数较时浪费了存储空间。邻接表结构的话可以先用头节点链表存储所有的图的节点,每一个头节点又是以该头节点为起始节点的边的链表的起始点。每个链接表的节点结构为该节点在头节点链表中的位置,和其下一节点。图的相关存储时的关键点在于:图的头节点链表的结构和边链表的结构,头节点中要包含该节点的值和边链表的链表指针。
2.转换成邻接表存储时,在邻接表中,对图中每个顶点建立一个单链表,第i个单链表中的结点表示依附于顶点Vi的边(对有向图是以顶点Vi为尾的弧)。每个结点由3个域组成,其中邻接点域(adjvex)指示与顶点Vi邻接的点在图中的位置,链域(nextarc)指示下一条边或弧的结点;数据域(info)存储和边或弧相关的信息,如权值等。所以一开始必须先定义邻接表的边结点类型以及邻接表类型,并对邻接表进行初始化,然后根据所输入的相关信息,包括图的顶点数、边数、是否为有向,以及各条边的起点与终点序号,建立图的邻接表.由于实验要求对无向图的储存,所以对于无向图,一条边的两的个顶点,互为邻接点,所以在存储时,应向起点的单链表表头插入一边结点,即终点。同时将终点的单链表表头插入一边结点,即起点。
3.深度优先遍历可以从图的初始点出发,访问初始点,然后依次从v未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到;若此时仍有顶点未被访问到,则从另一个未被访问的顶点出发,重复上述过程,直至所有点都被访问到为止。这是一个递归的过程。所以在实现深度优先遍历的过程中必须递归调用深度优先搜索函数。而且在深度优先搜索函数中必须设一标志数组以标记结点是否被访问。
4.具体过程应为:先访问初始点Vi,并标志其已被访问。此时定义一指向边结点的指针p,并建立一个while()循环,以指针所指对象不为空为控制条件,当Vi的邻接点未被访问时,递归调用深度优先遍历函数访问之。然后将p指针指向下一个边结点。这样就可以完成图的深度优先遍历了。

实现代码:


#include <string.h>
#include <malloc.h>
#include <conio.h>
#define MAX_VERTEX_NUM 30
#define OK 1
int visited[30];
typedef int InfoType;
typedef struct ArcNode{ //弧
 int adjvex;
    struct ArcNode *nextarc;
}ArcNode;
typedef struct VNode{//表头
 int data;
    ArcNode *firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct{//图
 AdjList vertices;
    int vexnum,arcnum;
    int kind;
}ALGraph;
typedef struct QNode{
    int data;
    struct QNode *next;
}QNode,*QueuePtr;
typedef struct{
 QueuePtr front;
 QueuePtr rear;
}LinkQueue;
void CreateDG(ALGraph G){
 int k,i,v1;
    printf("\n请输入结点个数: ");
    scanf("%d",&G.vexnum);
    printf("请输入弧的个数: ");
    scanf("%d",&G.arcnum);
    for(i=1;i<=G.vexnum;i++){//初使化表头
  G.vertices[i].data=i;
     G.vertices[i].firstarc=NULL;
    }
   for(k=1;k<=G.vexnum;k++) //输入边{
    int v2;
    printf("请输入与结点%d相邻的边数:",k);
    scanf("%d",&v2);
    printf("请输入与第%d个结点相连的结点编号: ",k);
    scanf("%d",&v1);
    ArcNode *p;
    p=(ArcNode*)malloc(sizeof(ArcNode));
    if(!p) exit(-1);
    p->adjvex=v1;
    p->nextarc=NULL;
    G.vertices[k].firstarc=p;
    for(int i=1;i<v2;i++){
     int m;
     printf("请输入与第%d个结点相连的结点编号: ",k);
           scanf("%d",&m);
           ArcNode *q;
           q=(ArcNode *)malloc(sizeof(ArcNode));//动态指针
           if(!q) exit(-1);
           q->adjvex=m;  //顶点给P
     q->nextarc=NULL;
           p->nextarc=q;
        p=q;
        //free(q);
    }
       //free(p);
   }
}
void DFS (ALGraph G,int v ){//深度搜索
 visited[v]=1;
 printf("%d  ",G.vertices[v].data);
 ArcNode *x;
 x=(ArcNode*)malloc(sizeof(ArcNode));
 if(!x) exit(-1);
 x=G.vertices[v].firstarc;
 int w;
 for (;x;x=x->nextarc){
   w=x->adjvex;
  if(visited[w]==0)
   DFS(G,w);
 }
}
void DFSB (ALGraph G,int v){//深度搜索的边集
 visited[v]=1;
 ArcNode *y;
 y=(ArcNode*)malloc(sizeof(ArcNode));
 if(!y) exit(-1);
 y=G.vertices[v].firstarc;
 int u=G.vertices[v].data;
 int w;
 for(;y;y=y->nextarc){
 w=y->adjvex;
  if(visited[w]==0){
   printf("%d--->%d\n",u,w);
   DFSB(G,w);
  }
 }
}
void InitQueue (LinkQueue &Q){//建立一个空队列
 Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
 if(!Q.front) exit(-1);
 Q.front->next=NULL;
}
void EnQueue (LinkQueue &Q,int e){//进队
 QNode *p;
 p=(QNode*)malloc(sizeof(QNode));
 if(!p) exit(-1);
 p->data=e;
 p->next=NULL;
 Q.rear->next=p;
 Q.rear=p;
 //free(p);
}
int DeQueue (LinkQueue &Q,int &e){//出队
 if(Q.front==Q.rear)
  return -1;
 QNode *p;
 p=(QNode*)malloc(sizeof(QNode));
 if(!p) exit(-1);
 p=Q.front->next;
 e=p->data;
 Q.front->next=p->next;
 if(Q.rear==p)
  Q.rear=Q.front;
 free(p);
 return e;
}
int QueueEmpty (LinkQueue Q){//判断队列是否为空
 if(Q.front==Q.rear)
  return 1;
 return 0;
}
void int main(){
 int i;
 ALGraph G;
    CreateDG(G);
 int x;
 printf("请输入结点数:");
 scanf("%d",&x);
 printf("邻接表为:\n");
 for(int j=1;j<=x;j++){
  printf("%d  ",G.vertices[j].data);
  ArcNode *p;
  p=(ArcNode*)malloc(sizeof(ArcNode));
  if(!p) exit(-1);
  p=G.vertices[j].firstarc;
  while(p){
   printf("%d  ",p->adjvex);
   p=p->nextarc;
  }
  printf("\n");;
 }
 printf("请输入第一个要访问的结点序号:\n");
 int n;
 scanf("%d",&n);
    for( i=0;i<30;i++)
  visited[i]=0;
 printf("深度搜索:\n");
 DFS(G,n);
    for( i=0;i<30;i++)
  visited[i]=0;
 printf("\n");
 printf("边集:\n");
 DFSB(G,n);
 system("pause");
 return 0;
}

动态查找表的操作算法

实现内容:

【问题描述】完成二叉排序树的查找、插入和删除。
【基本要求】
	1.进行二叉排序树的结点等类型的相关定义。
	2.编写一个子程序递归地查找二叉排序树。
	3.向二叉排序树中插入元素。这个过程利用前面的查找子程序,若找到同样的关键字,则返回FALSE,否则插入该元素,并保持结果仍然是二叉排序树,返回TRUE。
	4.利用上述插入元素的算法,生成一棵二叉排序树。
	5.编写一个子程序删除二叉排序树中指定关键字的元素。e
【测试数据】
   创建教材P227页图9.7(a)中的二叉排序树。

实现思路:

1.查找思路:先查找其根节点,如果根节点的数据与key值相等,则返回该根节点,并且返回TRUE;否则, 如果key值大于根节点,则查询其右子树;如果小于根节点,则查询其左子树。
2.当二叉排序树T中不存在关键字等于key的数据元素时,插入key并返回TRUE,否则返回FALSE,递归插入。

实现代码:

#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0

/* 二叉排序树的节点结构定义 */
typedef struct BiTNode{
	int data;
	struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
int SearchBST( BiTree T, int key, BiTree f, BiTree *p ){
	/* 递归查找二叉排序树T中是否存在key */
	/* 指针f指向T的双亲,其初始调用值为NULL */
	/* 若查找成功,则指针p指向该数据元素节点,并返回TRUE */
	/* 否则指针p指向查找路径上访问的最后一个节点并返回FALSE */
	if( !T ){
		*p = f;		//这是f唯一被用到的位置。
		return FALSE;
	}else{
		if( key == T->data ){
			*p = T;		
			return TRUE; 
		}else if( key > T->data )
			return SearchBST( T->rchild, key, T, p );		/* 在右子树继续查找 */
		else
			return SearchBST( T->lchild, key, T, p );		/* 在左子树继续查找 */
		}
}
int InsertBST( BiTree *T, int key ){
	/* 当二叉排序树T中不存在关键字等于key的数据元素时 */
	/* 插入key并返回TRUE,否则返回FALSE */
	/* 未调用查找函数,递归插入 */
	if( !(*T) ){									/* 树为空, */
		(*T) = (BiTree)malloc(sizeof(BiTNode));	/* 这个位置要留心,要重新分配空间,*T为空,说明未曾分配空间 */
		(*T)->data = key;
		(*T)->lchild = (*T)->rchild = NULL;
		return TRUE;
	}
	if( key == (*T)->data )
		return FALSE;
	if( key > (*T)->data )
		return InsertBST( &((*T)->rchild), key );		/* 插入右孩子 */
	else
		return InsertBST( &((*T)->lchild), key );		/* 插入左孩子 */
}
void order(BiTree t){//中序输出
    if(t == NULL)
        return ;
    order(t->lchild);
    printf("%d ", t->data);
    order(t->rchild);
}
int DeleteBST(BiTree *T, int key){
	/* 若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素节点 */
	/* 并返回TRUE;否则返回FALSE */
	if( !(*T))
		return FALSE;	/* 不存在关键字等于key的数据元素 */
	else{
		if( key == (*T)->data )
			Delete(T);
		else if( key < (*T)->data)
			return DeleteBST(&(*T)->lchild, key);
		else
			return DeleteBST(&(*T)->rchild, key);
	}
}
int Delete(BiTree *p){
	/* 从二叉排序树中删除节点p, 并重接它的左或右子树 */
	BiTree q, s;
	if(  !(*p)->lchild && !(*p)->rchild )	/* p为叶子节点 */
		*p = NULL;
	else if( !(*p)->lchild ){	/* 左子树为空,重接右子树 */
		q = *p;
		*p = (*p)->rchild;
		free(q);
	}
	else if( !(*p)->rchild ){	/* 右子树为空,重接左子树 */
		q = *p;
		*p = (*p)->lchild;		/* 不太理解 */
		free(q);
	}
	else{						/* 左右子树均不为空 */
		q = *p;
		s = (*p)->lchild;
		while(s->rchild){		/* 转左,然后向右走到尽头*/
			q = s;
			s = s->rchild;
		}
		(*p)->data = s->data;
		if( q != *p )				/* 判断是否执行上述while循环 */
			q->rchild = s->lchild;	/* 执行上述while循环,重接右子树 */
		else
			q->lchild = s->lchild;	/* 未执行上述while循环,重接左子树 */
		free(s);
	}
	return TRUE;
}
void main(){
	int i,result,SearchNumber,DeletNumber;
	int a[10] = {3,12,24,37,45,53,61,78,90,100};
	BiTree T = NULL;
	BiTree f, *p;
	for( i = 0; i < 10; i++ )
		InsertBST(&T, a[i]);
	printf("中序遍历二叉排序树:\n");
	order(T);
	printf("\n");
	printf("请输入要查找的数字:\tresult = 1 为找到,result = 0为找不到\n");
	scanf("%d",&SearchNumber);
	result = SearchBST(T,SearchNumber,f, &p);
	printf("result = %d\n",result);
	printf("请输入要删除的数字:\n");
	scanf("%d",&DeletNumber);
	printf("删除后的中序遍历的二叉排序树为:\n");
	DeleteBST(&T,DeletNumber);
	order(T);
	printf("\n");
}
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值