大二上学期数据结构课程设计

2023-10-26

1、报数问题

问题描述:有n个小朋友围成一圈玩游戏,小朋友从1至n编号,2号小朋友坐在1号小朋友的顺时针方向,3号小朋友坐在2号小朋友的顺时针方向,……,1号小朋友坐在n号小朋友的顺时针方向。
  游戏开始,从1号小朋友开始顺时针报数,接下来每个小朋友的报数是上一个小朋友报的数加1。若一个小朋友报的数为k的倍数或其末位数(即数的个位)为k,则该小朋友被淘汰出局,不再参加以后的报数。当游戏中只剩下一个小朋友时,该小朋友获胜。
  例如,当n=5, k=2时:
  1号小朋友报数1;
  2号小朋友报数2淘汰;
  3号小朋友报数3;
  4号小朋友报数4淘汰;
  5号小朋友报数5;
  1号小朋友报数6淘汰;
  3号小朋友报数7;
  5号小朋友报数8淘汰;
  3号小朋友获胜。
  给定n和k,请问最后获胜的小朋友编号为多少?
输入格式
  输入一行,包括两个整数n和k,意义如题目所述。
输出格式
  输出一行,包含一个整数,表示获胜的小朋友编号。
样例输入
5 2
样例输出
3
样例输入
7 3
样例输出
4
数据规模和约定
对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ k ≤ 9。
要求:利用单向循环链表存储结构模拟此过程。

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef struct Node
{
    int data;
    struct Node *next;
}Node,*SNode;
void CreateNode(SNode &T,int n)//建立单向循环链表
{   Node *p;
    int i;
    T->data=1;//没有头节点
    T->next=T;
    for(i=2;i<=n;i++)
    {
        p=new Node;
        p->data=i;
        p->next=T->next;
        T->next=p;
        T=p;
    }
}
void Baoshu(SNode T,int k)
{
    int i;
    i=0;
    Node *p,*pre,*q;
    pre=new Node;
    p=new Node;
    pre=T;
    p=pre->next;
    while(p->next!=p)
    {
        i++;//记录小朋友报的数
        if(i%k==0||i%10==k)
        {   q=new Node;
            q=p;
            pre->next=p->next;
            p=q->next;
            delete q;//删除符合要求的结点

        }
        else
        {
        pre=p;
        p=p->next;
        }

    }
    printf("%d\n",p->data);
}
int main()
{   int n,k;
    SNode H;
    while(scanf("%d%d",&n,&k)!=-1)
    {   H=new Node;
        CreateNode(H,n);
        Baoshu(H,k);
    }
    return 0;
}

2、算术表达式求值

