大二上---数据结构课程设计

课程设计

本次课设共五道题,通过查资料完成
(一)线性结构(链表)题目
joseph环

任务:编号是1,2,…,n的n个人按照顺时针方向围坐一圈,每个人只有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个仍开始顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。设计一个程序来求出出列顺序。
要求:利用单向循环链表存储结构模拟此过程,按照出列的顺序输出各个人的编号。
测试数据:m的初值为20,n=7 ,7个人的密码依次为3,1,7,2,4,7,4,首先m=6,则正确的输出是什么?
要求:输入数据:建立输入处理输入数据,输入m的初值,n ,输入每个人的密码,建立单循环链表。
输出形式:建立一个输出函数,将正确的输出序列
数据结构:
typedef struct Node
{
int data;
int password;
struct Node *next;
}Node, *LinkList;
基本操作:初始化单链表;给每个人赋密码;确定需要处理的人数;确定开始的上限值;得到正确的顺序;输出结果。

#include<bits/stdc++.h>
using namespace std;
int de ;           //记录被删除节点的数据,全局变量
typedef struct LNode
{
    int data;                    //序号
    int password;                   //密码
    struct LNode  *next;
}LNode,*LinkList;
LinkList IniList()
{
    LinkList head;
    head = (LinkList) malloc (sizeof(LNode));
    head->next = NULL;
    return head;
}
LinkList CreatList(int a[],int n){
    LinkList head = IniList();      //建立空链表,初始化
    LinkList r = head;
    int i=0;                        //r为链表的末端
    for(i=0;i<n;i++)
    {
        LinkList q = (LinkList) malloc (sizeof(LNode)); //创建新结点
        q->data = i+1;
        q->password = a[i];          //建立新节点,准备作尾结点
        r->next = q;                 //连接结点
        r = q;              //更新r,保持在尾结点,尾插
    }
    r->next = head->next;     //使链表为单向循环链表
    return head;
}
LinkList LinkDelete(LinkList m,int i){   //m为开始者前一结点,i为开始者的密码
    LinkList p,q;
    p = m;
    int j;
    for(j=0;j<i-1;j++)   p = p->next;     //p指向将被删除结点的上一结点
    q = p->next;
    p->next = q->next;            //删除并释放结点
    printf("%d出列\n",q->data);
    de = q->password;
    free(q);
    return p;                   //返回下一开始者前一结点
}
int StartGame(LinkList L,int n,int first_m){
    LinkList q = L;             //q为开始者前一位标记
    while(n-1){             //游戏剩下人数不为1
        q = LinkDelete(q,de);   //删除该轮被抽中者
        n--;
    }
    return q->data;//输出最后一个人
}
int main(){
    int p[30],n=0,ch,first_m;           //p数组存储密码
    LinkList head;
    printf("----------------Joseph环----------------\n");
    printf("请输入初始m值:");
    scanf("%d",&de);
    printf("请依次输入游戏者密码,以任意字符结束:");
    while(scanf("%d",&p[n++]));//n记录人数
    printf("---------------\n");
    head = CreatList(p,n-1);               //创建链表
    printf("%d出列\n",StartGame(head,n-1,de));    //开始游戏
    printf("----------------游戏结束----------------\n");
    return 0;
}
/*
m=20
3,1,7,2,4,7,4
6,7,4,1,5,3,2
*/

(二)栈和队列题目
停车场管理

设停车场(如下图1所示)内只有一个可停放几量汽车的狭长通道,且只有一个大门可供汽车进出。汽车在停车场内按车辆到达时的先后顺序,依次由北向南排列(大门在最南端,最先到达的第一辆车停放在车场的最北端),若车场内已经停满几量汽车,则后来的汽车只能在门外的便道上等候,一旦停车场内有车开走,则排在便道上的第一辆汽车即可开入;当停车场内某车辆要离开时,由于停车场是狭长的通道,在它之后开入车场的车辆必须先退出车场为它让路,待该车辆开出大门外后,为它让路的车辆再按原次序进入车场。在这里假设汽车不能从便道上开走。试设计一个停车场管理程序(这里只是一个假想的停车场管理,并不代表实际的停车场管理)。

