0
点赞
收藏
分享

微信扫一扫

《数据结构与算法R》实验指导书(2020)


前言:

🚩 半身浸江,全身如林,所谓万丈深渊,下去也是前程万里。我启程了,你呢?

LPT抱团内卷:​​每日刷题冲冲冲​​

一起做开源(有意私聊)

实验一 线性表

1. 设顺序表A中的数据元素递增有序,试写一程序,将x插入到顺序表的适当位置上,使该表仍然有序。

#include<stdio.h>
#include<stdlib.h>

#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10

/**
* 顺序表结构
*/
typedef struct{
int *elem; // 存储空间基址
int length ; // 列表长度
int listsize; // 储存容量
}SqList;

/**
* 初始化
*/
void InitList(SqList *L){
L->elem = (int *)malloc(LIST_INIT_SIZE*sizeof(int)); // 创建一个空列表
L->length = 0; // 空表长度为0
L->listsize = LIST_INIT_SIZE; // 初始存储容量

}

/**
* 输入
*/
void InputData(SqList *L){
printf("请输入列表元素个数:");
int n;
scanf("%d",&n);
/*判断列表是否需要扩容*/
int *p;
p = L->elem;
if(n > L->listsize){
L->elem = (int*)realloc(L->elem, (L->listsize+LISTINCREMENT)*sizeof(int));
L->listsize += (n + LISTINCREMENT);
}
/*输入列表*/
printf("请输入元素:");
while(n!=0){
scanf("%d", p);
p ++;
n --;
L->length ++;
}

}

/**
* 输出顺序列表
*/
void OutputList(SqList *L){
int i;
int *p = L->elem;
for(i = 0; i<L->length; i ++, p ++) printf("%d ",*p);

}

/**
* 插入元素
*/
void InsertElem(SqList *L,int e){
/*溢出判断*/
if(L->length + 1 > L->listsize){
L->elem = (int*)realloc(L->elem,(L->listsize+LISTINCREMENT)*sizeof(int));
L->listsize += LISTINCREMENT;
}

int *p = L->elem;
int *p_last = L->elem+L->length-1;
/* 查找元素插入的位置*/
while(e > *p&&p<p_last) p++;

int *q ;
for(q = (L->elem)+(L->length)-1; q >= p; q--) *(q+1) = *q;

*p = e;
L->length ++;

}

int main(){

SqList L; // 定义一个顺序表
InitList(&L); // 初始化
InputData(&L); // 输入数据
OutputList(&L); // 显示数据
printf("插入数据:");
int m;
scanf("%d", &m);
InsertElem(&L, m);
printf("\n插入后的顺序表:");
OutputList(&L);

return 0;
}

2. 用单链表ha 存储多项式A(x )=a0+a1x1+a2x2+…+anxn(其中aI为非零系数),用单链表hb 存储多项式B(x )=b0+b1x1+b2x2+…+bmxm(其中bj为非零系数),要求计算C(x )= A(x )+B(x ),结果存到单链表hc中。试写出程序。

3. 设有n个人围坐在一个圆桌周围,现从第s个人开始报数,数到第m的人出列,然后从出列的下一个人重新开始报数,数到m的人又出列,如此重复,直到所有的人全部出列为止。Josephus问题是:对于任意给定的n,m,s,求出按出列次序得到的n个人员的顺序表。

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <malloc.h>


using namespace std;
typedef struct list//链表
{
int date;
struct list *next;
}list,*linklist;
list* l;
void intlist(linklist &l,int n)//构建循环链表
{
l = (linklist)malloc(sizeof(list));//没有头节点
l->next = l;
l->date = 1;
linklist p;
for (int i = n; i > 1; i--)
{
p= (linklist)malloc(sizeof(list));
p->next = l->next;
l->next = p;
p->date = i;

}

}
void out(linklist l, int s, int m,int n)//依次出列
{
list* p = l;
int i ;
for (i = 1;; i++)//寻找s的位置
{
if (p->date == s)
{
break;
}
p = p->next;

}//找出s的位置 p记录

if (m != 1)//当m不等于一时
{
for (int j = 1; j <= n; j++)//有n次出列动作
{
if (j == 1)
{
for (int h = 1; h < m - 1; h++)
{
p = p->next;
}
}
else
{
for (int h = 1; h < m; h++)
{
p = p->next;
}
}
cout << p->next->date << " ";
p->next = p->next->next;
}
}
else
{
for (int j = 1; j <= n; j++)
{
cout << p->date << " ";
p = p->next;
}
}

}
int main()
{
while (1)
{
int n, s, m;
cout << "依次输入 人数 起始位置 长度:";
cin >> n >> s >> m;
if (n < s||n<=0||s<=0||m<=0)
{
cout << "输入错误,请重试!" << endl;
continue;
}
intlist(l, n);
cout << "输出排序:";
out(l, s, m, n);
cout << "\n";
}

return 0;
}

实验二 树

1. 编写递归算法,计算二叉树中叶子结点的数目。