问题描述:一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。假设操作数是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、结束符“#”,如:(7+15)*(23-28/4)#。引入表达式起始、结束符是为了方便。编程利用“算符优先法”求算术表达式的值。
基本要求:从键盘读入一个合法的算术表达式,输出正确的结果;显示输入序列和栈的变化过程,操作数类型扩充到整数。

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define maxsize 1000
char oper[7] = { '+', '-', '*', '/', '(', ')', '#' };
typedef struct OPND//存储操作数栈
{
    int data;
    struct OPND *next;
}OPND,*ND;
typedef struct OPTR//存储运算符
{
    char ch;
    struct OPTR *next;
}OPTR,*TR;
void Initint(ND &s)//初始化操作数栈
{
    s=NULL;
}
void Initchar(TR &s)//初始化运算符栈
{
    s=NULL;
}
void Pushint(ND &s,int x)//操作数入栈
{
    OPND *p;
    p=new OPND;
    p->data=x;
    p->next=s;
    s=p;

}
void Pushchar(TR &s,char x)//运算符入栈
{
    OPTR *p;
    p=new OPTR;
    p->ch=x;
    p->next=s;
    s=p;
}
int Popchar(TR &S, char &e) {//运算符栈出栈 *p;
    OPTR *p;
     if (!S)
        return 0;
     e = S->ch;
     p = S;
     S = S->next;
     delete p;
     return 1;
}
int Popint(ND &S,int &e) {//操作数出栈
      OPND *p;
      if (!S)
      return 0;
      e = S->data;
      p = S;
      S = S->next;
      delete p;
      return 1;
}
int Emptyint(ND S)//判断操作数栈是否为空
{
if (!S)
return 1;
return 0;
}
int Emptychar(TR S)//判断运算符栈是否为空
{
  if (!S)
  return 1;
  return 0;
}
int GetTopint(ND S)//取操作数栈顶元素
{
    if (!S)
   return 0;
   return S->data;
}
char GetTopchar(TR S)//取运算符栈顶元素
{
    if (!S)
   return 0;
   return S->ch;
}
int In(char ch)
{
    for(int i=0;i<7;i++)
    {
        if(ch==oper[i])
        return 1;
    }
    return 0;
}
int Operate(int a,char h,int b)
{
    switch(h)
    {
        case '+': return a+b;
        case '-': return a-b;
        case '*': return a*b;
        case '/': return a/b;
    }
}
int Precede(char ch1,char ch2)
{
    if((ch1 =='('&&ch2 ==')')||(ch1=='#'&&ch2=='#'))
            return '=';
    else if(ch1=='('||ch1=='#'||ch2=='('||(ch1=='+'||ch1=='-')&&(ch2=='*'||ch2=='/'))
            return '<';
    else
            return '>';
}
int my_atoi(char *c)
{  int sum=0;
    while(*c>='0'&&*c<='9')
    {
        sum=sum*10+*c-'0';
        c++;
    }
    return sum;
}
void EvaluateExpression()
{
    ND D;
    TR R;
    Initint(D);
    Initchar(R);
    Pushchar(R,'#');
    char  c[100];
    char ch,h,x;
    int a,b,i;
    cin>>ch;
    i=0;
    while(ch!='#'||GetTopchar(R)!='#')
    {
        if(!In(ch)){c[i]=ch;cin>>ch;i++;}
        else
        {  i=0;
          if(strlen(c)!=0)
          {
           int y=my_atoi(c);
           Pushint(D,y);
           memset(c,0,sizeof(c));
          }
           switch (Precede(GetTopchar(R),ch)) //比较OPTR的栈顶元素和ch的优先级
          {
            case '<'://优先级小,ch压入OPTR栈,读入下一字符
                   Pushchar(R,ch);
                   cin>>ch;
                   break;
            case '>'://优先级大,则弹出OPTR的栈顶运算符,从OPND栈顶弹出两个数进行相应运算
                  Popchar(R,h); //弹出OPTR栈顶的运算符
                  Popint(D,a);
                  Popint(D,b); //弹出OPND栈顶的两个运算数
                  Pushint(D,Operate(b,h,a)); //将运算结果压入OPND栈
                  break;
            case '=': //OPTR的栈顶元素是“(”且ch是“)”
                  Popchar(R,x);
                  cin>>ch; //弹出OPTR栈顶的“(”,读入下一字符ch
                  break;
          }
       }
    }
    printf("输出结果为: ");
    printf("%d\n",GetTopint(D)); //OPND栈顶元素即为表达式求值结果
}

int main()
{   while(1)
     {
       cout<<"请输入要计算的表达式(以#结束):" <<endl;
       EvaluateExpression();
     }

    return 0;
}

3、二叉树的构造

任务:已知二叉树的层序和中序遍历序列,或已知二叉树的先序序列、中序序列,试编写算法建立该二叉树( 用递归或非递归的方法都可以)。
要求:能够输入树的各个结点,并能够输出用不同方法遍历的遍历序列;分别建立建立二叉树存储结构的的输入函数、输出层序遍历序列的函数、输出先序遍历序列的函数。