分析:汽车在停车场内进出是按照栈的运算方式来实现的,先到的先进停车场;停车场的汽车离开停车场时,汽车场内其它汽车为该辆汽车让路,也是按栈的方式进行;汽车在便道上等候是按队列的方式进行的。因此,将停车场设计成一个栈,汽车让路也需要另一个栈来协助完成,汽车进出便道用队列来实现。
本设计,栈采用顺序栈结构,队列用链式存储结构。
存储结构定义如下:
#define stacksize 10
typedef struct sqstack
{
int data[stacksize];
int top;
} SqStackTp;
typedef struct linked_queue
{
int data;
struct linked_queue * next;
}LqueueTp;
typedef struct
{
LqueueTp *front , *rear ;
} QueptrTp;
停车场管理的算法描述如下:
1)接受命令和车号,若是汽车要进停车场,先判断停车场栈是否满,若不满,则汽车入栈,否则汽车进入便道队列等候。
2)若是汽车要离开停车场,为给汽车让路,将停车场栈上若干辆汽车入临时栈,等这辆车出停车场后,临时栈中的汽车出栈,在回到停车场栈,然后看便道队列是否为空,若不空则说明有汽车等候,从队头取出汽车号,让该车进入停车场栈。
3)重复1),2)直到为退出命令(车号为0或负数)。

#include<stdio.h>
#include<stdlib.h>
#define N 3 //停车场总共位置
#define M 3 //通道总共位置
//车子
typedef struct Car{
    int num;
}Car;
typedef struct stack{
    Car *base;
    Car *top;
    int sum;
}Park,Tmp;
typedef struct  linked_queue
{
  Car car;
  struct  linked_queue  * next;
}LqueueTp;
typedef  struct queue
{
  LqueueTp  *front ,  *rear ;
  int sum;
} QueptrTp;
QueptrTp line; //通道 全局变量
Park park; //停车场
Tmp tmp; //临时让路道
//初始化停车场
void InitPark(){
    park.base=(Car *)malloc(sizeof(Car)*N);
    park.top=park.base;
    park.sum=0;
}
//初始化临时让路道
void InitTmp(){
    tmp.base=(Car *)malloc(sizeof(Car)*M);
    tmp.top=tmp.base;
    tmp.sum=0;
}
//初始化通道
void InitLine(){
    line.front=(LqueueTp *)malloc(sizeof(LqueueTp));
    line.front->next=NULL;
    line.rear=line.front;
    line.sum=0;
}

//车子进停车场
void InPark(Car e){
    *(park.top)=e;
    park.top++;
    park.sum++;//记录停车场内有多少车
    printf("车辆%d停放在停车场第%d个位置.\n",e.num,park.sum);
}

//车子进通道line(链队列)
void InLine(Car e){
    LqueueTp *s=(LqueueTp*)malloc(sizeof(LqueueTp));
    s->car=e;
    s->next=NULL;
    line.rear->next=s;
    line.rear=s;//尾插
    line.sum++;
    printf("车辆停放在通道第%d个位置.\n",line.sum);
}

//车子进去临时让路道栈
void InTmp(Car e){
    *(tmp.top)=e;
    tmp.top++;
    tmp.sum++;
}

//出栈操作
void OutStack(stack *s){
    s->top--;
    s->sum--;
}

//通道链队列的第一辆车即队头元素
Car OutLine(){
    LqueueTp *firstqnode=line.front->next;
    Car firstcar=firstqnode->car;
    line.front->next=firstqnode->next;
    line.sum--;
    return firstcar;
}

//车子出停车场
void OutPark(Car e){
    int num=e.num;
    Car *c=park.top-1; //栈顶元素
    while(c->num!=num&&park.top>park.base){
        InTmp(*c); //栈顶元素进临时让路道
        OutStack(&park); //栈顶元素出去
        c--;
    }
    if(park.top==park.base) {
        printf("停车场无此车.\n");
    }
    else{
        OutStack(&park); //车子出停车场
    }
    while(tmp.sum>0){
        OutStack(&tmp);
        InPark(*(tmp.top));
    }

    //让通道里的队头进停车场
    while(park.sum<N&&line.sum>0){
        Car linefirstcar=OutLine();
        InPark(linefirstcar);
    }
}

void DisPark(){
    printf("停车场:\n");
    Car *p=park.base;
    while(p!=park.top){
        printf("车辆:%d\n",p->num);
        p++;
    }
}
void DisLine(){
    printf("通道:\n");
    LqueueTp *p=line.front->next;
    while(p){
        printf("车辆:%d\n",(p->car).num);
        p=p->next;
    }
}

