任务:编号是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
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
#include
#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
#include
#include
#define MAX 100
#define MAXVALUE 10000
#include
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
#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
#include
#include
#include
/*
strcmp
当s1s2时,返回正数
*/
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;
}