#include <iostream>
#include <bits/stdc++.h>
#include <windows.h>
#define maxsize 1000;
using namespace std;
typedef struct BiNode
{
    char ch;
    struct BiNode *lchild,*rchild;
}BiNode,*BiTree;
typedef struct Sq
{
    int pos;//记录当前节点在层次序列中的位置
    int low,high;//记录当前节点可能出现在中序序列中的范围
    BiTree parent;//记录当前节点的双亲节点
    int flag;//标记当前节点是左子树还是右子树。1为左,2为右
}Sq;
void LevCreateTree(BiTree &T)
{   printf("请依次输入层序遍历和中序遍历序列\n");
    Sq node[100],p;
    int rear,front;
    rear=front=0;
    char lev[100],in[100];
    gets(lev);
    gets(in);
    int n=strlen(lev);
    if(n<1) T=NULL;
    else
    {   int i,s;//i指向当前节点在中序序列中的位置,s指向当前节点在层序序列中的位置
        i=s=0;
        T=new BiNode;
        T->ch=lev[s];
        T->lchild=T->rchild=NULL;
        while(in[i]!=lev[s]) i++;//寻找当前节点在中序序列中的位置
        if(i==0&&i==n-1) return;//只有一个根节点;
        else if(i==0)//没有左子树
        {   T->lchild==NULL;
            p.pos=++s; p.low=i+1;   p.high=n-1; p.parent=T; p.flag=2;
            node[rear]=p; rear=(rear+1)%100;
        }
        else if(i==n-1)//没有右子树
        {
            T->rchild=NULL;
            p.pos=++s; p.low=0; p.high=i-1; p.parent=T; p.flag=1;
            node[rear]=p; rear=(rear+1)%100;
        }
        else
        {
             p.pos=++s; p.low=0; p.high=i-1; p.parent=T; p.flag=1;
             node[rear]=p; rear=(rear+1)%100;
             p.pos=++s; p.low=i+1;   p.high=n-1; p.parent=T; p.flag=2;
            node[rear]=p; rear=(rear+1)%100;
        }
        while(rear!=front)
        {
            p=node[front];
            front=(front+1)%100;
            BiTree parent=p.parent;
            BiNode *h=new BiNode;
            h->ch=lev[p.pos];
            h->lchild=h->rchild=NULL;
            if(p.flag==1) parent->lchild=h;
            else parent->rchild=h;
            i=p.low;
            while(in[i]!=lev[p.pos]) i++;//寻找当前节点在中序序列中的位置
            if(i==p.low&&i==p.high) //当前节点为叶子结点
            h->lchild=h->rchild=NULL;
            else if(i==p.low)//当前节点无左子树
            {
                h->lchild=NULL;
                p.pos=++s; p.low=i+1; p.parent=h; p.flag=2;
                node[rear]=p; rear=(rear+1)%100;
            }
            else if(i==p.high)//当前节点无右子树
            {
                h->rchild=NULL;
                p.pos=++s; p.high=i-1; p.parent=h; p.flag=1;
                node[rear]=p; rear=(rear+1)%100;
            }
            else
            {  int high=p.high;//记录当前high,防止右子树的high变动
               p.pos=++s; p.high=i-1; p.parent=h; p.flag=1;
               node[rear]=p; rear=(rear+1)%100;
               p.pos=++s; p.low=i+1; p.high=high; p.parent=h; p.flag=2;
               node[rear]=p; rear=(rear+1)%100;
            }

        }
    }


}
BiNode *PreCreateTree(char *pre,char *in,char n)
{
    BiNode *b;
	char *p;
	int k;
	if(n<=0) return NULL;
	b=new BiNode;
	b->ch=*pre;
  //要找到根节点在中序序列中的位置
	for(p=in;p<in+n;p++)
	{
		if(*p==*pre)
			break;
	}
	k=p-in;//统计根节点的左子树节点数
	//递归,得到每个节点的左右子树
	b->lchild=PreCreateTree(pre+1,in,k);
	b->rchild=PreCreateTree(pre+k+1,p+1,n-k-1);
	return b;
}
void Create(BiTree &root)
{   int n;
     while(1)
    {
    printf("------------请选择您的输入方式------------\n");
    printf("1.层序和中序遍历序列      2.先序和中序遍历序列\n");
    scanf("%d",&n);
    getchar();
    if(n!=1&&n!=2)
    printf("您的输入有误,请重新输入\n");
    else
    break;
    }
   Sleep(1000);
   system("cls");
   if(n==1)
    LevCreateTree(root);
    if(n==2)
    {   char pre[100],in[100];
        printf("请依次输入先序遍历和中序遍历序列\n");
        gets(pre);
        gets(in);
        int m=strlen(pre);
        root=PreCreateTree(pre,in,m);
    }

    system("cls");

}
void layerorder(BiTree T)
{
    BiTree s1[100];
    int front=0,rear=0;
    BiNode *p,*q;
    p=T;
    s1[rear]=p;
    rear=(rear+1)%maxsize;
    while(front!=rear)
    {
        q=s1[front];
        printf("%c",q->ch);
        front=(front+1)%maxsize;
        if(q->lchild!=NULL){s1[rear]=q->lchild;rear=(rear+1)%maxsize;}
        if(q->rchild!=NULL){s1[rear]=q->rchild;rear=(rear+1)%maxsize;}

    }
}
void preorder(BiTree p)
{
    if(p)
    {
        printf("%c",p->ch);
        preorder(p->lchild);
        preorder(p->rchild);
    }
}
void Choose(BiTree T)
{   int m;
    while(1)
    {
        printf("------------请选择您的输出方式------------\n");
        printf("1.层序遍历                    2.先序遍历\n");
        scanf("%d",&m);
        if(m!=1&&m!=2)
        printf("您的输入有误,请重新输入\n");
        else
        break;
    }
    Sleep(1000);
    system("cls");
    if(m==1)  {layerorder(T); printf("\n");}
    if(m==2)  {preorder(T); printf("\n");}
}
int main()
{  string s;
    while(1)
 {  printf("是否要退出程序?\n");
    cin>>s;
    if(s=="是") break;
    BiTree root;
    Create(root);
    Choose(root);
 }

    //cout << "Hello world!" << endl;
    return 0;
}