int main(){
    InitPark();
    InitTmp();
    InitLine();
    int flag=0;
    while(flag!=5)
    {
        printf("1.汽车停放-------");
        printf("2.汽车离开-------");
        printf("3.查看停车场-------");
        printf("4.查看通道-------");
        printf("5.退出--\n");
        printf("请输入:");
        scanf("%d",&flag);
        switch(flag){
        case 1:{
                printf("请输入车牌号:");
                Car car;
                scanf("%d",&car.num);
                if(park.sum<N)//判断停车场是否满
                    InPark(car);
                else if(line.sum<M)//判断便道是否满
                    InLine(car);
                else
                    printf("不好意思,无空地!\n");
                break;
               }
        case 2:{
                printf("输入车牌号:");
                Car car;
                scanf("%d",&car.num);
                OutPark(car);
                break;
               }
        case 3:{
                DisPark();
                break;
               }
        case 4:{
                DisLine();
                break;
               }
        case 5:{
                break;
               }
        default:
                printf("输入有误!\n");
        }
    }
    return 0;
}

(三)树型结构题目
哈夫曼编/译码器

任务:建立最优二叉树函数。
要求:可以建立函数输入二叉树,并输出其哈夫曼树。
在上交资料中请写明:存储结构、基本算法(可以使用程序流程图)、输入输出、源程序、测试数据和结果、算法的时间复杂度、另外可以提出算法的改进方法;
利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼码的编/译码系统。
一个完整的系统应具有以下功能:
(1)I:初始化(Initialization)。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
(2)E:编码(Encoding)。利用已建好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
(3)D:译码(Decoding)。利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
(4)P:印代码文件(Print)。将文件CodeFile以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件CodePrin中。
(5)T:印哈夫曼树(Tree printing)。将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
#define MAXVALUE 10000
#include<iostream>
using namespace std;
typedef struct
{
    int weight;
    int flag;
    int parent;
    char ch;
    int lchild;
    int rchild;
}HafNode;

typedef struct
{
    int bit[MAX];
    int start;
    int weight;
    char ch;
}Code;

typedef struct
{
    char bit[MAX];
    char ch;
    int weight;
}Coding;

void haffman(int weight[],char ch[],int n,HafNode haffTree[])  //生成哈夫曼树的函数
{
    int i,j,m1,m2,x1,x2;
    for (i=0;i<2*n-1;i++)//n输入字符个数
    {
       if(i<n)
       {
           haffTree[i].weight=weight[i];
           haffTree[i].ch=ch[i];//先存成完全二叉树
       }
       else//剩余节点为空
       haffTree[i].weight=0;
       haffTree[i].parent=-1;
       haffTree[i].flag=0;
       haffTree[i].lchild=-1;
       haffTree[i].rchild=-1;
    }
    for (i=0;i<n-1;i++)
    {
       m1=m2=MAXVALUE;//最小和次小
       x1=x2=0;
       for (j=0;j<n+i;j++)
       {
           if (haffTree[j].weight<m1&&haffTree[j].flag==0)
           {
              m2=m1;
              x2=x1;
              m1=haffTree[j].weight;
              x1=j;
           }
           else if(haffTree[j].weight<m2 && haffTree[j].flag==0)
           {
              m2=haffTree[j].weight;
              x2=j;
           }
       }
       haffTree[x1].parent= n + i;
       haffTree[x2].parent = n + i;
       haffTree[x1].flag = 1;
       haffTree[x2].flag = 1;
       haffTree[n+i].weight = haffTree[x1].weight + haffTree[x2].weight;
       haffTree[n+i].lchild = x1;
       haffTree[n+i].rchild = x2;//左边比右边小
    }
    FILE *fp;
    fp=fopen("huffman.txt","w+");
    printf("%d\n",n);
    fprintf(fp,"%d\n",n);
    for (i=0;i<n;i++)//字符和孩子信息
       fprintf(fp,"%c %d %d %d\n",haffTree[i].ch,haffTree[i].parent,haffTree[i].lchild,haffTree[i].rchild);
    for (i=n;i<2*n-1;i++)//非叶子节点信息
       fprintf(fp,"%d %d %d\n",haffTree[i].parent,haffTree[i].lchild,haffTree[i].rchild);
    fclose(fp);
}

void HaffmanCode (HafNode haffTree[],int n,Code haffCode[])/*生成哈夫曼编码的函数*/
{
    Code *cd=( Code *) malloc (sizeof (Code));
    int i,j,child,parent;
    for (i=0; i<n; i++)
    {
       cd->start=n-1;
       cd->weight=haffTree[i].weight;
       cd->ch=haffTree[i].ch;
       child=i;
       parent=haffTree[child].parent;
       while (parent !=-1)
       {
           if (haffTree[parent].lchild==child)
              cd->bit[cd->start]=0;
           else
              cd->bit[cd->start]=1;
           cd->start--;
           child =parent;
           parent=haffTree[child].parent;
       }
       for (j=cd->start+1; j<n; j++)
           haffCode[i].bit[j]=cd->bit[j];
       haffCode [i].start = cd->start+1;
       haffCode [i].weight=cd->weight;
       haffCode [i].ch=cd->ch;
    }
}

