本文最后更新于:2 个月前
《数据结构》上机实验内容和要求 通过上机实验加深对课程内容的理解,提高程序设计、开发及调试能力。本实验指导书适用于16学时《数据结构法》实验课,实验项目具体内容如下:
layout: pages title: 数据结构与算法实验指导书 author: 谭自财 date: 2021-03-21 07:21:35 categories: 数据结构与算法 tags:
实验报告要求
请按照评分标准和报告模板要求,提交实验报告电子版文件。
👦实验一、顺序表的实现及应用 一、实验目的 了解和掌握线性表的顺序存储结构;掌握用C语言上机调试线性表的基本方法;掌握线性表的基本操作:插入、删除、查找以及线性表合并等运算在顺序存储结构和链接存储结构上的运算,以及对相应算法的性能分析。
二、实验要求 给定一段程序代码,程序代码所完成的功能为:
(1)建立一个线性表;
(2)依次输入数据元素1,2,3,4,5,6,7,8,9,10;
(3)删除数据元素5;
(4)依次显示当前线性表中的数据元素。假设该线性表的数据元素个数在最坏情况下不会超过100个,要求使用顺序表。
程序中有3处错误的地方,有标识,属于逻辑错误,对照书中的代码仔细分析后,要求同学们修改错误的代码,修改后上机调试得到正确的运行结果。
三、程序代码 6 #include < stdio. h>
# include "stdlib.h"
# define MaxSize 100
typedef int DataType;
typedef struct
{
DataType list[ MaxSize] ;
int size;
} SeqList;
void ListInitiate ( SeqList * L)
{
L-> size = 0 ;
}
int ListLength ( SeqList L)
{
return L. size;
}
int ListInsert ( SeqList * L, int i, DataType x)
{
int j;
if ( L-> size >= MaxSize)
{
printf ( "顺序表已满无法插入! \\n" ) ;
return 0 ;
}
else if ( i < 0 || i > L-> size )
{
printf ( "参数i不合法! \\n" ) ;
return 0 ;
}
else
{
for ( j = L-> size; j >= i; j-- ) L-> list[ j+ 1 ] = L-> list[ j] ;
L-> list[ i] = x;
L-> size ++ ;
return 1 ;
}
}
int ListDelete ( SeqList * L, int i, DataType * x)
{
int j;
if ( L-> size <= 0 )
{
printf ( "顺序表已空无数据元素可删! \\n" ) ;
return 0 ;
}
else if ( i < 0 || i > L-> size- 1 )
{
printf ( "参数i不合法" ) ;
return 0 ;
}
else
{
* x = L-> list[ i] ;
for ( j = i + 1 ; j <= L-> size- 1 ; j++ ) L-> list[ j- 1 ] = L-> list[ j] ;
L-> size-- ;
return 1 ;
}
}
int ListGet ( SeqList L, int i, DataType * x)
{
if ( i < 0 || i > L. size- 1 )
{
printf ( "参数i不合法! \\n" ) ;
return 0 ;
}
else
{
* x = L. list[ i] ;
return 1 ;
}
}
void ListMerge ( SeqList L1, SeqList L2, SeqList * L3)
{
int ai= 0 , bi= 0 ;
int i= 0 , j= 0 , k= 0 ;
ListInitiate ( L3) ;
while ( i <= ListLength ( L1) - 1 && j <= ListLength ( L2) - 1 )
{
ListGet ( L1, i, & ai) ;
ListGet ( L2, j, & bi) ;
if ( ai<= bi)
{
ListInsert ( L3, k++ , ai) ;
++ i;
}
else {
ListInsert ( L3, k++ , bi) ;
++ j;
}
}
while ( i<= ListLength ( L1) - 1 )
{
ListGet ( L1, i++ , & ai) ;
ListInsert ( L3, ++ k, ai) ;
}
while ( j<= ListLength ( L2) - 1 )
{
ListGet ( L2, j++ , & bi) ;
ListInsert ( L3, k++ , bi) ;
}
}
int main ( void )
{ SeqList myList;
SeqList list;
SeqList listAll;
int i , x;
ListInitiate ( & myList) ;
ListInitiate ( & list) ;
ListInitiate ( & listAll) ;
for ( i = 0 ; i < 10 ; i++ )
ListInsert ( & myList, i, i+ 1 ) ;
ListDelete ( & myList, 4 , & x) ;
for ( int j = 0 ; j < 10 ; ++ j) {
ListInsert ( & list, j, j+ 21 ) ;
}
ListMerge ( myList, list, & listAll) ;
for ( i = 0 ; i < ListLength ( myList) ; i++ )
{
ListGet ( myList, i, & x) ;
printf ( "%d\\n" , x) ;
}
printf ( "\\n" ) ;
for ( i = 0 ; i < ListLength ( list) ; i++ )
{
ListGet ( list, i, & x) ;
printf ( "%d\\n" , x) ;
}
for ( i = 0 ; i < ListLength ( listAll) ; i++ ) {
ListGet ( listAll, i, & x) ;
printf ( "%d\\n" , x) ;
}
}
合并函数_WriteByLiyihan void ListMerge ( SeqList L1, SeqList L2, SeqList * L3)
{
int ai= 0 , bi= 0 ;
int i= 0 , j= 0 , k= 0 ;
ListInitiate ( L3) ;
while ( i <= ListLength ( L1) - 1 && j <= ListLength ( L2) - 1 )
{
ListGet ( L1, i, & ai) ;
ListGet ( L2, j, & bi) ;
if ( ai<= bi)
{
ListInsert ( L3, k++ , ai) ;
++ i;
}
else {
ListInsert ( L3, k++ , bi) ;
++ j;
}
}
while ( i<= ListLength ( L1) - 1 )
{
ListGet ( L1, i++ , & ai) ;
ListInsert ( L3, ++ k, ai) ;
}
while ( j<= ListLength ( L2) - 1 )
{
ListGet ( L2, j++ , & bi) ;
ListInsert ( L3, k++ , bi) ;
}
}
四、实验任务 1.改正上述程序中的错误。
2.编写合并函数,将两个有序线性表合并为一个有序表并在主函数中加以测试。
3.完成实验报告的撰写。
实验二 链表的实现及应用 一、实验目的 了解和掌握线性表的链式存储结构;掌握用C语言上机调试线性表的基本方法;掌握线性表的基本操作:插入、删除、查找以及线性表合并等运算在顺序存储结构和链接存储结构上的运算,以及对相应算法的性能分析。
二、实验要求 给定一段程序代码,程序代码所完成的功能为:
(1)建立一个线性表;
(2)依次输入数据元素1,2,3,4,5,6,7,8,9,10;
(3)删除数据元素5;
(4)依次显示当前线性表中的数据元素。假设该线性表的数据元素个数在最坏情况下不会超过100个,要求使用单链表。
程序中有3处错误的地方,有标识,属于逻辑错误,对照书中的代码仔细分析后,要求同学们修改错误的代码,上机调试并得到正确的运行结果。
三、程序代码: # include <stdio.h>
# include <stdlib.h>
# include <malloc.h>
typedef int DataType;
typedef struct Node
{
DataType data;
struct Node * next;
} SLNode;
void ListInitiate ( SLNode * * head)
{
if ( ( * head = ( SLNode * ) malloc ( sizeof ( SLNode) ) ) == NULL ) exit ( 1 ) ;
( * head) -> next = NULL ;
}
int ListLength ( SLNode * head)
{
SLNode * p = head;
int size = 0 ;
while ( p-> next != NULL )
{
p = p-> next;
size ++ ;
}
return size;
}
int ListInsert ( SLNode * head, int i, DataType x)
{
SLNode * p, * q;
int j;
p = head;
j = - 1 ;
while ( p-> next != NULL && j < i - 1 )
{
p = p-> next;
j++ ;
}
if ( j != i - 1 )
{
printf ( "插入位置参数错!" ) ;
return 0 ;
}
if ( ( q = ( SLNode * ) malloc ( sizeof ( SLNode) ) ) == NULL ) exit ( 1 ) ;
q-> data = x;
q-> next = p-> next;
p-> next = q;
return 1 ;
}
int ListDelete ( SLNode * head, int i, DataType * x)
{
SLNode * p, * s;
int j;
p = head;
j = - 1 ;
while ( p-> next != NULL && p-> next-> next!= NULL && j < i - 1 )
{
p = p-> next;
j++ ;
}
if ( j != i - 1 )
{
printf ( "删除位置参数错!" ) ;
return 0 ;
}
q= p-> next;
* x = s-> data;
p-> next = s-> next;
free ( s) ;
return 1 ;
}
int ListGet ( SLNode * head, int i, DataType * x)
{
SLNode * p;
int j;
p = head;
j = - 1 ;
while ( p-> next != NULL && j < i)
{
p = p-> next; j++ ;
}
if ( j != i)
{
printf ( "取元素位置参数错!" ) ;
return 0 ;
}
* x = p-> data;
return 1 ;
}
void Destroy ( SLNode * * head)
{
SLNode * p, * p1;
p = * head;
while ( p != NULL )
{
p1 = p;
p = p-> next;
free ( p1) ;
}
* head = NULL ;
}
void main ( void )
{
SLNode * head;
int i , x;
ListInitiate ( & head) ;
for ( i = 0 ; i < 10 ; i++ )
{
if ( ListInsert ( head, i, i+ 1 ) == 0 )
{
printf ( "错误! \\n" ) ;
rturn;
}
}
if ( ListDelete ( head, 4 , & x) == 0 )
{
printf ( "错误! \\n" ) ;
return ;
}
for ( i = 0 ; i < ListLength ( head) ; i++ )
{
if ( ListGet ( head, i, & x) == 0 )
{
printf ( "错误! \\n" ) ;
return ;
}
else printf ( "%d " , x) ;
}
Destroy ( & head) ;
}
三、实验任务 1.改正上述程序中的错误。
2.编写合并函数,将两个有序的单链表合并成一个有序单链表。
3.完成实验报告的撰写。
实验三、栈的实现及应用 一、实验目的 1.掌握栈的存储表示和实现
2.掌握栈的基本操作实现。
3.掌握栈在解决实际问题中的应用。
二、实验要求 问题描述:设计一个程序,演示用算符优先法对算术表达式求值的过程。利用算符优先关系,实现对算术四则混合运算表达式的求值。
(1)输入的形式:表达式,例如2*(3+4)#
包含的运算符只能有’+’ 、’-‘ 、’*’ 、’/‘ 、’(‘、 ‘)’,“#”代表输入结束符;
(2)输出的形式:运算结果,例如2*(3+4)=14; (3)程序所能达到的功能:对表达式求值并输出。
三、解题参考思路 为了实现用栈计算算数表达式的值,需设置两个工作栈:用于存储运算符的栈opter,以及用于存储操作数及中间结果的栈opnd。
算法基本思想如下:
(1)首先将操作数栈opnd设为空栈,而将’#’作为运算符栈opter的栈底元素,这样的目的是判断表达式是否求值完毕。
(2)依次读入表达式的每个字,表达式须以’#’结,读入字符若是操作数则入栈opnd,读入字符若是运算符,则将此运算符c与opter的栈顶元素top比较优先级后执行相应的操作,具体操作如下:
若top的优先级小于c,即top<c,则将c直接入栈opter,并读入下一字符赋值给c;
若top的优先级等于c,即top=c,则弹出opter的栈顶元素,并读入下一字符赋值给c,这一步目的是进行括号操作;
若top优先级高于c,即top>c,则表明可以计算,此时弹出opnd的栈顶两个元素,并且弹出opter栈顶的的运算符,计算后将结果放入栈opnd中。直至opter的栈顶元素和当前读入的字符均为’#’,此时求值结束。
算符间的优先关系如下表所示(表来源:严蔚敏《数据结构》):
表中需要注意的是θ1为opter的栈顶元素,θ2为从表达式中读取的操作符,此优先级表可以用二维数组实现。
图例:
比较算符优先关系代码示例:
1. int getIndex ( char theta)
2. {
3. int index = 0 ;
4. switch ( theta)
5. {
6. case '+' :
7. index = 0 ;
8. break ;
9. case '-' :
10. index = 1 ;
11. break ;
12. case '*' :
13. index = 2 ;
14. break ;
15. case '/' :
16. index = 3 ;
17. break ;
18. case '(' :
19. index = 4 ;
20. break ;
21. case ')' :
22. index = 5 ;
23. break ;
24. case '#' :
25. index = 6 ;
26. default : break ;
27. }
28. return index;
29. }
30.
31. char getPriority ( char theta1, char theta2)
32. {
33. const char priority[ ] [ 7 ] =
34. {
35. { '>' , '>' , '<' , '<' , '<' , '>' , '>' } ,
36. { '>' , '>' , '<' , '<' , '<' , '>' , '>' } ,
37. { '>' , '>' , '>' , '>' , '<' , '>' , '>' } ,
38. { '>' , '>' , '>' , '>' , '<' , '>' , '>' } ,
39. { '<' , '<' , '<' , '<' , '<' , '=' , '0' } ,
40. { '>' , '>' , '>' , '>' , '0' , '>' , '>' } ,
41. { '<' , '<' , '<' , '<' , '<' , '0' , '=' } ,
42. } ;
43.
44. int index1 = getIndex ( theta1) ;
45. int index2 = getIndex ( theta2) ;
46. return priority[ index1] [ index2] ;
47. }
四、实验任务 认真阅读与理解实验内容的具体要求,参考教材相关章节,结合实验内容的要求,编写实验程序并上机调试与测试,完成实验报告的撰写。
五、实验思路 创建两个结构体,一个做栈,一个是栈的节点
typedef struct node
{
int data;
struct node * next;
} Node;
typedef struct stack
{
Node * top;
int count;
} Stack;
包括栈的基本操作
栈的初始化
栈空的判断
压栈
出栈
取栈顶元素
清空栈
int InitStack ( Stack * s)
{
s-> top = NULL ;
s-> count= 0 ;
return OK;
}
int EmptyStack ( Stack * s)
{
return ( s-> count == 0 ) ? OK : ERROR;
}
int Push ( Stack * s, int e)
{
Node * p = ( Node * ) malloc ( sizeof ( Node) ) ;
if ( p == NULL )
{
return ERROR;
}
p-> data = e;
p-> next = s-> top;
s-> top = p;
s-> count++ ;
return OK;
}
int GetTop ( Stack * s)
{
if ( NULL == s-> top)
{
return ERROR;
}
return ( s-> top-> data) ;
}
int Pop ( Stack * s)
{
int e;
if ( NULL == s-> top)
{
return ERROR;
}
Node * p = s-> top;
e = p-> data;
s-> top = p-> next;
free ( p) ;
s-> count-- ;
return e;
}
int ClearStack ( Stack * s)
{
if ( s-> count <= 0 ) {
printf ( "栈已空" ) ;
return ERROR;
}
Node * p = s-> top;
while ( s-> count > 0 )
{
p= s-> top;
s-> top= s-> top-> next;
free ( p) ;
s-> count-- ;
}
s-> top== NULL ;
return OK;
}
int Priority ( char s)
{
switch ( s)
{
case '(' :
return 3 ;
case '*' :
case '/' :
return 2 ;
case '+' :
case '-' :
return 1 ;
default :
return 0 ;
}
}
判断符号还是数字,数字直接入栈
判断符号
如果是(符号栈为空||符号栈栈顶为’(‘&&当前符号不是’)’||栈顶优先级低于当前符号),则入栈不计算
如果’()’内无其他运算符,即最栈顶是(当前操作符号是),直接(出栈
如果(字符串扫描完成且符号栈不为空)||(当前运算符优先级低于栈顶元素)
int main ( ) {
Stack num, opt;
char l = '*' ;
char str[ 100 ] = { 0 } ;
int i = 0 , tmp = 0 , j;
if ( InitStack ( & num) != OK || InitStack ( & opt) != OK) {
printf ( "Init Failure!\\n" ) ;
exit ( 1 ) ;
}
while ( l != '#' ) {
printf ( "Please Input Operator :\\n" ) ;
scanf ( "%s" , str) ;
if ( str[ 0 ] == '#' ) return 0 ;
while ( str[ i] != '\\0' || EmptyStack ( & opt) != OK) {
if ( str[ i] >= '0' && str[ i] <= '9' ) {
tmp = tmp * 10 + str[ i] - '0' ;
i++ ;
if ( str[ i] < '0' || str[ i] > '9' ) {
Push ( & num, tmp) ;
tmp = 0 ;
}
} else {
if ( ( EmptyStack ( & opt) == OK) || ( GetTop ( & opt) == '(' && str[ i] != ')' ) || Priority ( str[ i] ) > Priority ( GetTop ( & opt) ) )
{
Push ( & opt, str[ i] ) ;
i++ ;
continue ;
}
if ( GetTop ( & opt) == '(' && str[ i] == ')' )
{
Pop ( & opt) ;
i++ ;
continue ;
}
if ( ( str[ i] == '\\0' && EmptyStack ( & opt) != OK) || ( str[ i] == ')' && GetTop ( & opt) != '(' ) || Priority ( str[ i] ) <= Priority ( GetTop ( & opt) ) )
{
switch ( Pop ( & opt) ) {
case '+' :
Push ( & num, Pop ( & num) + Pop ( & num) ) ;
break ;
case '-' :
j = Pop ( & num) ;
Push ( & num, Pop ( & num) - j) ;
break ;
case '*' :
Push ( & num, Pop ( & num) * Pop ( & num) ) ;
break ;
case '/' :
j = Pop ( & num) ;
Push ( & num, Pop ( & num) / j) ;
}
continue ;
}
}
}
printf ( "%d" , Pop ( & num) ) ;
printf ( "\\n" ) ;
i= 0 ;
}
return 0 ;
}
首先创建两个栈opnd、opter,设为opnd为空栈,而将’#’作为运算符栈opter的栈底元素,以判断表达式是否求值完毕。
依次读入表达式的每个字,表达式须以’#’结,读入字符若是操作数则入栈opnd,读入字符若是运算符,则将此运算符c与opter的栈顶元素top比较优先级后执行相应的操作,具体操作如下:
若top的优先级小于c,即top<c,则将c直接入栈opter,并读入下一字符赋值给c;
若top的优先级等于c,即top=c,则弹出opter的栈顶元素,并读入下一字符赋值给c,这一步目的是进行括号操作;
若top优先级高于c,即top>c,则表明可以计算,此时弹出opnd的栈顶两个元素,并且弹出opter栈顶的的运算符,计算后将结果放入栈opnd中。直至opter的栈顶元素和当前读入的字符均为’#’,此时求值结束。
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <strings.h>
# define OK 1
# define ERROR 0
# define MAX_LINE 100
typedef struct nodeNum
{
int data;
struct node * next;
} Node;
typedef struct stack
{
Node * top;
int count;
} Stack;
int InitStack ( Stack * l)
{
l-> top = NULL ;
l-> count= 0 ;
return OK;
}
int EmptyStack ( Stack * s)
{
return ( s-> count == 0 ) ? OK : ERROR;
}
int Push ( Stack * s, int e)
{
Node * p = ( Node * ) malloc ( sizeof ( Node) ) ;
if ( p == NULL )
{
return ERROR;
}
p-> data = e;
p-> next = s-> top;
s-> top = p;
s-> count++ ;
return OK;
}
int GetTop ( Stack * s)
{
if ( NULL == s-> top)
{
return ERROR;
}
return ( s-> top-> data) ;
}
int Priority ( char s)
{
switch ( s)
{
case '(' :
return 3 ;
case '*' :
case '/' :
return 2 ;
case '+' :
case '-' :
return 1 ;
case '#' :
return 0 ;
default :
return - 1 ;
}
}
int Pop ( Stack * s)
{
int e;
if ( NULL == s-> top)
{
return ERROR;
}
Node * p = s-> top;
e = p-> data;
s-> top = p-> next;
free ( p) ;
s-> count-- ;
return e;
}
int ClearStack ( Stack * s)
{
if ( s-> count <= 0 ) {
printf ( "栈已空" ) ;
return ERROR;
}
Node * p = s-> top;
while ( s-> count > 0 )
{
p= s-> top;
s-> top= s-> top-> next;
free ( p) ;
s-> count-- ;
}
s-> top== NULL ;
return OK;
}
int main ( ) {
char str[ MAX_LINE] = { "123" } ;
int i= 0 , temp= 0 , j= 0 ;
Stack opnd, opter;
if ( InitStack ( & opnd) != OK || InitStack ( & opter) != OK) {
printf ( "初始化错误,请关闭后重试" ) ;
exit ( 1 ) ;
}
Push ( & opter, '#' ) ;
do {
printf ( "请输入计算表达式,并以#结尾\\n" ) ;
scanf ( "%s" , str) ;
} while ( str[ 0 ] == '#' || str[ strlen ( str) - 1 ] != '#' ) ;
while ( str[ i] != '#' || GetTop ( & opter) != '#' )
{
if ( str[ i] >= '0' && str[ i] <= '9' )
{
temp = temp * 10 + str[ i] - '0' ;
i++ ;
if ( str[ i] < '0' || str[ i] > '9' )
{
Push ( & opnd, temp) ;
temp = 0 ;
}
} else {
if ( ( GetTop ( & opter) == '#' ) || ( GetTop ( & opter) == '(' && str[ i] != ')' ) || Priority ( str[ i] ) > Priority ( GetTop ( & opter) ) )
{
Push ( & opter, str[ i] ) ;
i++ ;
continue ;
}
if ( GetTop ( & opter) == '(' && str[ i] == ')' )
{
Pop ( & opter) ;
i++ ;
continue ;
}
if ( ( str[ i] == '#' && GetTop ( & opter) != '#' ) || ( str[ i] == ')' && GetTop ( & opter) != '(' ) || Priority ( str[ i] ) <= Priority ( GetTop ( & opter) ) )
{
switch ( Pop ( & opter) ) {
case '+' :
Push ( & opnd, Pop ( & opnd) + Pop ( & opnd) ) ;
break ;
case '-' :
j = Pop ( & opnd) ;
Push ( & opnd, Pop ( & opnd) - j) ;
break ;
case '*' :
Push ( & opnd, Pop ( & opnd) * Pop ( & opnd) ) ;
break ;
case '/' :
j = Pop ( & opnd) ;
Push ( & opnd, Pop ( & opnd) / j) ;
}
continue ;
}
}
}
printf ( "%d" , Pop ( & opnd) ) ;
printf ( "\\n" ) ;
return 0 ;
}
实验四、队列的实现及应用
一、实验目的
1.掌握队列的存储表示和实现。
2.掌握队列的基本操作实现。
3.掌握队列在解决实际问题中的应用。
二、实验要求
利用队列模拟服务台前的排队现象问题。
某银行有一个客户办理业务站,在单位时间内随机地有客户到达,设每位客户的业务办理时间是某个范围的随机值。设只有一个窗口,一位业务人员,要求程序模拟统计在设定时间内,业务人员的总空闲时间和客户的平均等待时间。假定模拟数据已按客户到达的先后顺序依次存于某个正文数据文件中,对应每位客户有两个数据:到达时间和需要办理业务的时间,文本文件内容如:10 20 10 10 45 5 55 10 58 15 65 10
三、解题参考思路 与栈相对应,队列是一种先进先出的线性表。它只允许在表的一端进行插入,而在另一端进行删除元素。允许插入的一端称队尾,允许删除的一端称队头。插入与删除分别称为入队与出队。队列示意图如下图所示:
一、数据描述(结构体定义)
typedef struct {
int arrive;
int treat;
} QNODE;
typedef struct node {
QNODE data;
Struct node * next;
} LNODE, * QueuePtr;
typedef struct {
QueuePtr front ;
QueuePtr rear ;
} LinkQueue;
二、存取操作(队列操作函数)
int InitQueue ( LinkQueue * Q) {
QueuePtr p = ( QueuePtr) malloc ( sizeof ( LNODE) ) ;
if ( p == NULL ) {
printf ( "初始化失败\\n" ) ;
return ERROR;
}
Q-> rear = Q-> front = p;
Q-> front-> next = NULL ;
return OK;
}
int EnQueue ( LinkQueue* Q, QNODE data) {
QueuePtr p = ( QueuePtr) malloc ( sizeof ( LNODE) ) ;
p-> data = data;
p-> next = NULL ;
Q-> rear-> next = p;
Q-> rear = p;
return OK;
}
int DeQueue ( LinkQueue * Q, QNODE * e) {
if ( Q-> front == Q-> rear) {
printf ( "队列为空,删除失败\\n" ) ;
return ERROR;
}
LNODE* p;
p = Q-> front-> next;
* e = p-> data;
Q-> front-> next = p-> next;
if ( Q-> rear == p) Q-> rear = Q-> front;
free ( p) ;
return OK;
}
三、主函数流程
{
设置统计初值:业务员等待时间,客户总的待时间,客户总人数等
设置当前时钟clock时间为0 ;
打开数据文件,准备读;
printf ( "\\nenterfilename:" ) ;
scanf ( "%s" , Fname) ;
读入第一位客户信息于暂存变量中;
do {
if ( 等待队列为空,并且还有客户) {
累计业务员总等待时间;
时钟推进到暂存变量中的客户的到达时间;
暂存变量中的客户信息进队;
读取下一位客户信息于暂存变量;
}
从等待队列出队一位客户;
累计客户人数;
将该客户的等待时间累计到客户的总等待时间;
设定当前客户的业务办理结束时间;
while ( 下一位客户的到达时间在当前客户处理结束之前,并且还有客户)
{
暂存变量中的客户信息进队;
读取下一位客户信息于暂存变量;
}
时钟推进到当前客户办理结束时间;
} while ( 还有未处理的客户) ;
计算统计结果,并输出;
void main ( ) {
QNODE curret, temp;
int dwait= 0 , clock= 0 , wait= 0 , count= 0 , have= 0 , finish;
LinkQueue BankQueue;
InitQueue ( & BankQueue) ;
printf ( "\\n请输入读取文件的文件名\\n" ) ;
scanf ( "%s" , file_name) ;
fopen_s ( & fp, file_name, "r" ) ;
while ( fp == NULL ) {
printf ( "当前目录没有此文件,请重新输入文件名" ) ;
scanf ( "%s" , file_name) ;
}
have = fscanf_s ( fp, "%d %d" , & temp. arrive, & temp. treat) ;
do {
if ( BankQueue. front-> next == NULL && have== 2 )
{
dwait+= temp. arrive- clock;
clock= temp. arrive;
EnQueue ( & BankQueue, temp) ;
have= fscanf ( fp, "%d %d" , & temp. arrive, & temp. treat) ;
}
count++ ;
DeQueue ( & BankQueue, & curret) ;
wait+= clock- curret. arrive;
finish= clock+ curret. treat;
while ( have== 2 && temp. arrive<= finish)
{
EnQueue ( & BankQueue, temp) ;
have= fscanf ( fp, "%d%d" , & temp. arrive, & temp. treat) ;
}
clock= finish;
} while ( have== 2 || BankQueue. front-> next!= NULL ) ;
printf ( "结果:业务员等待时间%d\\n客户平均等待时间%f\\n" , dwait, ( double ) wait/ count) ;
printf ( "模拟总时间:%d,\\n客户人数:%d,\\n总等待时间:%d\\n" , clock, count, wait) ;
getchar ( ) ;
}
# include <stdio.h>
# include <stdlib.h>
# include <malloc.h>
# define MAX_FILE_NAME_LENGHT 120
# define OK 1
# define ERROR 0
typedef struct {
int arrive;
int treat;
} QNODE;
typedef struct node {
QNODE data;
struct node * next;
} LNODE, * QueuePtr;
typedef struct {
QueuePtr front ;
QueuePtr rear ;
} LinkQueue;
char file_name[ MAX_FILE_NAME_LENGHT] ;
FILE * fp;
int InitQueue ( LinkQueue * Q) {
QueuePtr p = ( QueuePtr) malloc ( sizeof ( LNODE) ) ;
if ( p == NULL ) {
printf ( "初始化失败\\n" ) ;
return ERROR;
}
Q-> rear = Q-> front = p;
Q-> front-> next = NULL ;
return OK;
}
int EnQueue ( LinkQueue* Q, QNODE data) {
QueuePtr p = ( QueuePtr) malloc ( sizeof ( LNODE) ) ;
p-> data = data;
p-> next = NULL ;
Q-> rear-> next = p;
Q-> rear = p;
return OK;
}
int DeQueue ( LinkQueue * Q, QNODE * e) {
if ( Q-> front == Q-> rear) {
printf ( "队列为空,删除失败\\n" ) ;
return ERROR;
}
LNODE* p;
p = Q-> front-> next;
* e = p-> data;
Q-> front-> next = p-> next;
if ( Q-> rear == p) Q-> rear = Q-> front;
free ( p) ;
return OK;
}
void main ( ) {
QNODE curret, temp;
int dwait= 0 , clock= 0 , wait= 0 , count= 0 , have= 0 , finish;
LinkQueue BankQueue;
InitQueue ( & BankQueue) ;
printf ( "\\n请输入读取文件的文件名\\n" ) ;
scanf ( "%s" , file_name) ;
fopen_s ( & fp, file_name, "r" ) ;
while ( fp == NULL ) {
printf ( "当前目录没有此文件,请重新输入文件名" ) ;
scanf ( "%s" , file_name) ;
}
have = fscanf_s ( fp, "%d %d" , & temp. arrive, & temp. treat) ;
do {
if ( BankQueue. front-> next == NULL && have== 2 )
{
dwait+= temp. arrive- clock;
clock= temp. arrive;
EnQueue ( & BankQueue, temp) ;
have= fscanf ( fp, "%d %d" , & temp. arrive, & temp. treat) ;
}
count++ ;
DeQueue ( & BankQueue, & curret) ;
wait+= clock- curret. arrive;
finish= clock+ curret. treat;
while ( have== 2 && temp. arrive<= finish)
{
EnQueue ( & BankQueue, temp) ;
have= fscanf ( fp, "%d%d" , & temp. arrive, & temp. treat) ;
}
clock= finish;
} while ( have== 2 || BankQueue. front-> next!= NULL ) ;
printf ( "结果:业务员等待时间%d\\n客户平均等待时间%f\\n" , dwait, ( double ) wait/ count) ;
printf ( "模拟总时间:%d,\\n客户人数:%d,\\n总等待时间:%d\\n" , clock, count, wait) ;
getchar ( ) ;
}
四、实验任务 认真阅读与理解实验内容的具体要求,参考教材相关章节,结合实验内容的要求,编写实验程序并上机调试与测试,完成实验报告的撰写。
五、注意点
*fopen()函数原型为FILE * =fopen(char* ,char ** );
**fopen_s函数更改为int fopen_s(FILE ,char ,char *);
fscanf_s函数原型为 int fscanf_s(FILE *,char * ,dataType *……)
fscanf_s函数原型为 int fscanf_s(FILE *,char * ,dataType *……)
被打开的文件必须与exe文件夹放在一起,或者指定绝对路径
在使用fscanf前确保传入的FILE*不是NULL,否则会出现错误
# include <stdio.h>
int main ( ) {
char file_name[ 150 ] = "text.txt" ;
int data;
int data2;
FILE * fp;
int l = 1 ;
fopen_s ( & fp, file_name, "r" ) ;
if ( fp != NULL ) {
printf ( "OK" ) ;
fscanf_s ( fp, "%d %d" , & data2, & data) ;
printf ( "%d %d" , data, data2) ;
} else {
printf ( "Fause" ) ;
}
}
实验五、二叉树操作及应用 一、 实验目的 掌握二叉树的定义、结构特征,以及各种存储结构的特点及使用范围,各种遍历算法。掌握用指针类型描述、访问和处理二叉树的运算。掌握前序或中序的非递归遍历算法。
二、相关知识 遍历 二叉树的遍历主要有三种:
(1)先(根)序遍历(根左右)
(2)中(根)序遍历(左根右)
(3)后(根)序遍历(左右根)
举个例子:
https://img-blog.csdn.net/20180704200305280?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0ODQwMTI5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70
先(根)序遍历(根左右):A B D H E I C F J K G
中(根)序遍历(左根右) : D H B E I A J F K C G
后(根)序遍历(左右根) : H D I E B J K F G C A
class Node:
def __init__ ( self, dat, left= None, right= None) :
self. data = dat
self. left = left
self. right = right
def rebuild ( rear, center) :
if not rear:
return
cur = Node ( rear[ - 1 ] )
index = center. index ( rear[ - 1 ] )
cur. left = rebuild ( rear[ : index] , center[ : index] )
cur. right = rebuild ( rear[ index: - 1 ] , center[ index + 1 : ] ) #rear[ index: - 1 ] 是到倒数第二个数
return cur
def pre_order ( t) :
if t == None:
return
print ( t. data)
pre_order ( t. left)
pre_order ( t. right)
if __name__ == "__main__" :
rear = [ 'd' , 'a' , 'b' , 'e' , 'c' ]
center = [ 'd' , 'e' , 'b' , 'a' , 'c' ]
t = rebuild ( rear, center)
pre_order ( t)
二、 实验要求 有如下二叉树:
程序代码给出了该二叉树的链式存储结构的建立、前序、中序、后序遍历的算法,同时也给出了查询“E”是否在二叉树里的代码。代码有三处错误,有标识,属于逻辑错误,对照书中的代码仔细分析后,请修改了在电脑里运行。
# include <stdlib.h>
# include <stdio.h>
typedef char DataType;
typedef struct Node
{
DataType data;
struct Node * leftChild;
struct Node * rightChild;
} BiTreeNode;
void Initiate ( BiTreeNode * * root)
{
- root = ( BiTreeNode * ) malloc ( sizeof ( BiTreeNode) ) ;
( * root) -> leftChild = NULL ;
( * root) -> rightChild = NULL ;
}
void Destroy ( BiTreeNode * * root)
{
if ( ( * root) != NULL && ( * root) -> leftChild != NULL )
Destroy ( & ( * root) -> leftChild) ;
if ( ( * root) != NULL && ( * root) -> rightChild != NULL )
Destroy ( & ( * root) -> rightChild) ;
free ( * root) ;
}
BiTreeNode * InsertLeftNode ( BiTreeNode * curr, DataType x)
{
BiTreeNode * s, * t;
if ( curr == NULL ) return NULL ;
t = curr-> leftChild;
s = ( BiTreeNode * ) malloc ( sizeof ( BiTreeNode) ) ;
s-> data = x;
s-> leftChild = t;
s-> rightChild = NULL ;
curr-> leftChild = s;
return curr-> leftChild;
}
BiTreeNode * InsertRightNode ( BiTreeNode * curr, DataType x)
{
BiTreeNode * s, * t;
if ( curr == NULL ) return NULL ;
t = curr-> rightChild;
s = ( BiTreeNode * ) malloc ( sizeof ( BiTreeNode) ) ;
s-> data = x;
s-> rightChild = t;
s-> leftChild = NULL ;
curr-> rightChild = s;
return curr-> rightChild;
}
void PreOrder ( BiTreeNode * t, void visit ( DataType item) )
{
if ( t != NULL )
{
visit ( t-> data) ;
PreOrder ( t-> rightChild, visit) ;
PreOrder ( t-> leftChild, visit) ;
}
}
void InOrder ( BiTreeNode * t, void visit ( DataType item) )
{
if ( t != NULL )
{
InOrder ( t-> leftChild, visit) ;
InOrder ( t-> rightChild, visit) ;
visit ( t-> data) ;
}
}
void PostOrder ( BiTreeNode * t, void visit ( DataType item) )
{
if ( t != NULL )
{
visit ( t-> data) ;
PostOrder ( t-> leftChild, visit) ;
PostOrder ( t-> rightChild, visit) ;
}
}
void Visit ( DataType item)
{
printf ( "%c " , item) ;
}
BiTreeNode * Search ( BiTreeNode * root, DataType x)
{
BiTreeNode * find= NULL ;
if ( root!= NULL )
{
if ( root-> data== x)
find= root;
else
{
find= Search ( root-> leftChild, x) ;
if ( find== NULL )
find= Search ( root-> rightChild, x) ;
}
}
return find;
}
void main ( void )
{
BiTreeNode * root, * p, * pp, * find;
char x= 'E' ;
Initiate ( & root) ;
p = InsertLeftNode ( root, 'A' ) ;
p = InsertLeftNode ( p, 'B' ) ;
p = InsertLeftNode ( p, 'D' ) ;
p = InsertRightNode ( p, 'G' ) ;
p = InsertRightNode ( root-> leftChild, 'C' ) ;
pp = p;
InsertLeftNode ( p, 'E' ) ;
InsertRightNode ( pp, 'F' ) ;
printf ( "前序遍历:" ) ;
PreOrder ( root-> leftChild, Visit) ;
printf ( "\\n中序遍历:" ) ;
InOrder ( root-> leftChild, Visit) ;
printf ( "\\n后序遍历:" ) ;
PostOrder ( root-> leftChild, Visit) ;
find= Search ( root, x) ;
if ( find!= NULL )
printf ( "\\n数据元素%c在二叉树中 \\n" , x) ;
else
printf ( "\\n数据元素%c不在二叉树中 \\n" , x) ;
Destroy ( & root) ;
}
三、 实验任务: 1.改正程序错误。
2.编写二叉树的前序(或中序)的非递归遍历算法并进行测试。
#include
using namespace std;
stack<BiTreeNode*> s;
BiTreeNode *p;
s.push(p);
s.top();
s.pop();
s.empty()_
3.完成实验报告的撰写。
实验六、图的遍历操作及应用
掌握有向图和无向图的概念;掌握邻接矩阵和邻接链表建立图的存储结构;掌握DFS及BFS对图的遍历操作;了解图结构在人工智能、工程等领域的广泛应用。
二、 实验要求*
采用邻接矩阵和邻接链表作为图的存储结构,完成有向图和无向图的DFS和BFS操作。本实验给出了示例程序,其中共有4处错误,错误段均有标识,属于逻辑错误。请认真理解程序,修改程序代码,并在电脑上调试运行。
三、 DFS和BFS 的基本思想*
深度优先搜索法DFS的基本思想: *从图G中某个顶点Vo出发,首先访问Vo,然后选择一个与Vo相邻且没被访问过的顶点Vi访问,再从Vi出发选择一个与Vi相邻且没被访问过的顶点Vj访问,……依次继续。如果当前被访问过的顶点的所有邻接顶点都已被访问,则回退到已被访问的顶点序列中最后一个拥有未被访问的相邻顶点的顶点W,从W出发按同样方法向前遍历。直到图中所有的顶点都被访问。
广度优先算法BFS的基本思想: *从图G中某个顶点Vo出发,首先访问Vo,然后访问与Vo相邻的所有未被访问过的顶点V1,V2,……,Vt;再依次访问与V1,V2,……,Vt相邻的起且未被访问过的的所有顶点。如此继续,直到访问完图中的所有顶点。
四、
# include "stdio.h"
\#include"stdlib.h"
\#define MaxVertexNum 100
typedef struct {
char vexs[ MaxVertexNum] ;
int edges* * [ MaxVertexNum] ( notion:
int n, e;
} MGraph;
void CreatMGraph ( MGraph * G)
{
int i, j, k;
char a;
printf ( "Input VertexNum(n) and EdgesNum(e): " ) ;
scanf ( "%d,%d" , & G-> n, & G-> e) ;
scanf ( "%c" , & a) ;
printf ( "Input Vertex string:" ) ;
for ( i= 0 ; i< G-> n; i++ )
{
scanf ( "%c" , & a) ;
G-> vexs[ i] = a;
}
for ( i= 0 ; i< G-> n; i++ )
for ( j= 0 ; j< G-> n; j++ )
G-> edges* * [ i] ( notion:
printf ( "Input edges,Creat Adjacency Matrix\n" ) ;
for ( k= 0 ; k< G-> e; k++ ) {
scanf ( "%d%d" , & i, & j) ;
G-> edges* * [ i] ( notion:
G-> edges* * [ j] ( notion:
}
}
typedef enum { FALSE, TRUE} Boolean;
Boolean visited[ MaxVertexNum] ;
void DFSM ( MGraph * G, int i)
{
int j;
printf ( "%c" , G-> vexs[ i] ) ;
visited[ i] = TRUE;
for ( j= 0 ; j< G-> n; j++ )
if ( G-> edges* * [ i] ( notion:
DFSM ( G, j) ;
}
void DFS ( MGraph * G)
{
int i;
for ( i= 0 ; i< G-> n; i++ )
visited[ i] = FALSE;
for ( i= 0 ; i< G-> n; i++ )
if ( ! visited[ i] )
DFS ( G, i) ;
}
void BFS ( MGraph * G, int k)
{
int i, j, f= 0 , r= 0 ;
int cq[ MaxVertexNum] ;
for ( i= 0 ; i< G-> n; i++ )
visited[ i] = FALSE;
for ( i= 0 ; i<= G-> n; i++ )
cq[ i] = - 1 ;
printf ( "%c" , G-> vexs[ k] ) ;
visited[ k] = TRUE;
cq[ r] = k;
while ( cq[ f] != - 1 ) {
i= cq[ f] ; f= f+ 1 ;
for ( j= 0 ; j< G-> n; j++ )
if ( G-> edges* * [ i] ( notion:
printf ( "%c" , G-> vexs[ j] ) ;
visited[ j] = FALSE; r= r+ 1 ; cq[ r] = j;
}
}
}
void main ( )
{
MGraph * G;
G= ( MGraph * ) malloc ( sizeof ( MGraph) ) ;
CreatMGraph ( G) ;
printf ( "Print Graph DFS: " ) ;
DFS ( G) ;
printf ( "\n" ) ;
printf ( "Print Graph BFS: " ) ;
BFS ( G, 3 ) ;
printf ( "\n" ) ; }
VertexNum(n) and EdgesNum(e): 8,9
Input Vertex string: 01234567
Input edges,Creat Adjacency Matrix
0 1
0 2
1 3
1 4
2 5
2 6
3 7
4 7
5 6
Print Graph DFS: 01374256
Print Graph BFS: 31704256
\#include"stdio.h"
\#include"stdlib.h"
\#define MaxVertexNum 50
typedef struct node {
int adjvex;
struct node * next;
} EdgeNode;
typedef struct vnode {
char vertex;
EdgeNode * firstedge;
} VertexNode;
typedef VertexNode AdjList[ MaxVertexNum] ;
typedef struct {
AdjList adjlist;
int n, e;
} ALGraph;
void CreatALGraph ( ALGraph * G)
{
int i, j, k;
char a;
EdgeNode * s;
printf ( "Input VertexNum(n) and EdgesNum(e): " ) ;
scanf ( "%d,%d" , & G-> n, & G-> e) ;
scanf ( "%c" , & a) ;
printf ( "Input Vertex string:" ) ;
for ( i= 0 ; i< G-> n; i++ )
{
scanf ( "%c" , & a) ;
G-> adjlist[ i] . vertex= a;
G-> adjlist[ i] . firstedge= NULL ;
}
printf ( "Input edges,Creat Adjacency List\n" ) ;
for ( k= 0 ; k< G-> e; k++ ) {
scanf ( "%d%d" , & i, & j) ;
s= ( EdgeNode * ) malloc ( sizeof ( EdgeNode) ) ;
s-> adjvex= j;
s-> next= G-> adjlist[ i] . firstedge;
G-> adjlist[ i] . firstedge= s;
s= ( EdgeNode * ) malloc ( sizeof ( EdgeNode) ) ;
s-> adjvex= i;
s-> next= G-> adjlist[ j] . firstedge;
G-> adjlist[ j] . firstedge= s;
}
}
typedef enum { FALSE, TRUE} Boolean;
Boolean visited[ MaxVertexNum] ;
void DFSM ( ALGraph * G, int i)
{
EdgeNode * p;
printf ( "%c" , G-> adjlist[ i] . vertex) ;
visited[ i] = TRUE;
p= G-> adjlist[ i] . firstedge;
while ( p) {
if ( ! visited[ p-> adjvex] )
DFS ( G, p-> adjvex) ;
p= p-> next;
}
}
void DFS ( ALGraph * G)
{
int i;
for ( i= 0 ; i< G-> n; i++ )
visited[ i] = FALSE;
for ( i= 0 ; i< G-> n; i++ )
if ( ! visited[ i] )
DFSM ( G, i) ;
}
void BFS ( ALGraph * G, int k)
{
int i, f= 0 , r= 0 ;
EdgeNode * p;
int cq[ MaxVertexNum] ;
for ( i= 0 ; i< G-> n; i++ )
visited[ i] = FALSE;
for ( i= 0 ; i<= G-> n; i++ )
cq[ i] = - 1 ;
printf ( "%c" , G-> adjlist[ k] . vertex) ;
visited[ k] = TRUE;
cq[ r] = k;
while ( cq[ f] != - 1 )
{
i= cq[ f] ; f= f+ 1 ;
p= G-> adjlist[ i] . firstedge;
while ( p)
{
if ( ! visited[ p-> adjvex] ) {
printf ( "%c" , G-> adjlist[ p-> adjvex] . vertex) ;
visited[ p-> adjvex] = TRUE;
r= r+ 1 ; cq[ r] = p-> adjvex;
}
p= p-> next-> next;
}
}
}
void main ( )
{
int i;
ALGraph * G;
G= ( ALGraph * ) malloc ( sizeof ( ALGraph) ) ;
CreatALGraph ( G) ;
printf ( "Print Graph DFS: " ) ;
DFS ( G) ;
printf ( "\n" ) ;
printf ( "Print Graph BFS: " ) ;
BFS ( G, 3 ) ;
printf ( "\n" ) ;
}
Input VertexNum(n) and EdgesNum(e): 8,9
Input Vertex string: 01234567
Input edges,Creat Adjacency List
0 1
0 2
1 3
1 4
2 5
2 6
3 7
4 7
5 6
Print Graph DFS: 02651473
Print Graph BFS: 37140265
二、 实验任务*
\1. 改正程序中的错误并调试通过,测试并完成实验报告的撰写。
\2. 选做题,编写程序输出该无向网络的最小生成树以及该最小生成树的所有边。
实验七、查找算法的实现 一、实验目的
掌握顺序和二分查找算法 的基本思想及其实现方法。
二、实验要求
问题描述:对给定的任意数组(设其长度为n),分别用顺序和二分查找方法在此数组中查找与给定值k相等的元素。
顺序查找基本思想: 从查找表的一端开始,逐个将记录的关键字值和给定值进行比较,如果某个记录的关键字值和给定值相等,则称查找成功;否则,说明查找表中不存在关键字值为给定值的记录,则称查找失败。
二分查找基本思想: 先取查找表的中间位置的关键字值与给定关键字值作比较,若它们的值相等,则查找成功;如果给定值比该记录的关键字值大,说明要查找的记录一定在查找表的后半部分,则在查找表的后半部分继续使用折半查找;若给定值比该记录的关键字值小,说明要查找的记录一定在查找表的前半部分,则在查找表的前半部分继续使用折半查找。…直到查找成功,或者直到确定查找表中没有待查找的记录为止,即查找失败。
两者比较:
(1)顺序查找的查找效率很低;但是对于待查记录的存储结构没有任何要求,既适用于顺序存储,又适用于链式存储;当待查表中的记录个数较少时,采用顺序查找法较好。
(2)二分查找的平均查找长度较小,查找速度快;但它只能用于顺序存储,不能用于链式存储;且要求表中的记录是有序的。对于不常变动的有序表,采用折半查找法是较为理想的。
三、算法思想与算法描述
1、顺序查找,在顺序表R[0..n-1]中查找关键字为k的记录,成功时返回找到的记录位置,失败时返回-1,具体的算法如下所示:
int SeqSearch ( SeqList R[ ] , int n, KeyType k)
{
int i= 0 ;
while ( i< n&& R[ i] . key!= k)
{
printf ( "%d" , R[ i] . key) ;
i++ ;
}
if ( i>= n)
return - 1 ;
else
{
printf ( "%d" , R[ i] . key) ;
return i;
}
}
程序代码
# include <stdio.h>
# define KeyType int
# define MAX_SIZE 10
typedef struct {
int oder;
KeyType key;
} SeqList;
int SeqSearch ( SeqList R[ ] , int n, KeyType k)
{
int i= 0 ;
while ( i<= n&& R[ i] . key!= k)
{
i++ ;
}
if ( i > n)
return - 1 ;
else
{
printf ( "%d!" , R[ i] . key) ;
return i;
}
}
int main ( ) {
SeqList source[ ] = { { 0 , 9 } , { 1 , 13 } , { 2 , 15 } , { 3 , 7 } , { 4 , 45 } , { 5 , 32 } , { 6 , 56 } , { 7 , 89 } , { 8 , 60 } , { 9 , 36 } } ;
int finder;
int result= - 1 ;
printf ( "程序开始***************************\\n请输入查找内容:" ) ;
scanf ( "%d" , & finder) ;
result= SeqSearch ( source, 9 , finder) ;
if ( result == - 1 ) printf ( "未查找到相关信息" ) ;
else printf ( "所查找元素下标值为%d" , result) ;
return 0 ;
}
2、二分查找,在有序表R[0..n-1]中进行二分查找,成功时返回记录的位置,失败时返回-1,具体的算法如下:
int BinSearch ( SeqList R[ ] , int n, KeyType k)
{
int low= 0 , high= n- 1 , mid, count= 0 ;
while ( low<= high)
{
mid= ( low+ high) / 2 ;
printf ( "第%d次查找:在[ %d ,%d]中找到元素R[%d]:%d\\n " , ++ count, low, high, mid, R[ mid] . key) ;
if ( R[ mid] . key== k)
return mid;
if ( R[ mid] . key> k)
high= mid- 1 ;
else
low= mid+ 1 ;
}
return - 1 ;
}
# include <stdio.h>
# define KeyType int
# define MAX_SIZE 10
typedef struct {
int oder;
KeyType key;
} SeqList;
int BinSearch ( SeqList R[ ] , int n, KeyType k)
{
int low= 0 , high= n- 1 , mid, count= 0 ;
while ( low<= high)
{
mid= ( low+ high) / 2 ;
printf ( "第%d次查找:在[ %d ,%d]中找到元素R[%d]:%d\\n " , ++ count, low, high, mid, R[ mid] . key) ;
if ( R[ mid] . key== k)
return mid;
if ( R[ mid] . key> k)
high= mid- 1 ;
else
low= mid+ 1 ;
}
return - 1 ;
}
int main ( ) {
SeqList source[ ] = { { 0 , 5 } , { 1 , 7 } , { 2 , 9 } , { 3 , 12 } , { 4 , 15 } , { 5 , 18 } , { 6 , 20 } , { 7 , 22 } , { 8 , 25 } , { 9 , 30 } , { 10 , 100 } } ;
int finder;
printf ( "*********************程序开始***************************\\n" ) ;
int result= - 1 ;
printf ( "请输入查找内容:" ) ;
scanf ( "%d" , & finder) ;
while ( finder != '-1' ) {
result= BinSearch ( source, 10 , finder) ;
if ( result == - 1 ) printf ( "未查找到相关信息\\n" ) ;
else printf ( "所查找元素下标值为%d\\n" , result) ;
printf ( "请输入查找内容:" ) ;
scanf ( "%d" , & finder) ;
}
return 0 ;
}
C方式实现 #include < stdio. h>
#define KeyType int
#define MAX_SIZE 10
typedef struct{
int oder;
KeyType key;
} SeqList ;
int SeqSearch ( SeqList R [ ] , int n, KeyType k)
{
int i= 0 ;
while ( i<= n&& R [ i] . key!= k)
{
i++ ;
}
if ( i > n)
return - 1 ;
else
{
printf ( "%d!" , R [ i] . key) ;
return i;
}
}
int BinSearch ( SeqList R [ ] , int n, KeyType k)
{
int low= 0 , high= n- 1 , mid, count= 0 ;
while ( low<= high)
{
mid= ( low+ high) / 2 ;
printf ( "第%d次查找:在[ %d ,%d]中找到元素R[%d]:%d\\n " , ++ count, low, high, mid, R [ mid] . key) ;
if ( R [ mid] . key== k)
return mid;
if ( R [ mid] . key> k)
high= mid- 1 ;
else
low= mid+ 1 ;
}
return - 1 ;
}
int interpolationSearch ( SeqList R [ ] , int n, KeyType k)
{
int low= 0 , high= n- 1 , mid, count= 0 ;
while ( low < high) {
mid = low + ( high - low) * ( k - R [ low] . key) / ( R [ high] . key - R [ low] . key) ;
printf ( "第%d次查找:在[ %d ,%d]中找到元素R[%d]:%d\\n " , ++ count, low, high, mid, R [ mid] . key) ;
if ( k > R [ mid] . key) {
low = mid + 1 ;
} else if ( k < R [ mid] . key) {
high = mid - 1 ;
} else {
return mid;
}
}
return - 1 ;
return - 1 ;
}
int main ( ) {
SeqList source1[ ] = { { 0 , 9 } , { 1 , 13 } , { 2 , 15 } , { 3 , 7 } , { 4 , 45 } , { 5 , 32 } , { 6 , 56 } , { 7 , 89 } , { 8 , 60 } , { 9 , 36 } } ;
SeqList source2[ ] = { { 0 , 5 } , { 1 , 7 } , { 2 , 9 } , { 3 , 12 } , { 4 , 15 } , { 5 , 18 } , { 6 , 20 } , { 7 , 22 } , { 8 , 25 } , { 9 , 30 } , { 10 , 100 } } ;
SeqList * source;
int finder;
int size;
int way;
int data;
printf ( "程序开始***************************\\n" ) ;
int result= - 1 ;
printf ( "请输入查找内容:" ) ;
scanf ( "%d" , & finder) ;
printf ( "请选择查找方式:\\n1:顺序查找\\n2:折半查找\\n3:插值查找" ) ;
scanf ( "%d" , & way) ;
printf ( "请选择待查找数组" ) ;
scanf ( "%d" , & data) ;
if ( data == 1 ) {
source = source1;
size= 9 ;
} else if ( data == 2 ) {
source = source2;
size = 10 ;
}
while ( finder != '-1' ) {
switch ( way) {
case 1 : result= SeqSearch ( source, size, finder) ; break ;
case 2 : result= BinSearch ( source, size, finder) ; break ;
case 3 : result= interpolationSearch ( source, size, finder) ; break ;
default : printf ( "输入错误,程序结束" ) ;
}
if ( result == - 1 ) printf ( "未查找到相关信息\\n" ) ;
else printf ( "所查找元素下标值为%d\\n" , result) ;
printf ( "请输入查找内容:" ) ;
scanf ( "%d" , & finder) ;
printf ( "请选择查找方式:\\n1:顺序查找\\n2:折半查找\\n3:插值查找" ) ;
scanf ( "%d" , & way) ;
}
return 0 ;
}
Java方法实现 package com. finder. oder ;
import java. util. Scanner ;
public class Main {
public static void main ( String args[ ] ) {
int [ ] data = { 9 , 13 , 15 , 7 , 45 , 32 , 56 , 89 , 60 , 36 } ;
int finder;
int way;
int result= - 1 ;
System . out. println ( "请输入要查找的数据(int)" ) ;
Scanner input = new Scanner ( System . in) ;
finder = input. nextInt ( ) ;
way = input. nextInt ( ) ;
System . out. println ( "请选择查找方法\\n1:顺序查找\\n2:优化顺序查找\\n3:折半查找\\n4.插值查找" ) ;
switch ( way) {
case 1 : result = sequentialSearch ( data, finder) ; break ;
case 2 : result = sequentialSearch2 ( data, finder) ; break ;
case 3 : result = binarySearch ( data, finder) ; break ;
case 4 : result = interpolationSearch ( data, finder) ; break ;
default : System . out. println ( "输入错误,程序结束" ) ;
}
if ( result != - 1 ) System . out. println ( "下标为" + result) ;
else System . out. println ( "未查找到此数据" ) ;
}
public static int sequentialSearch ( int [ ] a, int key) {
for ( int i = 0 ; i < a. length; i++ ) {
if ( a[ i] == key)
return i;
}
return - 1 ;
}
public static int sequentialSearch2 ( int [ ] a, int key) {
int index = a. length - 1 ;
a[ 0 ] = key;
while ( a[ index] != key) {
index-- ;
}
return index;
}
public static int binarySearch ( int [ ] a, int key) {
int low, mid, high;
low = 0 ;
high = a. length - 1 ;
while ( low <= high) {
mid = ( high + low) / 2 ;
if ( key > a[ mid] ) {
low = mid + 1 ;
} else if ( key < a[ mid] ) {
high = mid - 1 ;
} else {
return mid;
}
}
return - 1 ;
}
public static int interpolationSearch ( int [ ] a, int key) {
int low, mid, high;
low = 0 ;
high = a. length - 1 ;
while ( low < high) {
mid = low + ( high - low) * ( key - a[ low] ) / ( a[ high] - a[ low] ) ;
if ( key > a[ mid] ) {
low = mid + 1 ;
} else if ( key < a[ mid] ) {
high = mid - 1 ;
} else {
return mid;
}
}
return - 1 ;
}
}
四、实验任务
认真阅读与理解实验内容的具体要求,参考教材相关章节,编写实验程序并上机调试与测试,完成实验报告的撰写。
1.已知含有10个整数的查找表如下:(9,13,15,7,45,32,56,89,60,36),从键盘上输入一个整数,用顺序查找的方法在查找表中查找该整数。若存在,输出该元素的下标值,否则,给出相应的信息。
2.对有序数据表(5,7,9,12,15,18,20,22,25,30,100),编写程序按折半查找方法查找12和28。
实验八、排序算法的实 一、实验目的
掌握常用的排序方法,并掌握用高级语言实现排序算法的方法;
深刻理解排序的定义和各种排序方法的特点,并能加以灵活应用;
了解各种方法的排序过程及其时间复杂度的分析方法。
二、实验要求 统计成绩:给出n个学生的考试成绩表,每条信息由姓名和分数组成,试设计一个算法:
(1) 按分数高低次序,打印出每个学生在考试中获得的名次,分数相同的为同一名次;
(2) 按名次列出每个学生的姓名与分数。
三、实验步骤 1.定义结构体。 typedef struct student {
char name[ 8 ] ;
int score;
} studentImform, * studentPtr;
typedef struct student {
char name[ 8 ] ;
int score;
} studentImform, * studentPtr;
2.定义结构体数组。
struct student students[ MAX_SIZE] ;
studentImform students[ MAX_SIZE] ;
studentPtr students = ( studentPtr) malloc ( sizeof ( studentImform ) ) ;
studentPtr students = ( studentPtr) malloc ( MAX_SIZE* sizeof ( studentImform ) ) ;
struct student Students[ MAX_SIZE] ;
studentImform Students[ MAX_SIZE] ;
studentImform Students[ N] ;
studentPtr Students = ( studentPtr) malloc ( sizeof ( studentImform ) ) ;
studentPtr Students = ( studentPtr) malloc ( sizeof ( studentImform ) * MAX_SIZE) ;
studentPtr Students = ( studentPtr) malloc ( sizeof ( studentImform ) * N) ;
3.编写主程序,对数据进行排序。 4.要求至少采用两种排序算法实现,如直接插入排序、快速排序等算法。 4.1直接插入排序基本思想
排序过程:默认初始数组下标为0的数字为有序序列,每次从后续数组中顺序拿一个数字,将这个数字放到前面的有序序列中,放的位置要确保放完之后依旧是有序的。
将n个元素的数列分为已有序和无序两个部分,
插入排序过程示例如下所示:
a1,a2,a3,a4,…,an
a1,a2,a3,a4,…,an
a1⑴,a2⑴,a3⑴,a4⑴…,an⑴
a1⑴,a2⑴,a3⑴,a4⑴…,an⑴
…
…
a1 ( n−1 ),a2 ( n−1 ) ,…, an ( n−1 )
a1 ( n−1 ),a2 ( n−1 ) ,…, an ( n−1 )
每次处理就是将无序数列的第一个元素与有序数列的元素从后往前逐个进行比较,找出插入位置,将该元素插入到有序数列的合适位置中。
void insertionSort ( int * number, int n)
{
int i= 0 , ii= 0 , temp= 0 ;
for ( i= 1 ; i< n; i++ )
{
temp= number[ i] ;
ii= i- 1 ;
while ( ii>= 0 && temp> number[ ii] )
{
number[ ii+ 1 ] = number[ ii] ;
ii-- ;
}
number[ ii+ 1 ] = temp;
}
}
4.2 快速排序基本思想
基本思想:是对冒泡排序的一种改进。1 快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
排序过程:对r[s……t]中记录进行一趟快速排序,附设两个指针i和j,设rp=r[s],x=rp.key。初始时令i=s,j=t。首先从j所指位置向前搜索第一个关键字小于x的记录,并和rp交换。再从i所指位置起向后搜索,找到第一个关键字大于x的记录,和rp交换。重复上述两步,直至i=j为止。再分别对两个子序列进行快速排序,直到每个子序列只含有一个记录为止。
排序演示示例
假设用户输入了如下数组:
Untitled
创建变量 i=0 (指向第一个数据),j=5(指向最后一个数据), k=6(赋值为第一个数据的值)。
我们要把所有比k小的数移动到k的左面,所以我们可以开始寻找比6小的数,从j开始,从右往左找,不断递减变量j的值,我们找到第一个下标3的数据比6小,于是把数据3移到下标0的位置,把下标0的数据6移到下标3,完成第一次比较:
Untitled
i=0 , j=3 , k=6
接着,开始第二次比较,这次要变成找比k大的了,而且要从前往后找了。递加变量i,发现下标2的数据是第一个比k大的,于是用下标2的数据7和j指向的下标3的数据的6做交换,数据状态变成下表:
Untitled
i=2 , j=3 ,k=6
称上面两次比较为一个循环。
接着,再递减变量jj,不断重复进行上面的循环比较。
在本例中,我们进行一次循环,就发现ii和jj “碰头”了:他们都指向了下标22。于是,第一遍比较结束。得到结果如下,凡是k(=6)k(=6)左边的数都比它小,凡是kk右边的数都比它大:
Untitled
如果ii和jj没有碰头的话,就递加i找大的,还没有,就再递减j找小的,如此反复,不断循环。注意判断和寻找是同时进行的。
然后,对k两边的数据,再分组分别进行上述的过程,直到不能再分组为止。
注意:第一遍快速排序不会直接得到最终结果,只会把比kk大和比kk小的数分到kk的两边。为了得到最后结果,需要再次对下标两边的数组分别执行此步骤,然后再分解数组,直到数组不能再分解为止(只有一个数据),才能得到正确结果。
void quickSortIn ( int left, int right, int a[ ] ) ;
{
if ( left>= right)
return ;
int i= left;
int j= right;
int key= a[ i] ;
while ( i< j)
{
while ( i< j&& key<= a[ j] )
j-- ;
a[ i] = a[ j] ;
while ( i< j&& key>= a[ i] )
i++ ;
a[ j] = a[ i] ;
}
a[ i] = key;
quickSortIn ( left, i- 1 , a) ;
quickSortIn ( i+ 1 , right, a) ;
}
void quickSort ( int a[ ] , int n) {
quickSortIn ( 0 , n, int a[ ] ) ;
}
4.3 选择排序 是一种简单直观的排序算法。1它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法(比如序列[5, 5, 3]第一次就将第一个[5]与[3]交换,导致第一个5挪动到第二个5后面)。
void selectSort ( int R[ ] , int n)
{
int i, j, k, index;
for ( i = 0 ; i < n - 1 ; i++ ) {
k = i;
for ( j = i + 1 ; j < n; j++ )
{
if ( R[ j] > R[ k] )
k = j;
}
index = R[ i] ;
R[ i] = R[ k] ;
R[ k] = index;
}
}
4.4冒泡排序 它重复地走访过要排序的元素列,一次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素已经排序完成。这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。
冒泡排序算法的原理如下:
1.比较相邻的元素。如果第一个比第二个大,就交换他们两个,这样是从小到大排。
(如果第一个比第二个小,交换 , 那就是从大到小排)
2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
void bubbleSort ( int a[ ] , int n)
{
int i, j, temp;
for ( j= 0 ; j< n- 1 ; j++ )
{
for ( i= 0 ; i< n- 1 - j; i++ )
{
if ( a[ i] > a[ i+ 1 ] )
{
temp= a[ i] ;
a[ i] = a[ i+ 1 ] ;
a[ i+ 1 ] = temp;
}
}
}
}
完整源代码 # include <stdio.h>
# include <stdlib.h>
# define MAX_SIZE 100
typedef struct student {
char name[ 8 ] ;
int score;
} studentImform, * studentPtr;
void insertionSort ( studentPtr number, int n)
{
int i= 0 , ii= 0 ;
studentImform temp;
for ( i= 1 ; i< n; i++ )
{
temp = number[ i] ;
ii= i- 1 ;
while ( ii>= 0 && temp. score > number[ ii] . score)
{
number[ ii+ 1 ] = number[ ii] ;
ii-- ;
}
number[ ii+ 1 ] = temp;
}
}
void bubbleSort ( studentPtr a, int n)
{
int i, j;
studentImform temp;
for ( j= 0 ; j< n- 1 ; j++ )
{
for ( i= 0 ; i< n- 1 - j; i++ )
{
if ( a[ i] . score < a[ i+ 1 ] . score)
{
temp = a[ i] ;
a[ i] = a[ i+ 1 ] ;
a[ i+ 1 ] = temp;
}
}
}
}
void selectSort ( studentPtr R, int n)
{
int i, j, k;
studentImform index;
for ( i = 0 ; i < n - 1 ; i++ ) {
k = i;
for ( j = i + 1 ; j < n; j++ )
{
if ( R[ j] . score > R[ k] . score)
k = j;
}
index = R[ i] ;
R[ i] = R[ k] ;
R[ k] = index;
}
}
void quicksortIn ( int left, int right, studentPtr a)
{
if ( left >= right) return ;
int i= left;
int j= right;
studentImform key= a[ i] ;
while ( i< j)
{
while ( i< j && key. score >= a[ j] . score)
j-- ;
a[ i] = a[ j] ;
while ( i< j && key. score <= a[ i] . score)
i++ ;
a[ j] = a[ i] ;
}
a[ i] = key;
quicksortIn ( left, i- 1 , a) ;
quicksortIn ( i+ 1 , right, a) ;
}
void quickSort ( studentPtr a, int n) {
quicksortIn ( 0 , n+ 1 , a) ;
}
int main ( ) {
int N, i= 0 , way;
studentImform Students[ MAX_SIZE] = { 0 } ;
printf ( "请输入学生数量\\n" ) ;
scanf ( "%d" , & N) ;
while ( N<= 0 ) {
printf ( "输入不合法,请重新输入\\n" ) ;
scanf ( "%d" , & N) ;
}
printf ( "请依次输入%d学生的姓名及成绩\\n" , N) ;
for ( int j= 0 ; j < N; ++ j) {
scanf ( "%s" , Students[ j] . name) ;
scanf ( "%d" , & Students[ j] . score) ;
while ( Students[ i] . name == NULL || Students[ j] . score< 0 ) {
printf ( "输入不合法,请重新输入%d位同学的信息\\n" , j+ 1 ) ;
scanf ( "%s" , Students[ j] . name) ;
scanf ( "%d" , & Students[ j] . score) ;
}
}
printf ( "请选择排序方式:\\n1.直接插入排序\\n2.快速排序\\n3.选择排序\\n4.\\n" ) ;
scanf ( "%d" , & way) ;
switch ( way) {
case 1 :
insertionSort ( Students, N) ;
break ;
case 2 :
quickSort ( Students, N) ;
break ;
case 3 :
selectSort ( Students, N) ;
break ;
case 4 :
bubbleSort ( Students, N) ;
default :
printf ( "输入有误\\n" ) ;
}
printf ( "\\t序号 \\t姓名\\t: \\t分数\\n" ) ;
for ( int j = 0 ; j < N; ++ j) {
printf ( "\\t%-d\\t%-s\\t:\\t%-d\\n" , j, Students[ j] . name, Students[ j] . score) ;
}
}
老师标准子函数
四、实验任务
认真阅读与理解实验内容的具体要求,参考教材相关章节,编写实验程序并上机调试与测试,完成实验报告的撰写。