4、校园导游程序

问题描述:用无向网表示你所在学校的校园景点平面图,图中顶点表示主要景点,存放景点的编号、名称、简介等信息,图中的边表示景点间的道路,存放路径长度等信息。要求能够回答有关景点介绍、游览路径等问题。
基本要求:查询各景点的相关信息;查询图中任意两个景点间的最短路径;查询图中任意两个景点间的所有路径;增加、删除、更新有关景点和道路的信息。

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define maxsize 50  //最大地点数
typedef struct ArcNode
{
    int length;//路线长度
    string name1;//路线终点的名字
    string info;//路线终点的简介
    struct ArcNode *nextarc;//指向下一条边的指针
}ArcNode;
typedef struct VNode
{
    string name;//每个地点的名字
    string intro;//每个地点简介
    ArcNode *firstarc;//指向第一条依附该地点的路线的指针
}VNode,*AdjList[maxsize];
typedef struct
{
    VNode vertices[maxsize];
    int vexnum,arcnum;
}ALGragh;
int LocateVex(ALGragh G,string v)
{   int i,flag;
    flag=0;
    for(i=1;i<=G.vexnum;i++)
    {
        if(G.vertices[i].name==v)
        {
            flag=1;
            return i;
        }
    }
    if(flag==0)
    return -1;
}