void Init(int weight[],char ch[])       //初始化操作,生成哈夫曼树及哈夫曼编码
{
    FILE *fp;
    int i,j,n;
    char ch1,wj[15];
    printf("进行初始化操作,按A开始从键盘输入数据\n");
    scanf("%c",&ch1);
    if (ch1=='A')
    {
       printf("输入字符集大小n:\n");
       scanf("%d",&n);
    }
    HafNode *myHaffTree=(HafNode *)malloc(sizeof (HafNode)*(2*n+1));
    Code *myHaffCode =(Code *)malloc (sizeof (Code)*n);
    for (i=0;i<n;i++)
    {
       if (ch1=='A')
       {
           printf("请输入字符和权值:\n");
           scanf("%s %d",&ch[i],&weight[i]);
       }
    }
    haffman(weight,ch,n,myHaffTree);
    HaffmanCode(myHaffTree,n,myHaffCode);
    fp=fopen("hfmTree.txt","w+");
    for (i=0;i<n;i++)
    {
       printf("%c %d ",myHaffCode[i].ch,myHaffCode[i].weight);
       fprintf(fp,"%c %d ",myHaffCode[i].ch,myHaffCode[i].weight);
        for ( j=myHaffCode[i].start; j<n; j++)
       {
           printf("%d",myHaffCode[i].bit[j]);
           fprintf(fp,"%d",myHaffCode[i].bit[j]);
       }
            fprintf(fp,"\n");
       printf("\n");
    }
    fclose(fp);
    printf("初始化成功!\n");
}

void bianma()     //哈夫曼编码过程的函数,用于将文件编码
{
    FILE *fp,*fp1,*fp2;
    char zf[500];
    fp=fopen("hfmTree.txt","r");
    Coding ch[100];
    char c;
    int i=0;
    while (feof(fp)==0)
    {
           fscanf(fp,"%s %d %s",&ch[i].ch,&ch[i].weight,&ch[i].bit);
            i++;
   }
    fclose(fp);
    printf("现在进行编码操作\n请选择:\nA.键盘输入            B.文件输入\n");
    scanf("%s",&c);
    if (c=='A')
    {

       printf("请输入字符串:\n");
       scanf("%s",&zf);
    }
    char ch1[20],ch2[20];
    int j;
    if (c=='B')
    {
       printf("正文的文件名:ToBeTran.txt\n");
       fp1=fopen("ToBeTran.txt","r");
    }
       printf("将结果保存到文件:CodeFile.txt中\n");
       fp2=fopen("CodeFile.txt","w+");
       if (c=='A')
       {
           int len,k;
           len=strlen(zf);
           for (k=0;k<len;k++)
              for (j=0;j<i;j++)
                  if (ch[j].ch==zf[k])
                  {
                     fprintf(fp2,"%s",ch[j].bit);
                     printf("%s",ch[j].bit);
                  }
                     printf("\n");
       }
       if (c=='B')
       {
           while(feof(fp1)==0)
           {
              fscanf(fp1,"%c",&c);
              for (j=0;j<i;j++)           //对文件中的每一个字符进行编码
                  if (ch[j].ch==c)
                  {
                     fprintf(fp2,"%s",ch[j].bit);
                     printf("%s",ch[j].bit);
                  }
           }
           fprintf(fp2,"\n");
           printf("\n");
           fclose(fp1);
       }
       fclose(fp2);
       printf("编码完成,已将结果存入CodeFile.txt中.\n\n");
}

void yima()               //译码操作
{
    FILE *fp,*fp1;
    fp=fopen("huffman.txt","r");
    int i,n;
    fscanf(fp,"%d",&n);
    HafNode *myHaffTree=(HafNode *)malloc(sizeof (HafNode)*(2*n+1));
    for (i=0;i<n;i++)
        fscanf(fp,"%s %d %d %d\n",&myHaffTree[i].ch,&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);
    for (i=n;i<2*n-1;i++)
       fscanf(fp,"%d %d %d\n",&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);
    fclose(fp);
    printf("译码文件的文件名:CodeFile.txt\n");
    printf("结果文件的文件名:TextFile.txt\n");
    fp=fopen("CodeFile.txt","r");
    fp1=fopen("TextFile.txt","w+");
    char ch;
    i=2*n-2;
     //getc(fp);
    while (!feof(fp))
    {
        fscanf(fp,"%ch",&ch);
       if (ch=='0')                    //若编码为0,则找此结点的左孩子;
           i=myHaffTree[i].lchild;
       if (ch=='1')                    //若编码为1,则找此结点的右孩子; 
           i=myHaffTree[i].rchild;
       if(myHaffTree[i].rchild==-1)
       {
           cout<<myHaffTree[i].ch;
           fprintf(fp1,"%c",myHaffTree[i].ch);
           i=2*n-2;
       }
    }
    printf("\n");
    fprintf(fp1,"\n");
    fclose(fp);
    fclose(fp1);
    printf("译码完成,已将结果存入TextFile.txt中.\n\n");
}

