数据结构实验代码

抽象数据类型的表示与实现

一、实验目的及要求
(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.表达式的语法检查(括号的匹配)
头文件123和上题相同
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与上两题相同
头文件4typedef 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]);
}

你可能感兴趣的:(C)