int adj[maxsize][maxsize];//初始矩阵,根据这个矩阵建立初始领接表
int we[maxsize][maxsize];//初始权值
void Init(ALGragh &G)//建立初始无向图
{   int i,j;
    memset(adj,0,sizeof(adj));
    //初始化领接矩阵和对应路径权值
   adj[1][2]=1;adj[1][3]=1;adj[2][4]=1;adj[2][7]=1;adj[8][9]=1;
   adj[3][10]=1;adj[4][5]=1;adj[5][6]=1;adj[6][7]=1;adj[7][8]=1;adj[10][9]=1;
   we[1][2]=105;we[1][3]=200;we[2][4]=50;we[2][7]=170;we[8][9]=50;
   we[3][10]=190;we[4][5]=220;we[5][6]=178;we[6][7]=97;we[7][8]=350;we[10][9]=189;
    G.vexnum=10;
    G.arcnum=14;
    G.vertices[1].name="行政楼";G.vertices[1].intro="行政人员办公处";
    G.vertices[2].name="食堂";G.vertices[2].intro="老食堂";
    G.vertices[3].name="赛博楼";G.vertices[3].intro="信息分院办公室所在地";
    G.vertices[4].name="求是楼";G.vertices[4].intro="实验楼计算机中心";
    G.vertices[5].name="格致楼";G.vertices[5].intro="法学管理学院";
    G.vertices[6].name="工程实习中心";G.vertices[6].intro="金工实习";
    G.vertices[7].name="仰仪楼";G.vertices[7].intro="机电计测分院";
    G.vertices[8].name="体育馆";G.vertices[8].intro="旁边有篮球场,足球场,还有网球场";
    G.vertices[9].name="一号教学楼";G.vertices[9].intro="主要以阶梯教室为主";
    G.vertices[10].name="二号教学楼";G.vertices[10].intro="小教室为多";
    for(i=1;i<maxsize;i++)
    G.vertices[i].firstarc=NULL;
    for(i=1;i<maxsize;i++)
    {
        for(j=1;j<maxsize;j++)
        {
            if(adj[i][j]==1)
            {
                ArcNode *p1=new ArcNode;
                p1->info=G.vertices[j].intro;
                p1->name1=G.vertices[j].name;
                p1->length=we[i][j];
                p1->nextarc=G.vertices[i].firstarc;
                G.vertices[i].firstarc=p1;

                ArcNode *p2=new ArcNode;
                p2->info=G.vertices[i].intro;
                p2->name1=G.vertices[i].name;
                p2->length=we[i][j];
                p2->nextarc=G.vertices[j].firstarc;
                G.vertices[j].firstarc=p2;

            }
        }
    }

}
int Operation(ALGragh &G,int m)
{   int n,k,l,i,flag1,flag2;
    flag1=0;
    flag2=0;
    //char v1[100],v2[100],v3[100],v4[100];
    string v1,v2,v3,v4;
    switch(m){
            case 1:{

                printf("请输入要添加的地点名称\n");//getchar();
                cin>>v1;//getchar();
                for(i=1;i<G.vexnum;i++)
                {
                    if(G.vertices[i].name==v1)
                    {printf("该地点已经存在\n");flag1=1;break;}
                }
                if(flag1==0)
                {
                G.vexnum++;
                G.vertices[G.vexnum].name=v1;
                printf("请输入改地点简介\n");//getchar();
                cin>>v2;//getchar();
                G.vertices[G.vexnum].intro=v2;
                printf("请输入与该地点直接相连的地点总数\n");//getchar();
                scanf("%d",&n);//getchar();
                printf("请输入与该地点直接相连的所有地点名称以及两地之间路程\n");//getchar();
                for(int i=1;i<=n;i++)
                {   cin>>v3>>l;
                    k=LocateVex(G,v3);
                    ArcNode *q1=new ArcNode;
                    q1->name1=v3;
                    q1->info=G.vertices[k].intro;
                    q1->length=l;
                    q1->nextarc=G.vertices[G.vexnum].firstarc;
                    G.vertices[G.vexnum].firstarc=q1;

                   ArcNode *p2=new ArcNode;
                  p2->info=G.vertices[G.vexnum].intro;
                  p2->name1=G.vertices[G.vexnum].name;
                  p2->length=l;
                  p2->nextarc=G.vertices[k].firstarc;
                  G.vertices[k].firstarc=p2;
                  }
                printf("已完成更新\n");
                }

            }
            case 2:
            {
                printf("请输入要删除的地点名称\n");
                cin>>v4;//
                for(i=1;i<G.vexnum;i++)
                {
                    if(G.vertices[i].name==v4)
                    {flag2=1;break;}
                }
                if(flag2==0)
                printf("该地点不存在\n");
                if(flag2==1)
                {
                k=LocateVex(G,v4);
                for(i=k;i<G.vexnum;i++)
                G.vertices[i]=G.vertices[i+1];
                G.vexnum--;
                for(i=1;i<=G.vexnum;i++)
                {
                    ArcNode *p=new ArcNode;
                    ArcNode *pre=new ArcNode;
                    pre=G.vertices[i].firstarc;
                    p=pre->nextarc;
                    if(pre->name1==v4){G.vertices[i].firstarc=p; delete pre;}
                    else
                    {
                        while(p!=NULL)
                       {
                        if(p->name1==v4){pre->nextarc=p->nextarc;delete p; break;}
                        pre=p;
                        p=p->nextarc;


                       }
                    }

                  }
                printf("已完成更新\n");
                }

            }
    }//switch
    return 0;
}
int visited[maxsize+1];//记录节点是否在栈内
int path[maxsize][maxsize];//记录直接相连的的结点是否被访问过
int path_record[maxsize];//使用数组栈记录路径
int path_min[maxsize];//记录最短路径
int min1;//标识当前最短路径长度
int min2;//表示当前最短路径所含结点个数
int g_idx;//标识当前栈顶位置
ArcNode *neighbour(ALGragh G,int x)//寻找可用结点
/*可用结点的要求为:1.不在栈内
                  2.没有被当前结点直接访问过*/
{
    ArcNode *q;
    q=G.vertices[x].firstarc;
    while(q!=NULL)
    {
        if(path[x][LocateVex(G,q->name1)]!=1&&visited[LocateVex(G,q->name1)]!=1)
        {
        return q;
        }
        q=q->nextarc;
     }
     if(q==NULL)return q;

}
void Findpath(ALGragh G,int u,int v)
{

    int i,vex;
    ArcNode *p;
    min1=999999;
    min2=0;
    while(g_idx>=0)
    {
        vex=path_record[g_idx];//记录当前栈顶节点
        if(vex==v)//已经走到结束节点,即已经找到路径,就输出完整路径
        {  int sum=0;
            for(i=0;i<=g_idx;i++)
            {
                cout<<G.vertices[path_record[i]].name<<" ";
                if(i>=0&&i<g_idx)
                {
                  ArcNode *s=new ArcNode;
                  s=G.vertices[path_record[i]].firstarc;
                  while(s!=NULL)
                  {
                      if(s->name1==G.vertices[path_record[i+1]].name)
                      {sum+=s->length;break;}
                      s=s->nextarc;
                  }

                }


            }
            printf("这条路径长度为: %d",sum);
            if(sum<min1)
            {
            min1=sum;
            for(i=0;i<=g_idx;i++)
            path_min[i]=path_record[i];
            min2=g_idx;
            }
            printf("\n");
            //最后一个节点出栈
            visited[v]=0;
            for(i=0;i<maxsize;i++)
            path[v][i]=0;
            path_record[g_idx]=-1;
            g_idx--;
        }
        else
        {
          p=neighbour(G,vex);//查找与当前结点连接的可用结点
          if(p!=NULL) //如果有可用节点,该节点入栈
          {
              path[vex][LocateVex(G,p->name1)]=1;
              g_idx++;
              path_record[g_idx]=LocateVex(G,p->name1);
              visited[LocateVex(G,p->name1)]=1;
          }
          else  //没有可用结点,当前节点出栈,与该结点直接相连的结点标记为未访问
          {
              visited[vex]=0;
              for(i=0;i<maxsize;i++)
              path[vex][i]=0;
              path_record[g_idx]=-1;
              g_idx--;
          }
        }
    }

}
int Update(ALGragh &G)
{   int x;
    printf("1.添加地点        2.删除地点\n");
    scanf("%d",&x);//getchar();
    Operation(G,x);//对无向图进行更新*/
    system("pause");
    system("cls");
    return 0;
}
int Find(ALGragh G)
{   int x,u,v,i;
    string v1,v2;
    printf("请输入起点和终点名称\n");
    cin>>v1>>v2;
    u=LocateVex(G,v1);
    v=LocateVex(G,v2);//对起点和终点定位
    memset(visited,0,sizeof(visited));
    memset(path,0,sizeof(path));
    memset(path_min,0,sizeof(path_min));//对所有相关数组进行初始化,避免下次寻找路线时数据不对等
    for(i=0;i<=G.vexnum;i++)
    path_record[i]=-1;
    g_idx=0;
    //起始点入栈
    path_record[g_idx]=u;
    visited[u]=1;
    Findpath(G,u,v);
    printf("其中最短路径为: ");
    for(i=0;i<=min2;i++)
    cout<<G.vertices[path_min[i]].name<<" ";
    printf("\n");
    printf("最短路径长度为: %d\n",min1);
    system("pause");
    system("cls");
    return 0;
}
int main()
{
    ALGragh G;
    int y;
    Init(G);//建立初始无向图
    while(1)
    {
      printf("请选择您要进行的操作\n");
      printf("1.更新地图        2.寻找路线         3.退出程序\n");
      scanf("%d",&y);
      system("pause");
      system("cls");
      switch(y)
      {
        case 1:
            {Update(G);break;}//更新地图
        case 2:
            {Find(G);break;}//寻找路线
      }
      if(y==3)break;
    }
    return 0;
}