void printfile()                //打印代码文件的操作;
{
    FILE *fp1,*fp2;
    printf("输入文件的文件名:CodeFile.txt\n");
    printf("结果保存的文件名:CodePrin.txt\n");
    fp1=fopen("CodeFile.txt","r");
    fp2=fopen("CodePrin.txt","w+");
    int count=0;
    char ch;
    while (!feof(fp1))
    {
        fscanf(fp1,"%c",&ch);
       printf("%c",ch);
       fprintf(fp2,"%c",ch);
       count++;
       if (count==50)
       {
           printf("\n");
           fprintf(fp2,"\n");
            count=0;
       }
    }
    printf("\n");
    fprintf(fp2,"\n");
    fclose(fp1);
    fclose(fp2);
    printf("打印代码完成,将结果存入CodePrin.txt中.\n\n");

}

void PrintTree(HafNode *huf,int n,int p,FILE *fp)//遍历打印
{
    int i;
    if (n==-1)
       return;
    PrintTree(huf,huf[n].rchild,p+1,fp);
    for (i=0;i<p;i++)
    {
        printf("   ");
        fprintf(fp,"   ");
    }
    if (p>=0&&huf[n].rchild==-1)
    {
       printf("---");
       printf("%c\n",huf[n].ch);            //如果此结点为叶子结点,则将此结点输出;
       fprintf(fp,"---%c\n",huf[n].ch);
    }
    else
    {
       printf("#\n");                     //如果此结点为非叶子结点,则输出"#";
       fprintf(fp,"#\n");
    }
    PrintTree(huf,huf[n].lchild,p+1,fp);
}

void printhaf()            //打印哈夫曼树整个过程
{
    FILE *fp;
    fp=fopen("huffman.txt","r");
    int i,n;
    fscanf(fp,"%d",&n);
    HafNode *myHaffTree=(HafNode *)malloc(sizeof (HafNode)*(2*n+1));
    for (i=0;i<n;i++)
       fscanf(fp,"%s %d %d %d/n",&myHaffTree[i].ch,&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);
    for (i=n;i<2*n-1;i++)
       fscanf(fp,"%d %d %d/n",&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);
    fclose(fp);
    printf("保存结果的文件名:TreePrint.txt\n");
    fp=fopen("TreePrint.txt","w+");
    PrintTree(myHaffTree,2*n-2,0,fp);
    fclose(fp);
    cout<<"打印哈夫曼树完成,同时已将结果存入TreePrint.txt中."<<endl;
}

void print()
{
   cout<<"*****                                                                      *****"<<endl;
   cout<<"*****                        哈夫曼编/译码器                              *****"<<endl;
   cout<<"*****                                                                      *****"<<endl;
   cout<<"***** c.编码   d.译码  e.打印哈夫曼树  f.打印代码文件  g.退出     *****"<<endl;
   cout<<"*****                                                                      *****"<<endl;
   cout<<"*****                                                                      *****"<<endl;
}

int main()
{
    int i,j,n=4;
    int weight[100];
    char ch[100],cha;
    print();
    Init(weight,ch);
    while (1)
    {
      printf("请输入要执行的操作:c.编码   d.译码   e.打印代码文件  f.打印哈夫曼树  g.退出\n");
       printf("请输入要执行的操作:");
       scanf("%s",&cha);
       if (cha=='g')
           break;
       switch (cha)
       {
       case 'c':bianma();break;      //执行编码操作
       case 'd':yima();break;      //执行译码操作
       case 'e':printfile();break;      //打印代码文件
       case 'f':printhaf();break;      //打印哈夫曼树
       }
    }
    return 0;
}

(四)图型结构题目
行车路线