#include<iostream>
using namespace std;
typedef struct TNode//二叉树结构
{
char nodeValue;//结点的值
TNode* left;//左子树
TNode* right;//右子树
}*BiTree;
//中序遍历方式创建二叉树 ,输入#代表该结点为空
void CreateBiTree(BiTree &T){
char nodeValue;
cin>> nodeValue;
//结点非空
if(nodeValue!='.'){
T=new TNode;
T->nodeValue=nodeValue;
CreateBiTree(T->left);
CreateBiTree(T->right);
}
else T=NULL;
}
//计算节点数目
int CountLeaf(BiTree T){
//叶子初始数目为0,使用静态变量
static int LeafNum=0;
if(T)//树非空
{
if(T->left==NULL&&T->right==NULL)//为叶子结点
LeafNum++;//叶子数目加1
else//不为叶子结点
{
CountLeaf(T->left);//递归统计左子树叶子数目
CountLeaf(T->right);//递归统计右子树叶子数目
}
}
return LeafNum;
}
//用来测试的main函数,
int main(){
BiTree T;
int leafNum;
cout<<"请输入中序遍历的二叉树序列如(ABC..DE.G..F...)"<<endl;
CreateBiTree(T);
leafNum=CountLeaf(T);
cout<<"该二叉树中叶子结点数为:"<<leafNum<<endl;
return 0;
}

2. 编写递归算法,在二叉树中求位于先序序列中第K个位置的结点。

#include <stdio.h>  
#include <stdlib.h>
#include <malloc.h>
int i ;
int k ;
int count = 0;
//定义树结构体
struct node{
char info;
struct node *llink,*rlink; //定义 左子树和右子树
};
//用node代替struct
typedef struct node NODE;
//创建 函数creat()
NODE *creat(){
char x;
NODE *p;
scanf("%c",&x); //输入 变量x的地址
printf("%c",x); //输出x
if(x!='.'){ //输入.代表该结点为空,判断结点是否为空

p=(NODE *)malloc(sizeof(NODE));
//分配一个Node类型大小的内存空间,并把分配空间的首地址强制转换成Node *类型的
p->info=x; //x赋值给info
p->llink=creat();
p->rlink=creat();
}
else
p=NULL;
return p;
}
//查找第K个节点数据
int found(NODE* T){
if(T)
{
i++;
if(i==k)//判断输入的K结点是否为对应的结点
printf("结果是 %c\n",T->info);//info储存数据
else
{
//重复调用自身 直到找到K
found(T->llink);
found(T->rlink);
}
}
return 0;
}

int main(){
NODE *T; //定义一个树T
printf("请输入树:\n"); //输入一个 树

T=creat(); //创建遍历
printf("k=");
scanf("%d",&k);//读取要查询的K节点
i=0;
found(T);

}

3. 将上述例题用非递归程序实现。

实验三 图

1.采用邻接表存储结构,编写一个求无向图的连通分量个数的算法。

2.试基于图的深度优先搜索策略编写一程序,判别以邻接表方式存储的有向图中是否存在有顶点Vi到Vj顶点的路径(i≠j)。

#include <stdio.h>
#include <stdlib.h>
#define MAXN 100 //最大边数
struct ArcNode{//弧结点
int ajdVex; //弧终点指针位置
ArcNode* next; //下一条弧的指针
};
struct Node{//顶点结点
ArcNode* Arc; //指向依附该顶点的弧指针
};
struct Graph{//邻接表
Node adjlist[MAXN]; //点集
bool visited[MAXN]; //是否被遍历
int n,m; //顶点数和弧数
};
Graph *G = (Graph*)malloc(sizeof(Graph));
int i,j,k;bool hasPath = false;
void createLink(){//创建邻接表
printf("请输入顶点数n 弧数m:");
scanf("%d %d",&G->n,&G->m);
printf("创建的所有点:");
for(i=0;i<G->n;i++){ G->adjlist[i].Arc = 0;printf("V%d ",i);}printf("\n");
for(j=0;j<G->m;j++){
printf("第%d条弧起点编号、终点编号:",j+1);
scanf("%d %d",&i,&k);
ArcNode *p = (ArcNode*)malloc(sizeof(ArcNode));
p->ajdVex = k; //将边所指向的点编号赋值
p->next = G->adjlist[i].Arc;
G->adjlist[i].Arc = p;
}
}
void print_Graph(){//输出邻接表
ArcNode *p;
for(i=0;i<G->n;i++){
p = G->adjlist[i].Arc;
printf("V%d",i);
while(p){
printf("->V%d",p->ajdVex);
p = p->next;
}printf("\n");
}
}
void existPath(int d,int z){//两点是否连通
G->visited[d] = true;
ArcNode *p = G->adjlist[d].Arc;
if(d == z)hasPath = true;
while(p){
if(p->ajdVex==z)hasPath = true;
if(!G->visited[p->ajdVex])existPath(p->ajdVex,z);
p = p->next;
}
}

