一、实验目的及要求
(1)了解非数值问题的数学模型不是数学方程,而是表、树和图之类的数据结构。
(2)理解数据、数据元素、数据对象、数据结构和数据类型等的定义。掌握数据的逻辑结构和存储结构及其种类;算法的重要特征等。
(3)熟悉类C语言的书写规范,特别注意参数的区别,输入输出的方式和错误处理方式,以及抽象数据类型的表示和实现。
(4)会根据语句频度估算算法的时间复杂度。
二、实验内容
1.交换数据
2.最大值和最小值函数
3.建立三元组并进行一系列操作
三、实验主要流程、基本操作或核心代码、算法片段(该部分如不够填写,请填写至附页)
1.交换数据
#include
void swap(int &a,int &b)
{
int temp;
temp=a;
a=b;
b=temp;
}
void main()
{
int i,j;
cin>>i>>j;
cout<<"start :i="<<i<<",j="<<j;
swap(i,j);
cout<<endl<<"then :i="<<i<<",j="<<j<<endl;
}
2.最大值和最小值函数
#include
#define N 10
typedef float ET;
void MAX(ET a[],int n,ET &max)
{
max=a[0];
int i;
for(i=0;i<n;i++)
{
if(a[i]>max)
{
max=a[i];
}
}
}
void MIN(ET a[],int n,ET &min)
{
min=a[0];
int i;
for(i=0;i<n;i++)
{
if(a[i]<min)
{
min=a[i];
}
}
}
void main()
{
ET a[N],max,min;
int n;
cout<<"n=?"<<endl;
cin>>n;
for(int i=0;i<n;i++)
{
cout<<"第"<<i+1<<"个:";
cin>>a[i];
}
MAX(a,n,max);
MIN(a,n,min);
cout<<"max="<<max<<",min="<<min<<endl;
}
3.建立三元组并进行一系列操作
typedef int ET;
typedef ET * Tri;
typedef int Status;//头文件1.h
#include
#include
#include
#include
#include
#define OK 1
#define OVERFLOW -2
#define ERROR 0
#define TRUE 1
#define FALSE 0//头文件 2.h
Status Crea(Tri &T,ET v1,ET v2,ET v3)
{
T=(ET*)malloc(3*sizeof(ET));//分配3个元素空间
if(!T)
exit(OVERFLOW);//分配空间失败
T[0]=v1;T[1]=v2;T[2]=v3;
return OK;
}
Status Destory(Tri &T)
{
free(T);
T=NULL;
return OK;
}
Status Get(Tri T,int i,ET &e)
{
if(i<1||i>3)
return ERROR;
e=T[i-1];
return OK;
}
Status Put(Tri &T,int i,ET e)
{
if(i<1||i>3)
return ERROR;
T[i-1]=e;
return OK;
}
Status IsDescending(Tri T)
{
return (T[0]<=T[1])&&(T[1]<=T[2]);
}
Status Max(Tri T,ET &e)
{
e=(T[0]>=T[1])?((T[0]>=T[2])?T[0]:T[2]):((T[1]>=T[2])?T[1]:T[2]);
return OK;
}
Status Min(Tri T,ET &e)
{
e=(T[0]<=T[1])?((T[0]<=T[2])?T[0]:T[2]):((T[1]<=T[2])?T[1]:T[2]);
return OK;
}
Status Avr(Tri T,float &e)
{
e=(T[0]+T[1]+T[2])/(float)3;
return OK;
}//头文件 3.h
#include "1.h"
#include "2.h"
#include "3.h"
void main()
{
system("color 0E");
Tri T;
ET a,b,c,e;
int i;
float f;
cout<<"***************三元组编程1.0***************"<<endl;
cout<<"请输入三元组的值:"<<endl;
cin>>a>>b>>c;
int choice;
do
{
printf("————————————————————————\n");
printf("|| 1.创建三元组 ||\n");
printf("|| 2.销毁三元组 ||\n");
printf("|| 3.获取三元组中的某个数 ||\n");
printf("|| 4.修改三元组中的某个数 ||\n");
printf("|| 5.三元组是否是升序 ||\n");
printf("|| 6.查找三元组中最大值 ||\n");
printf("|| 7.查找三元组中最小值 ||\n");
printf("|| 8.计算三元组中平均值 ||\n");
printf("|| 0.退出 ||\n");
printf("————————————————————————\n");
cin>>choice;
switch(choice)
{
case 1:
if(Crea(T,a,b,c)==OVERFLOW)
cout<<"系统分配空间失败"<<endl;
else
cout<<"系统分配空间成功"<<endl;
break;
case 2:
if(Destory(T)==OK)
cout<<"销毁成功"<<endl;
else
cout<<"销毁失败"<<endl;
break;
case 3:
cout<<"请输出查找元素(1,2,3):"<<endl;
cin>>i;
while(i<1||i>3)
{
cout<<"数据不合法,请重新输入"<<endl;
cout<<"请输出查找元素(1,2,3):"<<endl;
cin>>i;
}
Get(T,i,e);
cout<<e<<endl;
break;
case 4:
cout<<"请输入修改元素(1,2,3):"<<endl;
cin>>i;
while(i<1||i>3)
{
cout<<"数据不合法,请重新输入"<<endl;
cout<<"请输出查找元素(1,2,3):"<<endl;
cin>>i;
}
cout<<"请输入修改的值为:"<<endl;
cin>>e;
Put(T,i,e);
break;
case 5:
if(IsDescending(T)==1)
{
cout<<"是升序排列"<<endl;
}
else
{
cout<<"不是升序排列"<<endl;
}
break;
case 6:
Max(T,e);
cout<<"最大值为:"<<e<<endl;
break;
case 7:
Min(T,e);
cout<<"最小值为:"<<e<<endl;
break;
case 8:
Avr(T,f);
cout<<"平均值为:"<<f<<endl;
break;
case 0:
break;
}
}while(choice!=0);
}
//源程序4.cpp
一、实验目的及要求
(1)熟悉线性表的基本运算在两种存储结构(顺序结构和链式结构)上的实现,以线性表的各种操作(建立、插入、删除等)的实现为实验重点;
(2)通过本次实验帮助学生加深对顺序表、链表的理解,并加以应用;
(3)掌握循环链表和双链表的定义和构造方法。
二、实验内容
(1)编程实现顺序表的基本操作(建立、插入、删除、输出、顺序查找、折半查找、排序等),并设计一个菜单调用。
(2)编程实现单链表的基本操作(建立、插入、删除、求表长、顺序查找等),并设计一个菜单调用。
(3)编程实现双向循环链表的基本操作(建立、插入、删除、输出等),并设计一个菜单调用。
(4)编程求解约瑟夫环(约瑟夫问题):已知n个人(以编号1,2,3…,n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
注:(1)(2)为必做题,(3)(4)为选做题。
三、实验主要流程、基本操作或核心代码、算法片段(该部分如不够填写,请填写至附页)
1.编程实现顺序表的基本操作(建立、插入、删除、输出、顺序查找、折半查找、排序等),并设计一个菜单调用。
#include
#include
#include
#include
#include //改变控制台颜色时需要此头文件
#include //使用时间函数时需要此头文件
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define OK 1
#define ERROR 0
#define TURE 1
#define FALSE 0
#define OVERFLOW -1
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 100
typedef int STATUS;
typedef int ET;
typedef struct{
ET *elem;
int length;
int listsize;
}SqList;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
STATUS InitList_Sq(SqList &L) {
// 构造一个空的线性表L。
L.elem = (ET *)malloc(LIST_INIT_SIZE*sizeof(ET));
if (!L.elem) return OK; // 存储分配失败
L.length = 0; // 空表长度为0
L.listsize = LIST_INIT_SIZE; // 初始存储容量
return OK;
}
///////////////////////////////////////////////////////////////////
STATUS ListInsert_Sq(SqList &L, int i, ET e) {
// 在顺序线性表L的第i个元素之前插入新的元素e,
// i的合法值为1≤i≤ListLength_Sq(L)+1
ET *p;
if (i < 1 || i > L.length+1) return ERROR; // i值不合法
if (L.length >= L.listsize) { // 当前存储空间已满,增加容量
ET *newbase = (ET *)realloc(L.elem,
(L.listsize+LISTINCREMENT)*sizeof (ET));
if (!newbase) return ERROR; // 存储分配失败
L.elem = newbase; // 新基址
L.listsize += LISTINCREMENT; // 增加存储容量
}
ET *q = &(L.elem[i-1]); // q为插入位置
for (p = &(L.elem[L.length-1]); p>=q; --p) *(p+1) = *p;
// 插入位置及之后的元素右移
*q = e; // 插入e
++L.length; // 表长增1
return OK;
} // ListInsert_Sq
///////////////////////////////////////////////////////////////////
STATUS BuiltList_Sq(SqList &L,int n) {
int i;
ET e;
for(i=1;i<=n;i++)
{
cin>>e;
ListInsert_Sq(L,i,e);
}
return OK;
}
///////////////////////////////////////////////////////////////////
STATUS ListDelete_Sq(SqList &L, int i, ET &e) {
// i的合法值为1≤i≤ListLength_Sq(L)。
ET *p, *q;
if (i<1 || i>L.length) return ERROR; // i值不合法
p = &(L.elem[i-1]); // p为被删除元素的位置
e = *p; // 被删除元素的值赋给e
q = L.elem+L.length-1; // 表尾元素的位置
for (++p; p<=q; ++p) *(p-1) = *p; // 被删除元素之后的元素左移
--L.length; // 表长减1
return OK;
}
///////////////////////////////////////////////////////////////////
void Show(SqList L)
{
int i;
for(i=0;i<L.length;i++)
{
cout<<L.elem[i]<<" ";
}
cout<<endl;
}
///////////////////////////////////////////////////////////////////
STATUS Find(SqList &L, int i, ET &e)
{
if(i<L.length){
e=L.elem[i-1];
return OK;
}
else
return ERROR;
}
///////////////////////////////////////////////////////////////////
STATUS compare(ET a,ET b)
{
if(a==b)//strcmp(a,b)
{
return OK;
}
else
return ERROR;
}
///////////////////////////////////////////////////////////////////
int LocateElem_Sq(SqList L, ET e,STATUS (*compare)(ET, ET)) {
int i;
ET *p;
i = 1; // i的初值为第1个元素的位序
p = L.elem; // p的初值为第1个元素的存储位置
while (i <= L.length && (*compare)(*p++, e))
++i;
if (i <= L.length) return i;
else return 0;
}
///////////////////////////////////////////////////////////////////
void Sort(SqList &L)
{
int i,j;
ET temp,min;
for(i=0;i<L.length;i++)
{
min=L.elem[i];
for(j=i;j<L.length;j++)
{
if(min>L.elem[j])
{
temp=min;
min=L.elem[j];
L.elem[j]=temp;
}
}
L.elem[i]=min;
}
}
///////////////////////////////////////////////////////////////////
STATUS Find2(SqList &L, int &i, ET e)
{
Sort(L);
int low=0,high=L.length-1,mid; //置当前查找区间上、下界的初值
while(low<=high)
{
if(L.elem[low]==e)
i= low;
if(L.elem[high]==e)
i= high;
mid=low+((high-low)/2);
/*使用(low+high)/2会有整数溢出的问题
(问题会出现在当low+high的结果大于表达式结果类型所能表示的最大值时,
这样,产生溢出后再/2是不会产生正确结果的,而low+((high-low)/2)
不存在这个问题*/
if(L.elem[mid]==e)
i= mid; //查找成功返回
if(L.elem[mid]<e)
low=mid+1;
else
high=mid-1;
}
if(low>high)
return ERROR;//当low>high时表示所查找区间内没有结果,查找失败
}
void qusort(SqList &L, int start, int end) /*自定义函数qusort()*///快速排序
{
int i, j,key; /*定义变量为基本整型*/
i = start; /*将每组首个元素赋给i*/
j = end; /*将每组末尾元素赋给j*/
key = L.elem[start]; /*设置基准值*/
while (i < j)
{
while (i < j && key< L.elem[j])
j--; /*位置左移*/
if (i < j)
{
L.elem[i] = L.elem[j]; /*将s[j]放到s[i]的位置上*/
i++; /*位置右移*/
}
while (i < j && L.elem[i] <= L.elem[0])
i++; /*位置右移*/
if (i < j)
{
L.elem[j] = L.elem[i]; /*将大于基准值的s[j]放到s[i]位置*/
j--; /*位置右移*/
}
}
L.elem[i] = key; /*将基准值放入指定位置*/
if (start < i)
qusort(L, start, j - 1);/*对分割出的部分递归调用函数qusort()*/
if (i < end)
qusort(L, j + 1, end);
}
void Qusort(SqList &L)
{
clock_t start1=clock();
qusort(L,0,L.length-1);
clock_t end1=clock();
cout<<"使用了"<<end1-start1<<"毫秒"<<endl;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "1.h"
#include "2.h"
#include "3.h"
void main()
{
SqList L;
InitList_Sq(L);
cout<<"请输入元素个数"<<endl;
int n,i;
ET e;
cin>>n;
BuiltList_Sq(L,n);
int choice=-1;
do
{
printf("1.插入元素\n");
printf("2.删除元素\n");
printf("3.输出元素\n");
printf("4.顺序查找元素\n");
printf("5.折半查找元素\n");
printf("6.线性表冒泡排序\n");
printf("7.线性表快速排序\n");
printf("0.退出\n");
cout<<"请输入你的选择"<<endl;
cin>>choice;
switch(choice)
{
case 1:
cout<<"请输入插入位置和插入的数值"<<endl;
cin>>i>>e;
if(ListInsert_Sq(L,i,e)==OK)
{
cout<<"插入成功"<<endl;
}
else{
cout<<"插入失败"<<endl;
}
break;
case 2:
cout<<"请输入删除位置"<<endl;
cin>>i;
if(ListDelete_Sq(L, i, e))
{
cout<<"删除成功"<<endl;
}
else
{
cout<<"删除失败"<<endl;
}
cout<<"删除位置的值为"<<e<<endl;
break;
case 3:
Show(L);
break;
case 4:
cout<<"请输入查找位置"<<endl;
cin>>i;
if(Find(L, i, e))
{
cout<<"查找成功"<<endl;
}
else
{
cout<<"查找失败"<<endl;
}
cout<<"查找位置的值为"<<e<<endl;
break;
case 5:
cout<<"升幂排序"<<endl;
Show(L);
cout<<"请输入查找数值"<<endl;
cin>>e;
if(!Find2(L, i, e))
{
cout<<"查找成功"<<endl;
}
else
{
cout<<"查找失败"<<endl;
}
cout<<"查找数值的位置为"<<i+1<<endl;
break;
case 6:
Sort(L);
Show(L);
break;
case 7:
Qusort(L);
Show(L);
break;
case 0:
break;
default:
cout<<"选项不合法"<<endl;
break;
}
}while(choice);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2.链表
编程实现单链表的基本操作(建立、插入、删除、求表长、顺序查找等),并设计一个菜单调用。
头文件与顺序表的大体相同
typedef struct LNode{
ET data;
struct LNode *next;
}LNode,*Linklist;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Color()
{
int choice;
cout<<"请输入喜欢的颜色"<<endl;
cout<<"0.黑色 ";
cout<<"1.蓝色"<<endl;
cout<<"2.绿色 ";
cout<<"3.湖蓝色"<<endl;
cout<<"4.红色 ";
cout<<"5.紫色"<<endl;
cout<<"6.黄色 ";
cout<<"7.白色"<<endl;
cout<<"8.灰色 ";
cout<<"9.淡蓝色"<<endl;
cout<<"10.淡绿色 ";
cout<<"11.浅浅绿色"<<endl;
cout<<"12.淡红色 ";
cout<<"13.淡紫色"<<endl;
cout<<"14.淡黄色 ";
cout<<"15.亮白色"<<endl;
cin>>choice;
switch(choice)
{
case 0:system("color F0");break;
case 1:system("color F1");break;
case 2:system("color F2");break;
case 3:system("color F3");break;
case 4:system("color F4");break;
case 5:system("color F5");break;
case 6:system("color F6");break;
case 7:system("color 07");break;
case 8:system("color F8");break;
case 9:system("color F9");break;
case 10:system("color FA");break;
case 11:system("color FB");break;
case 12:system("color FC");break;
case 13:system("color FD");break;
case 14:system("color FE");break;
case 15:system("color 0F");break;
}
}
//////////////////////////////////////////////////////////
STATUS Get_by_location(Linklist L,int i,ET &e)
{
struct LNode *p;
int j;
p=L->next;
j=1;
while(p&&j<i)
{
p=p->next;
++j;
}
if(!p||j>i) return ERROR;
e=p->data;
return OK;
}
//////////////////////////////////////////////////////////
STATUS Insert(Linklist &L,int i,ET e)
{
struct LNode *p,*s;
int j;
p=L;
j=0;
while(p&&j<i-1)
{
p=p->next;
++j;
}
if(!p||j>i-1) return ERROR;
s=(Linklist)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return OK;
}
////////////////////////////////////////////////////////////
void Creat(Linklist &L,int n)
{
int i;
struct LNode *p,*q;
L=p=(Linklist)malloc(sizeof(LNode));
p->next=NULL;
/*
L=(Linklist)malloc(sizeof(LNode));
L->next=NULL;
for(i=n;i>0;--i){
p=(Linklist)malloc(sizeof(LNode));
cin>>p->data;
p->next=L->next;
L->next=p;
}
*///头插法
for(i=0;i<n;i++)
{
q=(Linklist)malloc(sizeof(LNode));
cin>>q->data;
q->next=NULL;//尾节点
p->next=q;
p=q;
}
}
/////////////////////////////////////////////////////////////
void Show(Linklist L)
{
L=L->next;
while(L)
{
cout<<L->data<<" ";
L=L->next;
}
cout<<endl;
}
////////////////////////////////////////////////
STATUS Get_by_value(Linklist L,int &i,ET e)
{
struct LNode *p;
int j;
p=L->next;
j=1;
while(p&&p->data!=e)
{
p=p->next;
++j;
}
if(!p) return ERROR;
i=j;
return OK;
}
////////////////////////////////////////////////////////////
STATUS Delet_by_value(Linklist &L,ET e)
{
struct LNode *p=L,*q=L->next;
while(q!=NULL&&q->data!=e)
{
p=q;
q=q->next;
}
if(q->data==e)
{
p->next=q->next;
free(q);
}
else
{
cout<<"该节点不存在"<<endl;
}
return OK;
}
/////////////////////////////////////////////////////////////
STATUS Delet_by_location(Linklist &L,int i)
{
struct LNode *p=L,*q=L->next;
int j=1;
while(q!=NULL&&j!=i)
{
p=q;
q=q->next;
j++;
}
if(j==i)
{
p->next=q->next;
free(q);
}
else
{
cout<<"该节点不存在"<<endl;
}
return OK;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "1.h"
#include "2.h"
#include "3.h"
void main()
{
cout<<"***************圣三一线性表(双向)2.0***************"<<endl;
cout<<"建立链表,请输入链表元素个数"<<endl;
int n,i;
ET e;
cin>>n;
struct LNode *L;
Creat(L,n);
cout<<endl;
int choice=-1;
do{
printf("==========================================\n");
printf("| |\n");
printf("| 1.插入元素 |\n");
printf("| 2.通过位置查找元素数值 |\n");
printf("| 3.通过数值查找元素位置 |\n");
printf("| 4.通过位置删除元素 |\n");
printf("| 5.通过数值删除元素 |\n");
printf("| 6.显示全部元素 |\n");
printf("| 7.改变当前文字颜色 |\n");
printf("| |\n");
printf("==========================================\n");
cin>>choice;
switch(choice)
{
case 1:
cout<<"请输入插入位置和插入元素的值"<<endl;
cin>>i>>e;
if(Insert(L,i,e)==OK)
{
cout<<"插入成功"<<endl;
}
else
{
cout<<"插入失败"<<endl;
}
break;
case 2:
cout<<"请输入查找位置"<<endl;
cin>>i;
if(Get_by_location(L,i,e)==OK)
{
cout<<"查找成功,该位置元素值为"<<e<<endl;
}
else
{
cout<<"查找失败"<<endl;
}
break;
case 3:
cout<<"请输入查找数值"<<endl;
cin>>i;
if(Get_by_value(L,i,e)==OK)
{
cout<<"查找成功,该元素位置为"<<i<<endl;
}
else
{
cout<<"查找失败"<<endl;
}
break;
case 4:
cout<<"请输入删除位置"<<endl;
cin>>i;
if(Delet_by_location(L,i)==OK)
{
cout<<"删除成功"<<endl;
}
else
{
cout<<"删除失败"<<endl;
}
break;
case 5:
cout<<"请输入删除数值"<<endl;
cin>>e;
if(Delet_by_value(L,e)==OK)
{
cout<<"删除成功"<<endl;
}
else
{
cout<<"删除失败"<<endl;
}
break;
case 6:
Show(L);
getchar();
break;
case 7:
Color();
break;
default: break;
}
}while(choice!=0);
}
3.双向链表
编程实现双向循环链表的基本操作(建立、插入、删除、输出等),并设计一个菜单调用。
头文件与线性链表相同
typedef int ET;
typedef struct LNode{
ET data;
struct LNode *prior,*next;
}LNode,*Linklist;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Color()//增加的无聊小功能
{
int choice;
cout<<"请输入喜欢的颜色"<<endl;
cout<<"0.黑色 ";
cout<<"1.蓝色"<<endl;
cout<<"2.绿色 ";
cout<<"3.湖蓝色"<<endl;
cout<<"4.红色 ";
cout<<"5.紫色"<<endl;
cout<<"6.黄色 ";
cout<<"7.白色"<<endl;
cout<<"8.灰色 ";
cout<<"9.淡蓝色"<<endl;
cout<<"10.淡绿色 ";
cout<<"11.浅浅绿色"<<endl;
cout<<"12.淡红色 ";
cout<<"13.淡紫色"<<endl;
cout<<"14.淡黄色 ";
cout<<"15.亮白色"<<endl;
cin>>choice;
switch(choice)
{
case 0:system("color F0");break;
case 1:system("color F1");break;
case 2:system("color F2");break;
case 3:system("color F3");break;
case 4:system("color F4");break;
case 5:system("color F5");break;
case 6:system("color F6");break;
case 7:system("color 07");break;
case 8:system("color F8");break;
case 9:system("color F9");break;
case 10:system("color FA");break;
case 11:system("color FB");break;
case 12:system("color FC");break;
case 13:system("color FD");break;
case 14:system("color FE");break;
case 15:system("color 0F");break;
}
}
//////////////////////////////////////////////////////////
STATUS Insert(Linklist &L, int i, ET e) {
struct LNode *p,*s;
int j;
p=L;
j=0;
while(p&&j<i-1)
{
p=p->next;
++j;
}
if(!p||j>i-1) return ERROR;
s=(Linklist)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
s->prior=p;
p->next->prior=s;
p->next=s;
return OK;
}
//////////////////////////////////////////////////////////
STATUS Delet(Linklist &L, int i, ET &e) {
struct LNode *p=L,*q=L->next;
int j=1;
while(q!=NULL&&j!=i)
{
p=q;
q=q->next;
j++;
}
if(j==i)
{
p->next=q->next;
q->next->prior=p;
e=q->data;
free(q);
}
else
{
cout<<"该节点不存在"<<endl;
}
return OK;
}
//////////////////////////////////////////////////////////
void Creat(Linklist &L,int n)
{
int i;
struct LNode *p,*q;
L=p=(Linklist)malloc(sizeof(LNode));
p->next=NULL;
/*
L=(Linklist)malloc(sizeof(LNode));
L->next=NULL;
for(i=n;i>0;--i){
p=(Linklist)malloc(sizeof(LNode));
cin>>p->data;
p->next=L->next;
L->next=p;
}
*///头插法
for(i=0;i<n;i++)
{
q=(Linklist)malloc(sizeof(LNode));
cin>>q->data;
q->next=NULL;//尾节点
p->next=q;
p=q;
q->prior=p;
}
}
/////////////////////////////////////////////////////////////
void Show(Linklist L)
{
L=L->next;
while(L)
{
cout<<L->data<<" ";
L=L->next;
}
cout<<endl;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4.编程求解约瑟夫环(约瑟夫问题):已知n个人(以编号1,2,3...,n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
头文件与线性链表相同
typedef struct LNode{
ET data;
struct LNode *next;
}LNode,*Linklist;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Creat(Linklist &L,int n)
{
int i;
struct LNode *p,*q;
L=p=(Linklist)malloc(sizeof(LNode));
p->data=1;
p->next=NULL;
for(i=2;i<=n;i++)
{
q=(Linklist)malloc(sizeof(LNode));
q->data=i;
q->next=NULL;
p->next=q;
p=q;
}
q->next=L;
}
//////////////////////////////////////////////////////////////////
Linklist Circle(Linklist &L,int &k,int m)
{
int i;
Linklist a,b;
a=b=L;
for(i=1;i<k;i++)
{
a=a->next;
}
int j;
b=a;
for(j=1;j<m;j++)
{
a=b;
b=b->next;
}
a->next=b->next;
cout<<"本次被出局的是:"<<b->data<<endl;
free(b);
k=1;
if(a->next==a)
{
cout<<"最后存活的是:"<<a->data<<endl;
return NULL;
}
else
{
return a->next;
}
}
/////////////////////////////////////////////////////////////////
void Show(Linklist L,int n)
{
int i=1;
while(L&&(i<=n))
{
i++;
cout<<L->data<<" ";
L=L->next;
}
cout<<endl;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "1.h"
#include "2.h"
#include "3.h"
void main()
{
int n,m,k;
cout<<"请输入总人数n,从编号为K,以m为循环"<<endl;
cin>>n>>k>>m;
Linklist L;
Creat(L,n);//建立链循环
Show(L,n);
while(L)
{
L= Circle(L,k,m);
}
}
一、实验目的及要求
(1)掌握栈和队列这两种特殊的线性表,熟悉它们的特性,在实际问题背景下灵活运用它们;
(2)本实验训练的要点是栈的观点及其典型应用。
二、实验内容
(1)编程实现顺序栈的基本操作,并应用栈的基本操作,实现:
a)进制的转换。
b)表达式的语法检查(括号的匹配)。
c)四则运算表达式的求值。
(2) 编程实现队列(链队列或循环队列)的基本操作,并应用栈和队列实现回文序列的判定。
三、实验主要流程、基本操作或核心代码、算法片段(该部分如不够填写,请填写至附页)
1.进制转换
#define STACK_INTT_SIZE 100
#define STACKINCREMENT 10
typedef int ST;
typedef struct{
ST *base;
ST *top;
int stacksize;
}SqStack;
Status InitStack(SqStack &S){
S.base=(ST * )malloc(STACK_INTT_SIZE*sizeof(ST));
if(!S.base)
exit(OVERFLOW);
S.top=S.base;
S.stacksize=STACK_INTT_SIZE;
return OK;
}
Status Push(SqStack &S,ST e){
if(S.top-S.base>=S.stacksize)
//栈满,追加空间
{
S.base=(ST*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(ST));
//增加10个ST
if(!S.base)
exit(OVERFLOW);
//存储分配失败
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}
*S.top++=e;
return OK;
}
Status Pop(SqStack &S,ST &e)
{
if(S.top==S.base)
return ERROR;
e=*--S.top;
return OK;
}
Status StackEmpty(SqStack S)
{
if(S.top==S.base)
return OK;
else
return ERROR;
}
void Conversion_Zhengshu(int N,int R)
{
int e=0;
SqStack S;
InitStack(S);
while(N){
Push(S,N%R);
N=N/R;
}
while(!StackEmpty(S)){
Pop(S,e);
if(e>=0&&e<=9)
printf("%d",e);
else
printf("%c",e-10+'A');
}
}
void Conversion_XiaoShu(float B,int R)
{
int e;
while(B>0.0001){
B=B*R;
e=(int)B;
B=B-e;
if(e>=0&&e<=9)
printf("%d",e);
else
printf("%c",e-10+'A');
}
}
void main()
{
float N=0;
int R=0;
cout<<"请输入需要转换的数值:"<<endl;
cin>>N;
cout<<"请输入需要转换成几进制:"<<endl;
cin>>R;
int A=0;//整数部分
float B=0;//小数部分
A=(int)N;
B=N-A;
if(A>0)//如果整数部分不为零,进行转换,否则输出0
Conversion_Zhengshu(A,R);//转换整数部分,并且输出
else
printf("0");
printf(".");//输出小数点
if(B>0.00001)//如果小数部分部委为零,进行转换,否则输出0
Conversion_XiaoShu(B,R);//转换小数部分,并且输出
else
cout<<"0";
cout<<endl;
}
2.表达式的语法检查(括号的匹配)
头文件1,2,3和上题相同
Cpp如下:
#include "1.h"
#include "2.h"
#include "3.h"
void main()
{
SqStack S;
InitStack(S);
char a[100]="";
cout<<"请输入括号:(,),[,],{,}"<<endl;
scanf("%s",&a);
int i=0;
char ch;
while(a[i]!='\0')
{
if(a[i]=='('||a[i]=='['||a[i]=='{')
Push(S,a[i]);
else if(a[i]==')')
{
Pop(S,ch);
if(ch!='(')
{
cout<<"括号不匹配"<<endl;
break;
}
}
else if(a[i]==']')
{
Pop(S,ch);
if(ch!='[')
{
cout<<"括号不匹配"<<endl;
break;
}
}
else if(a[i]=='}')
{
Pop(S,ch);
if(ch!='{')
{
cout<<"括号不匹配"<<endl;
break;
}
}
i++;
}
if(!StackEmpty(S))
cout<<"括号数量不匹配"<<endl;
else
cout<<"括号匹配对应"<<endl;
}
3.四则运算表达式(只做了中缀式转换成后缀式)
头文件1,2和前两题相同
头文件3增加了以下内容
char GetTop(SqStack S)
{
if(StackEmpty(S)!=OK)
return *S.top;
else
return '#';
}
char Precede(char A,char B)
{
if(A=='+'&&((B=='+')||(B=='-')||(B==')')||(B=='#')))
return '>';
else
return '<';
if(A=='-'&&((B=='+')||(B=='-')||(B==')')||(B=='#')))
return '>';
else
return '<';
if(A=='*'&&B=='(')
return '<';
else
return '>';
if(A=='/'&&B=='(')
return '<';
else
return '>';
if(A=='('&&B==')')
return '=';
else if(A=='('&&B!='#')
return '<';
if(A=='#'&&B=='#')
return '=';
else if(A=='#'&&B!=')')
return '<';
if(A==')'&&B!='(')
return '>';
}
char Operate(char a,char op,char b)
{
if(op=='+')
return '0'+atoi(&a)+atoi(&b);
else if(op=='-')
return '0'+atoi(&b)-atoi(&a);
else if(op=='*')
return '0'+atoi(&b)*atoi(&a);
else if(op=='/')
return '0'+atoi(&b)/atoi(&a);
else
return '0';
}
Cpp如下:
#include "1.h"
#include "2.h"
#include "3.h"
void main()
{
char a[100];
printf("请输入中缀运算表达式,以“#”结束\n");
scanf("%s",&a);
//输入字符串
SqStack S1;//操作符
InitStack(S1);
Push(S1,'#');
//初始化运算符栈,栈底为#
int i=0;
char e;
for(i=0;a[i]!='\0';i++)
//将字符串里面的元素进行遍历,若是数字则输出,若是字符则与栈内字符比较
{
if(isdigit(a[i]))
printf("%2c",a[i]);
else if(Precede(a[i],GetTop(S1))=='>')
Push(S1,a[i]);
else if(Precede(a[i],GetTop(S1))=='=')
Pop(S1,e);
else
{
while(Precede(a[i],GetTop(S1))=='<'&&StackEmpty(S1)!=OK)
{
Pop(S1,e);
printf("%2c",e);
}
}
}
while(StackEmpty(S1)!=OK)
//如果运算栈里还有运算符则全部输出
{
Pop(S1,e);
printf("%2c",e);
}
printf("\n");
}
二.回文序列判断
头文件1与上两题相同
头文件2:除了以下内容有所不同,其他内容与上两题相同
typedef char ET;
头文件3与上两题相同
头文件4:
typedef struct QNode{
ET data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front;
QueuePtr rear;
}LinkQueue;//队列
头文件5://队列的函数
Status InitQueue(LinkQueue &Q)
{
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
if(!Q.front) exit(OVERFLOW);
Q.front->next=NULL;
return OK;
}
Status DestroyQueue(LinkQueue &Q)
{
while(Q.front)
{
Q.rear=Q.front->next;
free(Q.front);
Q.front=Q.rear;
}
return OK;
}
Status EnQueue(LinkQueue &Q,ET e)
{
QueuePtr p;
p=(QueuePtr)malloc(sizeof(QNode));
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
return OK;
}
Status DeQueue(LinkQueue &Q,ET &e)
{
QueuePtr p;
if(Q.front==Q.rear)return ERROR;
p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front;
free(p);
return OK;
}
Status QueueEmpty(LinkQueue Q)
{
if(Q.front==Q.rear)
return OK;
else
return ERROR;
}
Status GetHead(LinkQueue Q,ET &e)
{
if(Q.front==Q.rear)
return ERROR;
else
{
e=Q.front->next->data;
return OK;
}
}
int QueueLength(LinkQueue Q)
{
int n=0;
QueuePtr p;
p=Q.front->next;
while(p)
{
n++;
p=p->next;
}
return n;
}
void ShowQueue(LinkQueue Q)
{
QueuePtr p;
p=Q.front->next;
while(p)
{
cout<<p->data<<" ";
p=p->next;
}
}
Cpp如下:
#include "1.h"
#include "2.h"
#include "3.h"
#include "4.h"
#include "5.h"
void main()
{
LinkQueue Q;
InitQueue(Q);
SqStack S;
InitStack(S);
char a[100];
cout<<"请输入需要检测的回文:"<<endl;
scanf("%s",&a);
int i=0;
while(a[i]!='\0')
{
EnQueue(Q,a[i]);
Push(S,a[i]);
i++;
}
cout<<endl;
char q,s;
int flag=0;
while(!QueueEmpty(Q)&&!StackEmpty(S))
{
DeQueue(Q,q);
Pop(S,s);
if(q!=s)
{
cout<<"不是回文序列"<<endl;
exit(-1);
}
}
cout<<"是回文序列"<<endl;
}
一、实验目的及要求
(1) 熟悉字符串类型定义和表示。
(2) 实现串的一些基本操作。
二、实验内容
(1) 编程实现两个串S和T的比较。
(2)编程实现串的模式匹配算法(BF算法)。
三、实验主要流程、基本操作或核心代码、算法片段(该部分如不够填写,请填写至附页)
头文件:
#include
#include
#include
#define MAXSTRLEN 255
typedef int Status;
typedef char ET;
typedef char SString[MAXSTRLEN+1];
int StrLength(SString T)
函数部分:
//返回字符串长度
{
int a;
a=T[0];
return a;
}
void Into_SString(SString &T)
{//字符串赋值操作
int i=1;
char ch=getchar();
while(ch!='\n')
{
T[i]=ch;
ch=getchar();
i++;
}
T[0]=i-1;//记录第一个串长度
}
Status Concat(SString &T, SString S1, SString S2) {
int i;
Status uncut;
if (S1[0]+S2[0] <= MAXSTRLEN) { // 未截断
for (i=1; i<=S1[0]; i++) T[i] = S1[i];
for (i=1; i<=S2[0]; i++) T[i+S1[0]] = S2[i];
T[0] = S1[0]+S2[0];
uncut = TRUE;
} else if (S1[0] < MAXSTRLEN) { // 截断
for (i=1; i<=S1[0]; i++) T[i] = S1[i];
for (i=S1[0]+1; i<=MAXSTRLEN; i++) T[i] = S2[i-S1[0]];
T[0] = (char)MAXSTRLEN;
uncut = FALSE;
} else { // 截断(仅取S1)
for (i=0; i<=MAXSTRLEN; i++) T[i] = S1[i];
uncut = FALSE;
}
return uncut;
}
int StrCompare(SString S, SString T)
{//字符串比较操作
int i=0;
for(i=0;i<=S[0]&&i<=T[0];i++)
{
if(S[i]!=T[i])
{
return (int)(S[i]-T[i]);
}
}
return 0;
}
Status SubString(SString &Sub, SString S, int pos, int len) {
int i;
if (pos < 1 || pos > S[0] || len < 0 || len > S[0]-pos+1)
return ERROR;
for(i=1; i<=len; i++)
Sub[i] = S[pos+i-1];
Sub[0] = len;
return OK;
}
void get_next(SString T, int *next) {
int i=1;
next[1]=0;
int j=0;
while (i<T[0]) {
if(j==0 || T[i]== T[j]) {
++i; ++j; next[i] = j;
} else j= next[j];
}
}
void get_nextval(SString T, int *next) {
// 求模式串T的next函数修正值并存入数组nextval。
int i = 1;
int j = 0;
next[1] = 0;
while (i<T[0]) {
if (j==0 || T[i]==T[j]) {
++i; ++j;
if (T[i]!=T[j]) next[i] = j;
else next[i] = next[j];
}
else j = next[j];
}
}
int Index(SString S, SString T, int pos) {
int n,m,i;
SString sub;
if(S[0]<T[0])
return -1;
if(pos+1>S[0])
return -1;
//增加函数健壮性,如果串S>串T,则返回错误
if (pos > 0) {
n = StrLength(S);
m = StrLength(T);
i = pos;
while (i <= n-m+1) {
SubString (sub, S, i, m);
if (StrCompare(sub,T) == 0) ++i;
else return i;
}
}
return 0;
}
int Index_KMP(SString S, SString T, int pos) {
if(S[0]<T[0])
return -1;
if(pos+1>S[0])
return -1;
//增加函数健壮性,如果串S>串T,则返回错误
int next[255];
int i = pos;
int j = 1;
//get_next(T, next);
get_nextval(T,next);
//nextval效率更好
while (i <= S[0] && j <= T[0]) {
if (j == 0 || S[i] == T[j]) { // 继续比较后继字符
++i; ++j;
} else j = next[j]; // 模式串向右移动
}
if (j > T[0]) return i-T[0]; // 匹配成功
else return 0;
}
主函数:
void main()
{
SString S1,S2;
printf("请输入字符串1\n");
Into_SString(S1);
printf("请输入字符串2\n");
Into_SString(S2);
//输入字符串
printf("字符串比较的结果为:");
if(StrCompare(S1,S2)==0)
printf("S1=S2\n");
else if(StrCompare(S1,S2)>0)
printf("S1>S2\n");
else if(StrCompare(S1,S2)<0)
printf("S1);
//字符串比较
int value=0,pos=0;
printf("请输入从哪个位置进行匹配\n");
scanf("%d",&pos);
value=Index_KMP(S1,S2,pos);
//value=Index(S1,S2,pos);
//这个算法也可以,但是效率较上面的KMP算法低
if(value==-1)
printf("匹配错误\n");
else
printf("子串位置在主串第%d号元素\n",value);
//字符串匹配
}
一、实验目的及要求
(1)掌握稀疏矩阵的三元组顺序表存储表示;
(2)实现稀疏矩阵的转置运算。
二、实验内容
(1)编程实现稀疏矩阵的三元组顺序表示方法及基本操作的实现(建立、输出、转置等)。
(2)编程实现稀疏矩阵的十字链表存储表示及基本操作的实现(建立、输出等)。
三、实验主要流程、基本操作或核心代码、算法片段(该部分如不够填写,请填写至附页)
Define.h
#define OK 1
#define ERROR 0
#define MAXSIZE 12500
typedef int ElemType;
typedef int Status;
MyTSMatrix.h
#include "Define.h"
#include "stdio.h"
#include "iostream.h"
typedef struct
{
int col,row; //行下标和列下标定义
ElemType value;
}Trible;//定义三元组
typedef struct OLNode{
int i,j;//行下标和列下标
ElemType e;
struct OLNode *right,*down;//行和列的后继链域
}OLNode,*OLink;
typedef struct{
OLink *rhead,*chead;
int mu,nu,tu;//行,列,非零元
}CrossList;
class MyTSMatrix
{
public:
Status CreateSMatrix_OL_HR();
void ShowSMatrix_OL();
Status CreateSMatrix_OL();
void FastTransposeSMatrix();
void TransSMatrix();
void ShowSMatrix();
void CreateSMatrix();
MyTSMatrix(int col,int row)
{
mu=col;
nu=row;
}
virtual ~MyTSMatrix();
private:
Trible data[MAXSIZE+1];//data[0]不用
int mu,nu,tu;
CrossList M;
int OL_m,OL_n,OL_t;
};
MyTSMatrix.cpp
#include "stdio.h"
#include "iostream.h"
#include "MyTSMatrix.h"
#include "Define.h"
#include "malloc.h"
MyTSMatrix::~MyTSMatrix()
{
}
void MyTSMatrix::CreateSMatrix()
{
int i,j,k=1;
ElemType temp;
tu= 0;
cout<<"输入"<<mu<<"行"<<nu<<"列的稀疏矩阵:"<<endl;
for (i=1;i<=mu;i++)
{
for (j=1;j<=nu;j++)
{
cin>>temp;
if (temp!=0)
{
data[k].col = j;//列
data[k].row = i;//行
data[k].value = temp;//赋值
tu++;//非零元个数加1
k++;//data[]下标加1
}
}
}
}
void MyTSMatrix::ShowSMatrix()
{
int i,j;
int pos =1;
for (i=1;i<=mu;i++)
{
for (j=1;j<=nu;j++)
{
if (data[pos].row==i&&data[pos].col==j)
{
cout<<data[pos].value<<" ";
pos++;
}
else
cout<<0<<" ";
}
cout<<endl;
}
}
void MyTSMatrix::TransSMatrix()
{
int p, q, col,T_tu;
Trible *T=new Trible[tu+1];
for (T_tu=1; T_tu<=tu; T_tu++){
T[T_tu].col=data[T_tu].col;
T[T_tu].row=data[T_tu].row;
T[T_tu].value=data[T_tu].value;
}
//复制一个同样大小的三元数组
q = 1;
for (col=1; col<=nu; ++col)
for (p=1; p<=tu; ++p)
if (T[p].row== col) {
data[q].col=T[p].row;
data[q].row=T[p].col;
data[q].value=T[p].value;
++q;
}
//通过遍历复制数组中的值将原数组的信息改变
int temp;
temp=nu;
nu=mu;
mu=temp;
//将类中的mu和nu的值对换
delete T;
}
void MyTSMatrix::FastTransposeSMatrix()
{
int *num= new int[nu];
int t;
for(t=1;t<=nu;t++)
num[t]=0;//num[]数组初始化
for(t=1;t<=tu;++t)
num[data[t].col]++;//把每列的非零元个数进行统计
int *cpot=new int[nu];
cpot[1]=1;
int col;
for(col=2;col<=nu;col++)
cpot[col]=0;//cpot[]数组的初始化
for(col=2;col<=nu;++col)
cpot[col]=cpot[col-1]+num[col-1];//将每列第一个非零元素位置记录来
int T_tu;
Trible *T=new Trible[tu+1];
for (T_tu=1; T_tu<=tu; T_tu++){
T[T_tu].col=data[T_tu].col;
T[T_tu].row=data[T_tu].row;
T[T_tu].value=data[T_tu].value;
}
//复制一个同样大小的三元数组
int p,q;
for(p=1;p<=tu;++p){
col=T[p].col;//记录第p个非零元素的列坐标
q=cpot[col];//在cpot[]数组找到列坐标为col的元素应该在的位置
data[q].col=T[p].row;
data[q].row=T[p].col;
data[q].value=T[p].value;//将对应位置的元素信息进行交换
++cpot[col];//在交换后让cpot[col]元素的位置信息加1
}
int temp;
temp=nu;
nu=mu;
mu=temp;
//将类中的mu和nu的值对换
delete num,cpot,T;//删除申请的num[],cpot[],数组T
}
Status MyTSMatrix::CreateSMatrix_OL()
{
// 创建稀疏矩阵M。采用十字链表存储表示。
OLNode *p,*q;
int i,j,e;
cout<<"请输入你将要输入的稀疏矩阵的行数,列数以及非零元个数:"<<endl;
int m,n,t;
cin>>m>>n>>t;
M.mu=m; M.nu=n; M.tu=t;
OL_m=m; OL_n=n; OL_t=t;
if (!(M.rhead = (OLink *)malloc((m+1)*sizeof(OLink)))) return ERROR;
if (!(M.chead = (OLink *)malloc((n+1)*sizeof(OLink)))) return ERROR;
for(int a=1;a<=m;a++)
M.rhead[a]=NULL;
for(int b=1;b<=n;b++)
M.chead[b]=NULL;// 初始化行列头指针向量;各行列链表为空链表
cout<<"请依次输入非零元的行,列,值:"<<endl;
for ( int c=1; c<=t; c++) {
cin>>i>>j>>e;
if (!(p = (OLNode *)malloc(sizeof(OLNode))))
return ERROR;
p->i=i; p->j=j; p->e=e; p->down=NULL; p->right=NULL; // 新结点
if (M.rhead[i] == NULL || M.rhead[i]->j > j) {
p->right = M.rhead[i];
M.rhead[i]= p; //插入元素的列下标小于原来的元素则往前插
}
else {
for (q=M.rhead[i]; (q->right) && (q->right->j<j); q=q->right);
p->right = q->right; q ->right = p; //否则插入元素插入列数大于自己的那个元素前面
} // 完成行插入
if (M.chead[j] == NULL || M.chead[j]->i > i) {
p->down = M.chead[j]; M.chead[j]= p;
}
else {
for ( q=M.chead[j]; (q->down) && q->down->i <i; q = q->down );
p->down = q->down; q->down = p;
} // 完成列插入
}
return OK;
}
void MyTSMatrix::ShowSMatrix_OL()
{//按行输出
int i,j;
OLNode *p;
for (i=1;i<=OL_m;i++)
{
p=M.rhead[i];
for (j=1;j<=OL_n;j++)
{
if (p!=NULL&&p->j==j)
{
cout<<p->e<<" ";
p=p->right;
}
else
cout<<0<<" ";
}
cout<<endl;
}
}
Status MyTSMatrix::CreateSMatrix_OL_HR()
{
OLNode *p,*q;
int i,j;
cout<<"请输入你将要输入的稀疏矩阵的行数以及列数:"<<endl;
int m,n;
cin>>m>>n;
M.mu=m; M.nu=n;
OL_m=m; OL_n=n; OL_t=0;
if (!(M.rhead = (OLink *)malloc((m+1)*sizeof(OLink)))) return ERROR;
if (!(M.chead = (OLink *)malloc((n+1)*sizeof(OLink)))) return ERROR;
for(int a=1;a<=m;a++)
M.rhead[a]=NULL;
for(int b=1;b<=n;b++) M.chead[b]=NULL;// 初始化行列头指针向量;各行列链表为空链表
cout<<"请输入稀疏矩阵:"<<endl;
ElemType temp;
for (i=1;i<=OL_m;i++)
{
for (j=1;j<=OL_n;j++)
{
cin>>temp;
if (temp!=0)
{
if (!(p = (OLNode *)malloc(sizeof(OLNode)))) return ERROR;
p->i=i; p->j=j; p->e=temp; p->down=NULL; p->right=NULL; // 新结点
if (M.rhead[i] == NULL || M.rhead[i]->j > j) {
p->right = M.rhead[i]; M.rhead[i]= p; //插入元素的列下标小于原来的元素则往前插
}
else {
for (q=M.rhead[i]; (q->right) && (q->right->j<j); q=q->right);
p->right = q->right; q ->right = p; //否则插入元素插入列数大于自己的那个元素前面
} // 完成行插入
if (M.chead[j] == NULL || M.chead[j]->i > i) {
p->down = M.chead[j]; M.chead[j]= p;
}
else {
for ( q=M.chead[j]; (q->down) && q->down->i <i; q = q->down );
p->down = q->down; q->down = p;
} // 完成列插入
OL_t++;
}
}
}
return OK;
}
Main.cpp
#include "stdio.h"
#include "iostream.h"
#include "MyTSMatrix.h"
#include "Define.h"
int main()
{
int row,col;
cout<<"请输入你将要输入的稀疏矩阵的行数以及列数:"<<endl;
cin>>col>>row;
MyTSMatrix S(col,row);
S.CreateSMatrix();
cout<<"输出矩阵:"<<endl;
S.ShowSMatrix();
S.TransSMatrix();
//S.FastTransposeSMatrix();
cout<<"转置后的内容:"<<endl;
S.ShowSMatrix();
//S.CreateSMatrix_OL();
S.CreateSMatrix_OL_HR();
cout<<"输出十字矩阵:"<<endl;
S.ShowSMatrix_OL();
return 0;
}
一、实验目的及要求
(1)通过实验,掌握二叉树的两种基本的存储结构及二叉树的建立、遍历(先序、中序、后序、层次遍历),并加以应用(计算二叉树的高度、统计结点数目等)。
(2)Huffman编码和译码。
二、实验内容
(1)按先序次序输入二叉树中结点的值,建立一棵以二叉链表作存储结构的二叉树,然后按先序、中序、后序、层序分别遍历这棵二叉树,并完成二叉树的相应信息的统计(如各种结点数目、计算高度等)。
(2)建立一棵二叉排序树,然后进行中序遍历,并实现动态查找。
(3)设计一个完整的编/译码系统:针对一篇文档,统计各个字符的出现次数,并为其设计Huffman编码,然后进行译码。
注:(1)为必做题,(2)~(3)为选做题。
三、实验主要流程、基本操作或核心代码、算法片段(该部分如不够填写,请填写至附页)
#include
#include
#include
#include
#include
#define OK 1
#define ERROR 0
#define TURE 1
#define FALSE 0
#define OVERFLOW -1
typedef int Status;
typedef int TElemType;
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;//左右孩子指针
}BiTNode,*BiTree;
//普通二叉树
typedef BiTree ET;
typedef struct QNode{
ET data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front;
QueuePtr rear;
}LinkQueue;
Status InitQueue(LinkQueue &Q)
{
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
if(!Q.front) exit(OVERFLOW);
Q.front->next=NULL;
return OK;
}
Status DestroyQueue(LinkQueue &Q)
{
while(Q.front)
{
Q.rear=Q.front->next;
free(Q.front);
Q.front=Q.rear;
}
return OK;
}
Status EnQueue(LinkQueue &Q,ET e)
{
QueuePtr p;
p=(QueuePtr)malloc(sizeof(QNode));
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
return OK;
}
Status DeQueue(LinkQueue &Q,ET &e)
{
QueuePtr p;
if(Q.front==Q.rear)return ERROR;
p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front;
free(p);
return OK;
}
Status QueueEmpty(LinkQueue Q)
{
if(Q.front==Q.rear)
return OK;
else
return ERROR;
}
Status CreateTree(BiTree &T)
{//按先序次序输入二叉树中结点的值(字符)
//构造二叉链表表示二叉树
TElemType ch;
ch=getchar();
if(ch=='#')
T = NULL;
else
{
if(!(T=(BiTNode*)malloc(sizeof(BiTNode))))
exit(OVERFLOW);
T->data = ch;//生成根节点
CreateTree(T->lchild);//构造左子树
CreateTree(T->rchild);//构造右子树
}
return OK;
}
void PreOrder(BiTree T)
{//先序遍历
if(T!=NULL)
{
cout<<T->data;
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}
void IntOrder(BiTree T)
{//中序
if(T)
{
IntOrder(T->lchild);
cout<<T->data;
IntOrder(T->rchild);
}
}
void PostOrder(BiTree T)
{//后序
if(T)
{
PostOrder(T->lchild);
PostOrder(T->rchild);
cout<<T->data;
}
}
void LevelOrder(BiTree T)
{//层次遍历
LinkQueue Q;
BiTree b;
InitQueue(Q);
if(T)
{
EnQueue(Q,T);
while(!QueueEmpty(Q))
{
DeQueue(Q,b);
cout<<b->data;
if(b->lchild)
EnQueue(Q,b->lchild);
if(b->rchild)
EnQueue(Q,b->rchild);
}
}
}
int TreeDepth(BiTree T)
{//树的高度
int h,lh,rh;
if(!T)
h=0;
else
{
lh = TreeDepth(T->lchild);
rh = TreeDepth(T->rchild);
if(lh>=rh)
h = lh+1;
else
h = rh+1;
}
return h;
}
int Count(BiTree T)
{//结点总数
int num,numl,numr;
if(!T)
num = 0;
else
{
numl = Count(T->lchild);
numr = Count(T->rchild);
num = numl+numr+1;
}
return num;
}
void insert(BiTree &T,TElemType x)
{//插入二叉排序树
if(T==NULL)
{
T=(BiTree)malloc(sizeof(BiTNode));
T->data=x;
T->lchild=NULL;
T->rchild=NULL;
}
else
{
if(x<=T->data)
insert(T->lchild,x);
else
insert(T->rchild,x);
}
}
void CreateBiTree(BiTree &root)
{//创建二叉排序树
TElemType x;
root=NULL;
cin>>x;
while(x!=0)
{
insert(root,x);
cin>>x;
}
}
Status Delete(BiTree &p) {
// 从二叉排序树中删除结点p,并重接它的左或右子树
BiTree q, s;
if (!p->rchild) { // 右子树空则只需重接它的左子树
q = p; p = p->lchild; free(q);
} else if (!p->lchild) { // 只需重接它的右子树
q = p; p = p->rchild; free(q);
} else { // 左右子树均不空
q = p; s = p->lchild;
while (s->rchild) // 转左,然后向右到尽头
{ q = s; s = s->rchild; }
p->data = s->data; // s指向被删结点的“后继”
if (q != p) q->rchild = s->lchild; // 重接*q的右子树
else q->lchild = s->lchild; // 重接*q的左子树
free(s);
}
return TRUE;
} // Delete
#include "IncludeFile.h"
#include "DefineFile.h"
#include "Bitree.h"
#include "Bitree2.h"
#include "LinkQueue.h"
#include "LinkQueueFun.h"
#include "BitreeFun.h"
#include "BitreeFun2.h"
//abc##de#g##f###
//123##45#6##7###
//1 9 8 5 6 7 4 3 2 0
void main()
{
BiTree T;
cout<<"先序创建二叉树"<<endl;
CreateTree(T);
cout<<"先序遍历"<<endl;
PreOrder(T);
cout<<endl;
cout<<"中序遍历"<<endl;
IntOrder(T);
cout<<endl;
cout<<"后序遍历"<<endl;
PostOrder(T);
cout<<endl;
cout<<"层次遍历"<<endl;
LevelOrder(T);
cout<<endl;
cout<<"树的高度为:"<<endl;
cout<<TreeDepth(T)<<endl;
cout<<"结点个数为:"<<endl;
cout<<Count(T)<<endl;
cout<<"创建排序二叉树"<<endl;
cout<<endl;
BiTree T1;
CreateBiTree(T1);
cout<<"中序遍历"<<endl;
IntOrder(T1);
cout<<endl;
free(T);//释放内存
}
一、实验目的及要求
(1)通过完成本实验,掌握图的两种基本的存储结构(邻接矩阵、邻接表),以及图的基本算法实现(建立、遍历),并能运用图结构分析和解决一些实际问题。
(2)本实验训练的要点是:图的两种基本存储结构及各种操作的算法实现(建立、遍历、图的典型应用)。
二、实验内容
(1)建立图的邻接矩阵(或邻接表)存储表示,计算顶点的度(入度、出度)并实现深度优先或广度优先对图进行遍历。
(2)编程实现最小生成树求解的Prim算法。
(3)编程实现AOV网的拓扑排序。
(4)编程实现AOE网的关键路径。
(5)编程实现单源点最短路径的Dijkstra算法。
三、实验主要流程、基本操作或核心代码、算法片段(该部分如不够填写,请填写至附页)
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
typedef int Status;
#define INIFINITY 1000 // 最大值
#define MAX_VERTEX_NUM 20 //最大顶点数
typedef enum{DG,DN,UDG,UDN} GraphKind; //图的四种类型
typedef char VertexType; //顶点类型
typedef bool visited;
typedef struct {
VertexType vexs[MAX_VERTEX_NUM]; //顶点向量
int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//邻接矩阵
int vexnum,arcnum; //顶点数和弧的数目
GraphKind kind; //图的种类
}MGraph;
struct
{
VertexType adjvex;
int lowcost;
}closedge[MAX_VERTEX_NUM];
//辅助数组
Status CreateUDN(MGraph &G){
int i,j,k;
VertexType v1,v2;
int w;
cout<<endl<<"输入图的顶点数和边数:";
cin>>G.vexnum>>G.arcnum;
cout<<endl<<"输入图的顶点信息:";
for (i=0;i<G.vexnum;i++) cin>>G.vexs[i];
for (i=0;i<G.vexnum;i++)
for (j=0;j<G.vexnum;j++) G.arcs[i][j]=INIFINITY;
cout<<endl<<"输入边的信息 v1,v2,w"<<endl;
for (k=0;k<G.arcnum;k++) {
cin>>v1;
cin>>v2;
cin>>w;
i=LovateVex(G,v1);
j=LovateVex(G,v2);
G.arcs[i][j]=w;
G.arcs[j][i]=G.arcs[i][j];
}//for k
return OK;
}//CreateUDN
Status CreateDN(MGraph &G){
int i,j,k;
VertexType v1,v2;
int w;
cout<<endl<<"输入图的顶点数和边数:";
cin>>G.vexnum>>G.arcnum;
cout<<endl<<"输入图的顶点信息:";
for (i=0;i<G.vexnum;i++) cin>>G.vexs[i];
for (i=0;i<G.vexnum;i++)
for (j=0;j<G.vexnum;j++) G.arcs[i][j]=INIFINITY;
cout<<endl<<"输入边的信息 v1,v2,w"<<endl;
for (k=0;k<G.arcnum;k++) {
cin>>v1;
cin>>v2;
cin>>w;
i=LovateVex(G,v1);
j=LovateVex(G,v2);
G.arcs[i][j]=w;
//G.arcs[j][i]=G.arcs[i][j];
}//for k
return OK;
}//CreateDN
Status CreateUDG(MGraph &G){
int i,j,k;
VertexType v1,v2;
//int w;
cout<<endl<<"输入图的顶点数和边数:";
cin>>G.vexnum>>G.arcnum;
cout<<endl<<"输入图的顶点信息:";
for (i=0;i<G.vexnum;i++) cin>>G.vexs[i];
for (i=0;i<G.vexnum;i++)
for (j=0;j<G.vexnum;j++) G.arcs[i][j]=0;
cout<<endl<<"输入边的信息 v1,v2"<<endl;
for (k=0;k<G.arcnum;k++) {
cin>>v1;
cin>>v2;
i=LovateVex(G,v1);
j=LovateVex(G,v2);
G.arcs[i][j]=1;
G.arcs[j][i]=G.arcs[i][j];
}//for k
return OK;
}//CreateUDG
Status CreateDG(MGraph &G){
int i,j,k;
VertexType v1,v2;
//int w;
cout<<endl<<"输入图的顶点数和边数:";
cin>>G.vexnum>>G.arcnum;
cout<<endl<<"输入图的顶点信息:";
for (i=0;i<G.vexnum;i++) cin>>G.vexs[i];
for (i=0;i<G.vexnum;i++)
for (j=0;j<G.vexnum;j++) G.arcs[i][j]=0;
cout<<endl<<"输入边的信息 v1,v2"<<endl;
for (k=0;k<G.arcnum;k++) {
cin>>v1;
cin>>v2;
i=LovateVex(G,v1);
j=LovateVex(G,v2);
G.arcs[i][j]=1;
//G.arcs[j][i]=G.arcs[i][j];
}//for k
return OK;
}//CreateDG
//建立图G的邻接矩阵
Status CreateGraph(MGraph &G){
int kind;
cout<<endl<<"输入图的类型:0-DG,1-DN,2-UDG,3-UDN:"<<endl;
cin>>kind;
G.kind=(GraphKind)kind;
switch (G.kind){
case DG :return CreateDG(G);
case DN :return CreateDN(G);
case UDG :return CreateUDG(G);
case UDN :return CreateUDN(G);
default :return ERROR;
}
}//CreateGraph
//获取对应字符的下标值
int LovateVex(MGraph G,VertexType v)
{
for (int i=0;G.vexs[i]!=v;i++);
return i;
}
//获取出度值
int GetOut(MGraph G,int i)
{
int j;
int sum=0;
for(j=0;j<G.vexnum;j++)
{
if(G.arcs [i][j]!=0&&G.arcs [i][j]!=INIFINITY)
sum++;
}
return sum;
}
//获取入度值
int GetIn(MGraph G,int j)
{
int i;
int sum=0;
for(i=0;i<G.vexnum;i++)
{
if(G.arcs [i][j]!=0&&G.arcs [i][j]!=INIFINITY)
sum++;
}
return sum;
}
//获取度数
int GetInAndOut(MGraph G,int i)
{
int j;
int sum=0;
for(j=0;j<G.vexnum ;j++)
{
if(G.arcs [i][j]!=0&&G.arcs [i][j]!=INIFINITY)
sum++;
}
return sum;
}
//广度搜索
void BFSTraverse(MGraph G)
{
visited visited[MAX_VERTEX_NUM];
int v,u,w;
for(v=0;v<G.vexnum ;v++)
visited[v]=false;
//初始化,将所有点先标记为未访问的状态
LinkQueue Q;
InitQueue(Q);
//辅助队列
for(v=0;v<G.vexnum ;v++)
if(!visited[v])
{
visited[v]=true;
cout<<G.vexs[v];
EnQueue(Q,v);
while(!QueueEmpty(Q))
{
DeQueue(Q,u);
for(w=0;w<G.vexnum ;w++)
{
if((G.arcs [u][w]==1)&&(!visited[w]))
{
visited[w]=true;
cout<<G.vexs [w];
EnQueue(Q,w);
}
}
}
}
}
//深度遍历
void DFS(MGraph G,int v,visited *visited)
{
visited[v]=true;
cout<<G.vexs [v];
for(int w=0;w<G.vexnum ;w++)
{
if((G.arcs [v][w]==1)&&(!visited[w]))
DFS(G,w,visited);
}
}
void DFSTraverse(MGraph G)
{
visited visited[MAX_VERTEX_NUM];
int v;
for(v=0;v<G.vexnum ;v++)
visited[v]=false;
//初始化,将所有点先标记为未访问的状态
for(v=0;v<G.vexnum ;v++)
if(!visited[v])
DFS(G,v,visited);
}
//寻找closedge数组中代价最小的边
int mininum(MGraph G)
{
int min,los;
//因为寻找的最小代价非0
for(int j=0;j<G.vexnum ;j++)
{
if(closedge[j].lowcost!=0)
min=closedge[j].lowcost;
}
//寻找到一个不为0代价
for(j=0;j<G.vexnum ;j++)
{
if(closedge[j].lowcost!=0&&closedge[j].lowcost<=min)
{
min=closedge[j].lowcost;
los=j;
}
}
//代价不为0且代价最小的边
return los;
}
//普里姆算法构造最小生成树
void MiniSpanTree_PRIM(MGraph G,VertexType u)
{
int k=LovateVex(G,u);
for(int j=0;j<G.vexnum ;j++)
if(j!=k)
{
closedge[j].adjvex=u;
closedge[j].lowcost=G.arcs [k][j];
}
closedge[k].adjvex=u;
closedge[k].lowcost=0;
//初始化
for(int i=1;i<G.vexnum ;i++)
{
k=mininum(G);
cout<<closedge[k].adjvex<<"--"<<G.vexs [k]<<"||";
closedge[k].lowcost=0;
for(int j=0;j<G.vexnum ;j++)
{
if(G.arcs [k][j]<closedge[j].lowcost)
{
closedge[j].adjvex=G.vexs [k];
closedge[j].lowcost=G.arcs [k][j];
}
}
//更新closedge数组的值
}
}
void DijkstraPath(MGraph g,int *dist,int *path,int v0) //v0表示源顶点
{
int i,j,k;
bool *visited=(bool *)malloc(sizeof(bool)*g.vexnum );
for(i=0;i<g.vexnum ;i++) //初始化
{
if(g.arcs [v0][i]>0&&i!=v0)
{
dist[i]=g.arcs[v0][i];
path[i]=v0; //path记录最短路径上从v0到i的前一个顶点
}
else
{
dist[i]=INIFINITY; //若i不与v0直接相邻,则权值置为无穷大
path[i]=-1;
}
visited[i]=false;
path[v0]=v0;
dist[v0]=0;
}
visited[v0]=true;
for(i=1;i<g.vexnum;i++) //循环扩展n-1次
{
int min=INIFINITY;
int u;
for(j=0;j<g.vexnum ;j++) //寻找未被扩展的权值最小的顶点
{
if(visited[j]==false&&dist[j]<min)
{
min=dist[j];
u=j;
}
}
visited[u]=true;
for(k=0;k<g.vexnum ;k++) //更新dist数组的值和路径的值
{
if(visited[k]==false&&g.arcs [u][k]>0&&min+g.arcs [u][k]<dist[k])
{
dist[k]=min+g.arcs [u][k];
path[k]=u;
}
}
}
}
void showPath(int *path,int v,int v0) //打印最短路径上的各个顶点
{
stack<int> s;
int u=v;
while(v!=v0)
{
s.push(v);
v=path[v];
}
s.push(v);
while(!s.empty())
{
cout<<s.top()<<" ";
s.pop();
}
}
//输出图G
void PrintGraph(MGraph G){
int v0;
int *dist=(int *)malloc(sizeof(int)*G.vexnum );
int *path=(int *)malloc(sizeof(int)*G.vexnum );
int i,j;
cout<<endl<<"图的顶点数和边数:";
cout<<setw(3)<<G.vexnum<<setw(3)<<G.arcnum;
cout<<endl<<"图的顶点信息:"<<endl;
for (i=0;i<G.vexnum;i++) cout<<setw(3)<<G.vexs[i];
if(G.kind ==DG||G.kind ==DN)
{
cout<<endl<<"图的顶点出度:"<<endl;
for (i=0;i<G.vexnum;i++) cout<<setw(3)<<GetOut(G,i);
cout<<endl<<"图的顶点入度:"<<endl;
for (i=0;i<G.vexnum;i++) cout<<setw(3)<<GetIn(G,i);
}
else
{
cout<<endl<<"图的度数:"<<endl;
for (i=0;i<G.vexnum;i++) cout<<setw(3)<<GetInAndOut(G,i);
}
cout<<endl<<"图的邻接矩阵:"<<endl;
for (i=0;i<G.vexnum;i++){
cout<<endl;
for (j=0;j<G.vexnum;j++)
if (G.arcs[i][j]==INIFINITY)cout<<setw(5)<<"∞";
else cout<<setw(5)<<G.arcs[i][j];
}//for i
cout<<endl;
if(G.kind ==UDG)
{
cout<<endl<<"图的广度遍历:"<<endl;
BFSTraverse(G);
cout<<endl<<"图的深度遍历:"<<endl;
DFSTraverse(G);
cout<<endl;
}
if(G.kind ==DN)
{
cout<<"输入起点(源点):";
cin>>v0; //输入源顶点
DijkstraPath(G,dist,path,v0);
for(i=0;i<G.vexnum ;i++)
{
if(i!=v0)
{
showPath(path,i,v0);
cout<<dist[i]<<endl;
}
}
}
//MiniSpanTree_PRIM(G,G.vexs [2]);
}