5、二叉排序树与文件操作

功能要求:
(1)从键盘输入一组学生记录建立二叉排序树;
(2)中序遍历二叉排序树;
(3)求二叉排序树深度;
(4)求二叉排序树的所有节点数和叶子节点数;
(5)向二叉排序树插入一条学生记录;
(6)从二叉排序树中删除一条学生记录;
(7)从二叉排序树中查询一条学生记录;
(8)以广义表的形式输出二叉排序树

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef struct Student
{
    int data;
    string name;
    double score[5];
}StuNode;
typedef struct BSTNode
{
    StuNode info;
    struct BSTNode *lchild,*rchild;

}BSTNode,*BSTree;
void InsertBST(BSTree &T,StuNode S)
{
    if(!T)//T为空,即找到了插入位置
    {
        BSTNode *p=new BSTNode;
        p->info=S;
        p->lchild=p->rchild=NULL;
        T=p;
    }
    else if(S.data<T->info.data) InsertBST(T->lchild,S);
    else if(S.data>T->info.data) InsertBST(T->rchild,S);
}

int CreatBST(BSTree &T)
{   StuNode s;
    printf("请输入您要插入的学生信息,学生信息包括学号,姓名,各科成绩,中间用空格隔开,并以0结尾\n");
   // ofstream fout("bst.txt");
    cin>>s.data;
    int i=0;
    while(s.data!=0)
    {
        cin>>s.name>>s.score[0]>>s.score[1]>>s.score[2];
        InsertBST(T,s);//
        cin>>s.data;
    }
    return 0 ;
}
void InOderTraverse(BSTree T)
{
    if(T)
    {
        InOderTraverse(T->lchild);
        cout<<T->info.data<<" "<<T->info.name<<" "<<T->info.score[0]<<" "<<T->info.score[1]<<" "<<T->info.score[2]<<endl;
        InOderTraverse(T->rchild);
    }
}
int DepthBST(BSTree T)
{
    if(T==NULL) return 0;
    else
    {
        int l=DepthBST(T->lchild);
        int r=DepthBST(T->rchild);
        if(l>r)return l+1;
        else return r+1;
    }

}
int Count(BSTree T)
{
    if(T==NULL) return 0;
    else return Count(T->lchild)+Count(T->rchild)+1;
}
int Leaves(BSTree T)
{
    if(T==NULL) return 0;
    else if(T->lchild==NULL&&T->rchild==NULL)return 1;
    else return Leaves(T->lchild)+Leaves(T->rchild);
}
BSTree SearchBST(BSTree T,int x)
{
    if((!T)||x==T->info.data) return T;
    else if(x<T->info.data) return SearchBST(T->lchild,x);
    else return SearchBST(T->rchild,x);
}
void DeleteBST(BSTree &T,int x)
{
    BSTNode *p,*f,*q,*s;
    p=T,f=NULL;
    //while循环从根开始查找关键字为x的结点
    while(p)
   {
       if(p->info.data==x)break;
       f=p;//f记录p的双亲结点
       if(p->info.data>x)p=p->lchild;
       else p=p->rchild;
   }
   if(!p)  return ;//找不到相关结点
   q=p;
   if((p->lchild)&&(p->rchild))//被删除结点左右子树均不空
   //这种情况下不必执行最后的if语句
   {   //在p结点的左子树中查找最右结点
       s=p->lchild;
       while(s->rchild)
       {
           q=s;//q为s的双亲结点
           s=s->rchild;
       }
       p->info=s->info;
       if(q!=p)q->rchild=s->lchild;
       else q->lchild=s->lchild;
       delete s;
       return ;
   }
   else if(!p->lchild)//p的左子树为空
   {
       p=p->rchild;//p的右子树上移
   }
   else if(!p->rchild)
    {
        p=p->lchild;//p的左子树上移
    }
    //把P及其子树挂到f的相应位置
    if(!f)T=p;//要删除的节点为根节点
    else if(q==f->lchild)f->lchild=p;
    else f->rchild=p;
    delete q;
}
void Order_save(BSTree T,int data[],string name[],double score1[],double score2[],double score3[])
{
    static int m=0;
    if(T)
    {

        Order_save(T->lchild,data,name,score1,score2,score3);
        data[m]=T->info.data;
        name[m]=T->info.name;
        score1[m]=T->info.score[0];
        score2[m]=T->info.score[1];
        score3[m]=T->info.score[2];
        m++;
        Order_save(T->rchild,data,name,score1,score2,score3);
    }
}
void Guangyibiao(BSTree T)
{
    cout<<T->info.data<<" "<<T->info.name<<" "<<T->info.score[0]<<" "<<T->info.score[1]<<" "<<T->info.score[2];
    if(T->lchild!=NULL)
    {
        cout<<"(";Guangyibiao(T->lchild);
        if(T->rchild==NULL) cout<<")";
    }
    if(T->rchild!=NULL)
    {
        if(T->lchild==NULL) cout<<"(";
        cout<<",";
        Guangyibiao(T->rchild);
        cout<<")";
    }
}
int main()
{   BSTree T;
    int depth,sum,leaf,x,y,i,m,data1;
    int data[1000];
    string name[1000],name1;
    double score1[1000],score2[1000],score3[1000],s1,s2,s3;
    BSTNode *p;
    T=NULL;
    while(1)
    {
        printf("----------------------------------------------------------------------------------------------------------------\n");
        printf("                                    欢迎使用学生信息管理系统      \n");
        printf("                                    请选择您要进行的操作\n");
        printf("----------------------------------------------------------------------------------------------------------------\n");
        printf("1.输入学生信息        2.查找学生信息       3.删除学生信息       4.查询当前学生总数        5.输出所有学生信息       6.查询当前二叉排序树叶子结点数\n");
        printf("7.查询当前二叉排序树的深度                 8.二叉树存盘         9.广义表输出              10.退出程序\n");
        cin>>x;

        switch(x)
        {
            case 1: //建立二叉排序树
                  {
                    CreatBST(T);
                    system("pause");
                    system("cls");
                    break;
                }
            case 2: //查找学生信息
                 {
                     printf("请输入您要查找的学生学号\n");
                     cin>>y;
                     p=SearchBST(T,y);
                     cout<<p->info.data<<" "<<p->info.name<<" "<<p->info.score[0]<<" "<<p->info.score[1]<<" "<<p->info.score[2];
                     system("pause");
                     system("cls");
                     break;
                 }
           case 3://删除一条学生记录
           {
               printf("请输入您要删除的学生学号\n");
               cin>>y;
               DeleteBST(T,y);
                system("pause");
                system("cls");
               break;
           }
           case 4://求二叉排序树的所有节点数
           {
               sum=Count(T);
               printf("%d\n",sum);
               system("pause");
              system("cls");
               break;

           }
           case 5: //中序遍历二叉树
                 {
                     InOderTraverse(T);
                      system("pause");
                      system("cls");
                     break;
                }
           case 6://求二叉排序树的叶子结点数
                 {leaf=Leaves(T);
                 printf("%d\n",leaf);
                  system("pause");
                 system("cls");
                 break;
                 }

          case 7:  //求二叉排序树深度
               {
               depth=DepthBST(T);
               printf("%d\n",depth);
                system("pause");
               system("cls");
               break;
               }

          case 8:
                {   m=Count(T);
                    ofstream fout("bst.txt");
                    Order_save(T,data,name,score1,score2,score3);
                    for(i=0;i<m;i++)
                    fout<<data[i]<<" "<<name[i]<<" "<<score1[i]<<" "<<score2[i]<<" "<<score3[i]<<endl;
                    fout.close();
                    printf("从文件中读取的结果为:\n");
                    ifstream fin("bst.txt");
                    for(i=0;i<m;i++)
                    {
                        fin>>data1>>name1>>s1>>s2>>s3;
                        cout<<data1<<" "<<name1<<" "<<s1<<" "<<s2<<" "<<s3<<endl;

                    }
                    fin.close();
                    break;

                }
          case 9:
                {
                    Guangyibiao(T);
                    system("pause");
                    system("cls");
                   break;
                }
          case 10:
                break;
          default:
          {
              printf("您的输入有误,请重新输入\n");
              system("pause");
              system("cls");
              break;
          }

        }
        if(x==10)break;
    }
    //插入一条学生记录
   //InsertBST(T,p);
    return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

大二上学期数据结构课程设计 的相关文章