void setFlase(){//visited置零
hasPath = false;
for(i=0;i<G->n;i++) G->visited[i] = false;
}
int main(){
createLink();
while(true){printf("\n");
printf("请输入操作(1.判断路径 2.退出):");
int choice; scanf("%d",&choice);setFlase();

if(choice == 1){
printf("请输入两点编号:"); scanf("%d %d",&i,&k);existPath(i,k);
if(hasPath){printf("两点连通!\n");//print_Path(i,k);
}
else printf("两点不连通!\n");
}
if(choice == 2)break;
}
return 0;
}

3.在上述例题中,如改用邻接表的方式存储图,试编一程序实现上述算法。
顶点表nodelist的每个元素包含四个字段:

info

mark

pre

out

其中mark为布尔类型,用来标记顶点是否被访问过。开始时,所有元素的mark字段为false,每访问过一个顶点,则mark字段置为true。info为顶点值,pre为访问路径上该顶点的前驱顶点的序号,out指向该顶点的出边表。

实验四 查找

1. 编写程序实现下面运算:在二叉排序树中查找关键字为key的记录。

2. 试将折半查找的算法改写成递归算法。

#include <stdio.h>  
int bin_search(int key[],int low, int high,int k)
{
int mid;
if(low>high)
return -1;
else{
mid = (low+high) / 2;
if(key[mid]==k)
return mid;
if(k>key[mid])
return bin_search(key,mid+1,high,k); /*在序列的后半部分查找*/
else
return bin_search(key,low,mid-1,k); /*在序列的前半部分查找*/
}
}

int main()
{
int n , i , addr;
int A[10] = {2,3,5,7,8,10,12,15,19,21};
//printf("The contents of the Array A[10] are\n");
//for(i=0;i<10;i++)
//printf("%d ",A[i]); /*显示数组A中的内容*/
printf("\nPlease input a interger for search\n");
scanf("%d",&n); /*输入待查找的元素*/
addr = bin_search(A,0,9,n);
if(-1 != addr) /*查找成功*/
printf("%d is at the %dth unit is array A\n ",n,addr);
else printf("There is no %d in array A\n",n); /*查找失败*/
getchar();
return 0;
}

实验五 内排序

1.设计一个用链表表示的直接选择排序算法,并用程序实现。
算法说明:已知待排序初始序列用单链表存贮,头指针head指向第一个结点,从这个待排序列中找出最小结点,插入head之后,用r来指示。r以前为已排序序列,r以后为未排序序列。再从未排序序列中找出最小结点插入r的后面,让r指向这个结点。反复执行这个过程,直到排好序。

#include<stdio.h>
#include<malloc.h>
#include<conio.h>
typedef struct VNode
{
int info;
struct VNode *next_node;
}Node;
void input(Node*head, int number) //输入待排序的列表
{
if(number!=0)
{
int i;
Node *t;
t=(Node *)malloc(sizeof(Node));
head->next_node=t;
scanf("%d",&i);
t->info=i;
input(t,number-1);
}
}
void output(Node*head, int count) //输出排序列表
{
Node *t;
if(count!=0)
{
t=head->next_node;
printf("%d ",t->info);
output(t,count-1);
}
}
void select(Node*head, int num)
{
int tem=0;
if(num!=0)
{
int min_node;
Node *t;
Node *r;
Node *q;
t=head->next_node; //指向下一个结点
r= head->next_node; //指向下一个结点
q=head; //指向头结点
min_node= t->info; //选出最小的
for(int i=0;i<num;i++)
{
if(min_node>t->info)
{
min_node= t->info;
r=t;
tem=i;
}
t=t->next_node;
}
for(int j=0;j<tem;j++)
q=q->next_node;
q->next_node=r->next_node;
r->next_node=head->next_node;
head->next_node=r;
select(head->next_node,num-1);
}
}
int main()
{
int num;
Node *head;
head=( Node *)malloc(sizeof(Node));
printf("请输入序列数据的个数:");
scanf("%d",&num);
printf("请输入序列的数据:\n");
input(head,num);
printf("\n选择排序后的序列为:\n");
select(head,num);
output(head,num);
getch();
}

2.对N个关键字取整数的记录进行整序,以使所有关键字为非负数的记录排在关键字为负数的记录之前,要求使用最少的附加空间,且算法的时间复杂度为O(N)。

#include <stdio.h>
#include <malloc.h>
#include <Windows.h>
//排序函数
void Sort(int* a,int m){
int i=0;
int j=m-1;
int temp;
while(i<=j){
while(i<m&&a[i]>=0){
i++;
}
while(j>=0&&a[j]<0){
j--;
}
if(i<j){
temp=a[i];
a[i]=a[j];
a[j]=temp;
i++;
j--;
}
}

}
int main(){
int n,i;
int* p;
printf("请输入数据有待整序个数(必须大于1):\n");
scanf("%d",&n);
while(n<2){
printf("你输入的数值不合理,请重新输入:\n");
scanf("%d",&n);
}
p=(int*)malloc(n*sizeof(int));
printf("请输入数据:\n");
for(i=0;i<n;i++){
scanf("%d",&p[i]);
}
Sort(p,n);
printf("整序后的数据为:\n");
for(i=0;i<n;i++){
printf("%-4d",p[i]);
}
printf("\n");
system("pause");
return 0;
}


举报

相关推荐

0 条评论