小明和小芳出去乡村玩,小明负责开车,小芳来导航。
  小芳将可能的道路分为大道和小道。大道比较好走,每走1公里小明会增加1的疲劳度。小道不好走,如果连续走小道,小明的疲劳值会快速增加,连续走s公里小明会增加s2的疲劳度。
  例如:有5个路口,1号路口到2号路口为小道,2号路口到3号路口为小道,3号路口到4号路口为大道,4号路口到5号路口为小道,相邻路口之间的距离都是2公里。如果小明从1号路口到5号路口,则总疲劳值为(2+2)2+2+22=16+2+4=22。
  现在小芳拿到了地图,请帮助她规划一个开车的路线,使得按这个路线开车小明的疲劳度最小。
输入格式
输入的第一行包含两个整数n, m,分别表示路口的数量和道路的数量。路口由1至n编号,小明需要开车从1号路口到n号路口。
  接下来m行描述道路,每行包含四个整数t, a, b, c,表示一条类型为t,连接a与b两个路口,长度为c公里的双向道路。其中t为0表示大道,t为1表示小道。保证1号路口和n号路口是连通的。
输出格式
  输出一个整数,表示最优路线下小明的疲劳度。
样例输入
6 7
1 1 2 3
1 2 3 2
0 1 3 30
0 3 4 20
0 4 5 30
1 3 5 6
1 5 6 1
样例输出
76
样例说明
从1走小道到2,再走小道到3,疲劳度为52=25;然后从3走大道经过4到达5,疲劳度为20+30=50;最后从5走小道到6,疲劳度为1。总共为76。
数据规模和约定
对于30%的评测用例,1≤n≤8,1≤m≤10;
  对于另外20%的评测用例,不存在小道;
  对于另外20%的评测用例,所有的小道不相交;
  对于所有评测用例,1≤n≤500,1≤m≤105,1≤a, b≤n,t是0或1,c≤105。保证答案不超过106。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
long long dl[505][505],xl[505][505];//大路 小路
long long dis1[505],dis2[505];//大路小路到达i点时的疲劳度
bool vis[505];
int n,m;
void floyd()//先求出全走小路
{
	for(int k=1;k<=n;k++)
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	{
		if(xl[i][j]>xl[i][k]+xl[k][j]&&xl[i][k]!=inf&&xl[k][j]!=inf)
		{
			xl[i][j]=xl[i][k]+xl[k][j];
		}
	}
}
int main()
{
	memset(xl,inf,sizeof(xl));
	memset(dl,inf,sizeof(dl));//初始化
	cin>>n>>m;//路口数和道路的数量
	for(int i=1;i<=m;i++)//输入道路信息
	{
		int a,b,c,d;//类型a(0大道,1小道),连接b,c,长度d
		cin>>a>>b>>c>>d;
		if(a==1&&xl[b][c]>d)//小道存入小道的数组中
		{
			xl[b][c]=xl[c][b]=d;
		}
		else if(a==0&&dl[b][c]>d)
		{
			dl[b][c]=dl[c][b]=d;
		}
	}
	floyd();
	memset(dis1,inf,sizeof(dis1));
	memset(dis2,inf,sizeof(dis2));
	queue<int>q;
	dis1[1]=dis2[1]=0;
	q.push(1);
	vis[1]=1;
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		vis[now]=0;
		for(int i=1;i <=n;i++)
		{
			long long v=dl[now][i];//大路疲劳度
			if(dis1[i]>dis1[now]+v)//大路加大路的疲劳度,直接相加,比较后取小数
			{
				dis1[i]=dis1[now]+v;
				if(vis[i])continue;
				vis[i]=1;
				q.push(i);
			}
			if(dis1[i]>dis2[now]+v)//大路加小路的疲劳度
			{
				dis1[i]=dis2[now]+v;
				if(vis[i])continue;
				vis[i]=1;
				q.push(i);
			}
			if(xl[now][i]<1e10)
			{
				v=xl[now][i]*xl[now][i];
				if(dis2[i]>v+dis1[now])//小路加大路的疲劳度
				{
					dis2[i]=dis1[now]+v;
					if(vis[i])continue;
					vis[i]=1;
					q.push(i);
				}
			}
		}
	}
	cout<<min(dis1[n],dis2[n])<<endl;
	return 0;

}
/*
test data:
6 7
1 1 2 3
1 2 3 2
0 1 3 30
0 3 4 20
0 4 5 30
1 3 5 6
1 5 6 1
输出76
6 7
0 1 2 2
0 2 3 3
0 3 4 3
0 4 5 1
0 1 4 6
0 1 5 8
0 5 6 1
输出8
6 5
1 1 2 2
1 2 3 3
1 3 4 3
1 4 5 1
1 5 6 1
输出100
*/

(五)查找、排序、文件
二叉排序树与文件操作

功能要求:
(1)从键盘输入一组学生记录建立二叉排序树;
(2)*二叉排序树存盘;
(3)*由文件恢复内存的二叉排序树;
(4)中序遍历二叉排序树;
(5)求二叉排序树深度;
(6)求二叉排序树的所有节点数和叶子节点数;
(7)向二叉排序树插入一条学生记录;
(8)从二叉排序树中删除一条学生记录;
(9)从二叉排序树中查询一条学生记录;
(10)以广义表的形式输出二叉排序树
//定义学生记录类型
Struct student
{
Char num[6]; //学号
Int grade; //成绩
};
//定义二叉排序树节点值的类型为学生记录类型
typedef student ElemType;
//定义二叉排序树的节点类型
typedef Struct BSTNode
{
ElemType data;
Struct BSTNode *left;
Struct BSTNode *rchild;
} BSTNode;
KeyType key[m+1] ;//保存n个关键字域,下标0位置未用
MBNode * ptr[m+1] ; //保存n+1 个指向子树的指针域
Int recptr[m+1] ; //保存每个关键字对应记录的存储位置域,下标0位置未用
};

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
/*
strcmp
当s1<s2时,返回为负数

当s1=s2时,返回值= 0

当s1>s2时,返回正数
*/
using namespace std;
struct  student {
    char  num[6];//学号
    int    grade;//成绩
};
typedef  student   ElemType;
typedef  struct BSTNode {
    ElemType  data;
    struct BSTNode  *lchild;
    struct BSTNode  *rchild;
} BSTNode,*BSTree;


BSTNode *pre=NULL;
int n;
    int found(BSTree T,char c[])         //查找
    {
        BSTNode *p=T;
        while (p !=NULL)
        {
            if (strcmp(p->data.num,c)==0)//两者相等
            {
                return 1;
            }
            else
                if (strcmp(p->data.num,c)>0)
                {
                    pre=p;p=p->lchild;  //查左子树;数更小
                }
                else
                {
                    pre=p;p=p->rchild;  //查右子树;
                }
        }
       return 0;
    }

    void insert(BSTree &T,student a)//插入算法
    {
        BSTree s;
        char c[6];
        strcpy(c,a.num);//复制
        if (found(T,c)==0)
        {
            s=(BSTree)malloc(sizeof(BSTNode));
            s->data=a;
            s->lchild=NULL;
            s->rchild=NULL;
            if (T==NULL)
                {T=s;}            //新结点作为根结点;
            else if(strcmp(s->data.num,pre->data.num)<0)
                pre->lchild=s;      //插入左子树;
            else
            pre->rchild=s;    //插入右子树;
        }
    }

    void InOrderTraverse(BSTree T)
    {//中序遍历算法
        if (T!=NULL)
        {
            InOrderTraverse(T->lchild);
            cout<<T->data.num<<" "<<T->data.grade<<endl;
            InOrderTraverse(T->rchild);
        }
    }

    int Delete(BSTree &p)// 从二叉排序树中删除节点p, 并重接它的左或右子树
    {

        BSTree 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;
            }
            strcpy(p->data.num,s->data.num);

            if( q != p )				/* 判断是否执行上述while循环 */
                q->rchild = s->lchild;	/* 执行上述while循环,重接右子树 */
            else
                q->lchild = s->lchild;	/* 未执行上述while循环,重接左子树 */
            free(s);
        }
        cout<<"删除成功\n";
        n--;
        return 1;
    }

    int DeleteBST(BSTree &T, student a)
    {
        char c[6];
        strcpy(c,a.num);
        if(found(T,c)==0)
            printf("无节点\n");
        else
        {
            if( strcmp(c,T->data.num)==0)
                Delete(T);
            else if( strcmp(c,T->data.num)<0)
                return DeleteBST(T->lchild, a);
            else
                return DeleteBST(T->rchild, a);
        }
    }



void F1( BSTree &t)//输入学生数据
{
    t=NULL;
    int i;
    student a;
    printf("输入学生个数数量:\n");
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        printf("请输入第%d节点:\n",i);
        cout<<"学号:";
        cin>>a.num;
        cout<<"成绩:";
        cin>>a.grade;
        insert(t,a);
    }
}
void F22(BSTree T,FILE *w){//先序遍历二叉树的递归算法
	if (T){
		fprintf(w,"%s %d\n",T->data.num,T->data.grade);
		F22(T->lchild,w);
		F22(T->rchild,w);
	}
}
void F2(BSTree T)
    {//先序遍历(存盘)算法
        FILE *w=fopen("text.txt","w+");
        F22(T,w);
        cout<<"存盘成功\n";
        fclose(w);
    }



BSTree F3()//从文件中读取先序序列重建二叉排序树
{   FILE *w=fopen("text.txt","r+");
    student a;
    n=0;
    BSTree t=NULL;
     getc(w);
    if(feof(w))
    {
        printf("文件为空");
    }
    else
    {
        rewind(w);
        while(!feof(w))
        {
            fscanf(w,"%s %d\n",&a.num,&a.grade);
            printf("学号:%s 成绩:%d\n",a.num,a.grade);
            insert(t,a);n++;
        }
    }

        fclose(w);
        return t;
}
int F5(BSTree T){//求二叉树深度
	int depl,depr;
	if (T==NULL) return 0;
         else {
		depl=F5(T->lchild);
		depr=F5(T->rchild);
		if (depl>=depr) return (depl+1);
		else return (depr+1);
	        }
}

int F6(BSTree T)   //求叶子结点的个数
{if(!T) return 0;                     //空树没有叶子
  else
     if(T->lchild==NULL&&T->rchild==NULL) return 1; //叶子结点
         else  return F6(T->lchild)+F6(T->rchild);
       //左子树叶子数加上右子树叶子数
}

void F7(BSTree t)
{
    student a;
    cout<<"请输入新增的学生信息:\n";
    cout<<"学号:";cin>>a.num;
    cout<<"\n成绩:";cin>>a.grade;
     insert(t,a);
     n++;
     cout<<"插入成功\n";
}
void F8(BSTree t)
{
    student a;
    printf("\n请输入要删除的节点:\n");
    scanf("%s",a.num);
    DeleteBST(t,a);
}
void F9(BSTree t)
{
        BSTNode *p=t;
        char c[7];
        cout<<"请输入要查询的学号:";
        cin>>c;
        int flag=0;
        while (p !=NULL)
        {
            if (strcmp(p->data.num,c)==0)
            {
                cout<<"查询到记录如下:\n";
                cout<<"学号: "<<p->data.num<<"  成绩:"<<p->data.grade<<endl;
                flag=1;break;
            }
            else
                if (strcmp(p->data.num,c)>0)
                {
                    pre=p;p=p->lchild;  //查左子树;
                }
                else
                {
                    pre=p;p=p->rchild;  //查右子树;
                }
        }
        if(flag==0)
        cout<<"未查询到相关数据\n";
       return ;

}
void F10(BSTree t) {
    cout <<t->data.num;
    if(t->lchild != NULL)
    {
        cout << '(';
        F10(t->lchild);
        if(t->rchild == NULL)
        {
            cout << ')';
        }
    }
    if(t->rchild != NULL)
    {
        if(t->lchild == NULL)
        {
            cout << '(';
        }
        cout << ',';
       F10(t->rchild);
        cout << ')';
    }
}
void init()//菜单
{   cout<<"请选择操作\n";
    cout<<"(1)从键盘输入一组学生记录建立二叉排序树;\n";
    cout<<"(2)二叉排序树存盘;\n";
    cout<<"(3)由文件恢复内存的二叉排序树;\n";
    cout<<"(4)中序遍历二叉排序树;\n";
    cout<<"(5)求二叉排序树深度;\n";
    cout<<"(6)求二叉排序树的所有节点数和叶子节点数;\n";
    cout<<"(7)向二叉排序树插入一条学生记录;\n";
    cout<<"(8)从二叉排序树中删除一条学生记录;\n";
    cout<<"(9)从二叉排序树中查询一条学生记录;\n";
    cout<<"(10)以广义表的形式输出二叉排序树\n";

}
int main()
{

    BSTree t=NULL;
    int a,aa;
    init();
    while(cin>>a)
    {   int f=0;
        switch(a)
        {
            case 0:f==1;break;
            case 1:F1(t);break;
            case 2:F2(t);break;
            case 3:t=F3();break;
            case 4:InOrderTraverse(t);break;
            case 5: aa=F5(t);cout<<"二叉排序树深度为: "<<aa;break;
            case 6: aa=F6(t);cout<<"二叉排序树的所有节点数为:"<<n<<"  二叉排序树的叶子节点数为:"<<aa;break;
            case 7:F7(t);break;
            case 8:F8(t);break;
            case 9:F9(t);break;
            case 10:F10(t);break;
        }
        if(f==1)break;
        cout<<endl;
        init();
    }
    return 0;
}

  • 5
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值