数据结构课程设计排序算法演示系统

数据结构课程设计排序算法演示系统

完整代码及文档已上传https://download.csdn.net/download/qq_45772158/12615816

一 . 简介

各种内部排序算法的时间复杂度分析结果只给出了算法执行时间的阶,或大概执行时间。试通过随机的数据比较各算法的关键字比较次数和关键字移动次数,以取得直观感受。

二 . 设计内容和要求

基本要求:
(1) 界面友好,易与操作。可采用菜单或其它人机对话方式进行选择。
(2) 实现各种内部排序,包括直接插入排序,冒泡排序,直接选择排序,快速排序,堆排序,归并排序等。
(3) 演示程序以人机对话的形式进行。每次测试完毕显示各种比较指标值的列表,以便比较各种排序的优劣。
测试数据:
利用随机函数产生N个随机整数(10000以上),对这些数进行多种方法进行排序。比较的指标为有关键字参加的比较次数和关键字的移动次数(关键字交换以3次计)。

三 . 本设计所采用的数据结构

typedef struct{
KeyType key; //关键字
}RedType;

4.1 详细设计 思想

主函数:
#include<stdio.h>
#include<string.h>
#include<time.h>
#include <stdlib.h>
#include<math.h>
#define MAXSIZE 20000 //排序元素个数
typedef int KeyType; //定义关键字的整数类型
typedef struct{
KeyType key; //关键字
}RedType;
RedType R[MAXSIZE];
typedef struct{
RedType r[MAXSIZE+1]; //0号单元闲置或用作哨兵单元
int length; //顺序表长度
int mov; //记录关键字移动次数
int com; //关键字的比较次数
int dt[];
}Sqlist;

4.1.1 冒泡排序
在这里插入图片描述
核心思想
依次比较相邻的两个数,将小数放在前面,大数放在后面,第一轮比较后,最大的数便被放到了最后;第二轮操作前 n-1 个数据(假设有 n 个数据),依然是依次比较相邻的两个数,将小数放在前面,大数放在后面,倒数第二个数便是第二大的数;同理第 i 轮操作前 n-i+1 的数据(假设 i 取值是从 1 开始的),则 n-i+i 位置上的数据为第 i 大的数据。一共有 n-1 轮,第 i 轮比较中共比较 n-i 次比较。
核心代码
void BubbleSort(Sqlist *L) {
int i,j;
int N=L->length;
for(i=0;ilength;i++){
L->r[0]=L->r[1];
for(j=1;j<N-i;j++){
if(L->r[0].key>=L->r[j+1].key){
L->r[j]=L->r[j+1];
L->mov++;}
else{
L->r[j]=L->r[0];
L->r[0]=L->r[j+1];
L->mov+=2;}
L->com++;
L->r[j+1]=L->r[0];}}
printf(“冒泡排序后的排列顺序如下:\n”);
for(i=1;i<=MAXSIZE;i++)
printf("%d\t",L->r[i]);//输出排序后数组和相关数据
printf("\n关键字移动次数为:%d\n",L->mov);
printf(“关键字比较次数为:%d\n”,L->com);
}
在这里插入图片描述
4.1.2 直接插入排序
核心思想
经过 i-1 遍处理后 ,L[1…i-1] 己排好序。第 i 遍处理仅将 L[i] 插入 L[1…i-1] 的适当位置,使得 L[1…i] 又是排好序的序列。要达到这个目的,我们可以用顺序比较的方法。首先比较 L[i] 和 L[i-1] ,如果 L[i-1] ≤ L[i] ,则 L[1…i] 已排好序,第 i 遍处理就结束了;否则交换 L[i] 与 L[i-1] 的位置,继续比较 L[i-1] 和 L[i-2] ,直到找到某一个位置 j(1 ≤ j ≤ i-1) ,使得 L[j] ≤ L[j+1] 时为止
核心代码
void InsertSort(Sqlist *L) {
int i,j;
for(i=2;i<=L->length;i++) {
L->com++;
if((L->r[i].key < L->r[i-1].key)) //如果r[i]的值比r[i-1]的值要小的话
{
L->r[0] = L->r[i]; //将待插入的记录暂存到监视哨中 (为了避免数组下标出界,在r[0]处设置监视哨 )
L->r[i] = L->r[i-1]; //r[i-1]后移
L->mov+=2; //移动次数加2
for(j=i-2;(L->r[0].key < L->r[j].key);j–) //从后向前寻找插入位置
{
L->r[j+1] = L->r[j]; //纪录逐个后移,直到找到插入位置
L->mov++;
L->com++; }
L->r[j+1] = L->r[0]; //将r[0]即原r[i]插入到正确位置
L->mov++;}}
printf(“直接插入排序后的排列顺序如下:\n”);
for(i=1;i<=L->length;i++)
printf("%d\t",L->r[i]);//输出排序后数组和相关数据
printf("\n关键字移动次数为:%d\n",L->mov);
printf(“关键字比较次数为:%d\n”,L->com); }

4.1.3简单选择排序
核心思想

  1. 有一个长度为n的数组,先经过N-1次比较,找出N个数中最小的数将它与数组的第一个元素交换——-第一次选择排序结束,并且将最小的数安放在第一个数组元素的位置。
  2. 在通过n-2次比较,从剩余的n-1个数中找出最小的数将它与数组的第二个元素交换—–第二次排序结束。
  3. 重复上述步骤,经过n-1次排序后,排序完成。
    void SelectSort(Sqlist *L) {
    int i,j,k;
    for (i=1; i<=L->length; ++i) {// 选择第i小的记录,并交换到位
    L->r[0]=L->r[i];
    k=i;
    for(j=i+1;j<=L->length;j++){ // 在L.r[i…L.length]中选key最小者
    L->com++;
    if(L->r[0].key>L->r[j].key) {
    L->r[0]=L->r[j];
    k=j;
    L->mov++; } }
    if (k!=i) { // L.r[i]←→L.r[j]; 与第i个记录交换
    RedType temp;
    temp=L->r[i];
    L->r[i]=L->r[k];
    L->r[k]=temp;
    L->mov+=3;; } }
    printf(“简单选择排序后的排列顺序如下:\n”);
    for(i=1;i<=L->length;i++)
    printf("%d\t",L->r[i]);//输出排序后数组和相关数据
    printf("\n关键字移动次数为:%d\n",L->mov);
    printf(“关键字比较次数为:%d\n”,L->com);
    }
    4.1.4快速排序

核心思想
首先检查数据列表中的数据数,如果小于两个,则直接退出程序。如果有超过两个以上的数据,就选择一个分割点将数据分成两个部分,小于分割点的数据放在一组,其余的放在另一组,然后分别对两组数据排序。通常分割点的数据是随机选取的。这样无论你的数据是否已被排列过,你所分割成的两个字列表的大小是差不多的。而只要两个子列表的大小差不多
核心代码
int Partition(Sqlist *L,int low,int high)
{ //对顺序表中的子表r[low…high]进行一趟排序,返回枢轴位置
int pivotkey;
L->r[0] = L->r[low]; //用子表的第一个记录做枢轴记录
pivotkey=L->r[low].key; //枢轴纪录关键字
while(low<high)
{
while(low<high && L->r[high].key>=pivotkey)
{
high–;
L->com++;
}
L->r[low] = L->r[high]; //将比枢轴纪录小的纪录移到低端
L->mov++;
while(low<high && L->r[low].key<=pivotkey)
{
low++;
L->com++;
}
L->r[high] = L->r[low]; //将比枢轴纪录大的纪录移到高端
L->mov++;
}
L->r[low] = L->r[0]; //枢轴记录到位
L->mov++;
return high; //返回枢轴位置
}

void QSort(Sqlist *L, int low, int high) {
int pivotloc,i;
if (low<high) { // 长度大于1
pivotloc = Partition(L, low, high); // 将L.r[low…high]一分为二
QSort(L, low, pivotloc-1); // 对左子表递归排序,pivotloc是枢轴位置
QSort(L, pivotloc+1, high); // 对右子表递归排序
}}
void QuickSort(Sqlist *L){ //对顺序表L做快速排序
QSort(L,1,L->length);
printf(“快速排序后的排列顺序如下:\n”);
for(int i=1;i<=L->length;i++)
printf("%d\t",L->r[i]);//输出排序后数组和相关数据
printf("\n关键字移动次数为:%d\n",L->mov);
printf(“关键字比较次数为:%d\n”,L->com);}
4.1.5 堆排序

核心思想
堆排序是一树形选择排序,在排序过程中,将 R[1…N] 看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。将原始记录序列建成一个堆,成为初始堆,并输出堆顶元素;调整剩余的记录序列,使之成为一个新堆,再输出堆顶元素;如此反复进行,当堆中只有一个元素时,整个序列的排序结束,输出的序列便是原始序列的非递减有序序列。在堆排序的过程中,主要负责两方面的工作:一是如何将原始记录序列构造成一个堆,即建立初始堆;二是输出堆顶元素后,如何将剩余记录整理成一个新堆。
核心代码
void HeapAdjust(Sqlist L, int s, int m)
{ //假设r[s+1…m]已经是堆,将r[s…m]调整为以r[s]为根的大根堆
int j;
RedType 4rc;
rc = L->r[s];
L->mov++;
for (j=2
s; j<=m; j*=2) { // 沿key较大的孩子结点向下筛选
L->com++;
if (j<m && L->r[j].keyr[j+1].key) //j为key较大的记录下标 {
++j; // j为key较大的记录的下标
L->com++;
}
if (rc.key >= L->r[j].key) break; // rc应插入在位置s上
L->r[s] = L->r[j];
L->mov++;
s = j;
}
L->r[s] = rc; // 插入
L->mov++;}
void HeapSort(Sqlist *L) {
int i;
RedType rc;
for(i=L->length/2;i>0;i–) //把H->r[…]建成大顶堆
HeapAdjust ( L, i, L->length );
for(i=L->length;i>1;i–){
rc = L->r[i];
L->r[i] = L->r[1];
L->r[1] = rc;
L->mov+=3;
HeapAdjust(L,1,i-1); // 将H.r[1…i-1] 重新调整为大顶堆
}
printf(“堆排序后的排列顺序如下:\n”);
for(i=1;i<=L->length;i++)
printf("%d\t",L->r[i]);//输出排序后数组和相关数据
printf("\n关键字移动次数为:%d\n",L->mov);
printf(“关键字比较次数为:%d\n”,L->com);}
4.1.6 希尔排序
核心思想
先取一个小于 n 的整数 d1 作为第一个增量,把文件的全部记录分成 d1 个组。所有距离为 dl 的倍数的记录放在同一个组中。先在各组内进 行 直接插入排序 ;然后,取第二个增量 d2<d1 重复上述的分组和排序,直至所取的增量 dt=1(dt<dt-l< … <d2<d1) ,即所有记录放在同一组中进行直接插入排序为止。
核心代码
void ShellInsert(Sqlist L,int dk) //希尔排序
{ //对顺序表L做一趟增量是dk的希尔插入排序
int i,j;
for(i=dk+1;i<=L->length;++i){
L->com++;
if(L->r[i].keyr[i-dk].key) //需将L.r[i]插入有序增量子表
{
L->r[0]=L->r[i]; // r[0]只是暂存单元,不是哨兵。暂存在L.r[0]
for(j=i-dk;j>0&&L->r[0].keyr[j].key;j-=dk)
{ L->r[j+dk]=L->r[j]; //记录后移,直到找到插入位置
L->mov++;
L->com++; }
L->r[j+dk]=L->r[0]; //将r[0]即原r[i],插入到正确位置
L->mov++; }}}
void ShellSort(Sqlist L,int dt[],int t)
{ //按增量序列dt[0…t-1]对顺序表作t趟希尔排序
int i,k;
for(k=0;k<t;++k)
ShellInsert(L,dt[k]); //一趟增量为dt[t]的希尔插入排序
图七 希尔排序
}
4.1.7 归并排序
核心思想
将有 n 个记录的原始序列看作 n 个有序子序列,每个子序列的长度为 1 ,然后从第一个子序列开始,把相邻的子序列两两合并,得到 [n/2] 个长度为 2 或 1 的子序列(当子序列个数为奇数时,最后一组合并得到的序列长度为 1 ),把这一过程称为一次归并排序,对第一次归并排序后的 [n/2] 个子序列采用上述方法继续顺序成对归并,如此重复,当最后得到的长度为 n 的一个子序列时,该子序列便是原始序列归并排序后的有序序列。
核心代码
void MergePass(int length,int x,int y)// 一次二路归并排序
{ int i;
for(i=1;i+2
length-1<=L;i=i+2
length)
{ Merge(i,i+length-1,i+2
length-1,x,y); // 函数调用
}
if(i+length-1<L)
{ Merge(i,i+length-1,L,x,y); // 函数调用
}
}
// 归并排序
void Mergesort() // 二路归并排序
{ int length,k,m=0,i,x=0,y=0;
printf("\n\t\t 原始数据为(按回车键开始排序): \n\t\t");
for(k=1;k<=L;k++)
{ printf("%5d",R[k].key);
}
getchar();
printf("\n");
for(length=1;length<L;length
=2)
{ MergePass(length,&x,&y);
m++; // 输出语句包括排序的结果及次数
printf("\t\t 第 %d 趟归并排序的结果为: \n\t\t",m);
for(k=1;k<=L;k++)
{ printf("%5d",R[k].key);
}
getchar();
printf("\n");
}
printf("\n\t\t 排序最终结果是: \n\t\t");
for(i=1;i<=L;i++)
{ printf("%5d",R[i].key);
}
printf("\n");
printf("\t\t 比较次数: %d\n",x);
printf("\t\t 移动次数: %d\n",y);
}

  • 15
    点赞
  • 101
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构》(C语言版)<br>算法源码及运行演示系统使用说明<br>一、启动演示系统<br>双击演示系统应用程序文件“DS_VC_ALGO.EXE”启动演示系统,出现图1所示界面。<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>图1 《数据结构》(C语言版)算法源码及运行演示系统主界面<br>二、演示系统使用步骤<br>除了个别算法之外,演示系统给出了《数据结构》(C语言版)书中算法对应的程序代码(CPP文件)和测试运行程序(VC++6.0的EXE文件)。通过本系统,可以显示算法的源代码以及运行结果。具体操作步骤如下:<br>1.选择相应章<br>单击演示系统界面右侧章选择按钮。<br>例如,要选择第6章,则单击“第6章”选择按钮。<br>当相应章被选择后,窗口的右侧部分将列出本章的算法选择按钮。<br>例如,选择第6章后,窗口的右侧部分将显示第6章中的算法6.1-6.13和6.15的选择按钮。由于书中的算法6.14和6.16只是示意性算法,故未给出源码,其按钮上的文字为灰色,处于“无效”状态。<br>2.选择相应章中的算法<br>单击窗口右侧部分所列举的本章某个算法选择按钮,被选择的算法的源码将在窗口左侧空白区域中显示。对于较长的源码,单击显示区域后,可用键盘的光标键和翻页键浏览源码。<br> 例如,选择了第6章中的算法6.5后界面如图2所示:<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>图2 选择算法6.5<br>3.运行测试程序<br>单击窗口上部的“运行”按钮,将弹出运行窗口,运行所选算法的测试程序。若运行按钮为灰色,表示该算法无单独测试程序。<br> 例如,算法6.5的测试运行窗口如图3所示:<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>图3 测试运行窗口<br>测试运行说明:<br>测试运行窗口显示程序的执行过程及结果。若在显示过程中出现运行窗口无法正常演示的情况,只需调节运行窗口大小即可正常显示(调节最小化按钮或窗口最大化/还原按钮“ ”)。<br>三、退出演示系统<br>使用完毕后,单击窗口右上角关闭按钮“ ”退出演示系统。<br>四、测试程序示例<br>在《数据结构》的课程教学中,各抽象数据类型的设计与实现是重要的学习和实践环节。为此,本系统只给出了各算法源码的测试程序的可执行文件。在此,给出算法6.5的测试程序示例,以供参考。<br>算法6.5是中序遍历线索二叉树的非递归算法,要对其源码进行测试,可首先调用算法6.6及6.7建立中序线索二叉树。以下是测试程序的源码,相关类型和辅助函数定义在文件include06.h和include06.cpp中,
数据结构算法演示(Windows版) 使 用 手 册 一、 功能简介 本课件是一个动态演示数据结构算法执行过程的辅助教学软件, 它可适应读者对算法的输入数据和过程执行的控制方式的不同需求, 在计算机的屏幕上显示算法执行过程中数据的逻辑结构或存储结构的变化状况或递归算法执行过程中栈的变化状况。整个系统使用菜单驱动方式, 每个菜单包括若干菜单项。每个菜单项对应一个动作或一个子菜单。系统一直处于选择菜单项或执行动作状态, 直到选择了退出动作为止。 二、 系统内容 本系统内含84个算法,分属13部分内容,由主菜单显示,与《数据结构》教科书中自第2章至第11章中相对应。各部分演示算法如下: 1. 顺序表 (1)在顺序表中插入一个数据元素(ins_sqlist) (2)删除顺序表中一个数据元素(del_sqlist) (3)合并两个有序顺序表(merge_sqlist) 2. 链表 (1)创建一个单链表(Crt_LinkList) (2)在单链表中插入一个结点(Ins_LinkList) (3)删除单链表中的一个结点(Del_LinkList) (4)两个有序链表求并(Union) (5)归并两个有序链表(MergeList_L) (6)两个有序链表求交(ListIntersection_L) (7)两个有序链表求差(SubList_L) 3. 栈和队列 (1)计算阿克曼函数(AckMan) (2)栈的输出序列(Gen、Perform) (3)递归算法的演示  汉诺塔的算法(Hanoi)  解皇后问题的算法(Queen)  解迷宫的算法(Maze)  解背包问题的算法(Knap) (4)模拟银行(BankSimulation) (5)表达式求值(Exp_reduced) 4. 串的模式匹配 (1)古典算法(Index_BF) (2)求Next 函数值(Get_next)和按Next 函数值进行匹配 (Index_KMP(next)) (3)求 Next 修正值(Get_nextval)和按 Next 修正值进行匹配(Index_KMP(nextval)) 5. 稀疏矩阵 (1)矩阵转置 (Trans_Sparmat) (2)快速矩阵转置 (Fast_Transpos) (3)矩阵乘法 (Multiply_Sparmat) 6. 广义表 (1)求广义表的深度(Ls_Depth) (2)复制广义表(Ls_Copy) (3)创建广义表的存储结构(Crt_Lists) 7. 二叉树 (1)遍历二叉树  二叉树的线索化  先序遍历(Pre_order)  中序遍历(In_order)  后序遍历(Post_order) (2) 按先序建二叉树(CrtBT_PreOdr) (3) 线索二叉树  二叉树的线索化  生成先序线索(前驱或后继) (Pre_thre)  中序线索(前驱或后继) (In_thre)  后序线索(前驱或后继) (Post_thre)  遍历中序线索二叉树(Inorder_thlinked)  中序线索树的插入(ins_lchild_inthr)和删除(del_lchild_inthr)结点 (4)建赫夫曼树和求赫夫曼编码(HuffmanCoding) (5)森林转化成二叉树(Forest2BT) (6)二叉树转化成森林(BT2Forest) (7)按表达式建树(ExpTree)并求值(CalExpTreeByPostOrderTrav) 8. 图 (1)图的遍历  深度优先搜索(Travel_DFS)  广度优先搜索(Travel_BFS) (2)求有向图的强连通分量(Strong_comp) (3)有向无环图的两个算法  拓扑排序(Toposort)  关键路径(Critical_path) (4)求最小生成树  普里姆算法(Prim)  克鲁斯卡尔算法(Kruscal) (5)求关节点和重连通分量(Get_artical) (6)求最短路径  弗洛伊德算法(shortpath_Floyd)  迪杰斯特拉算法(shortpath_DIJ) 9. 存储管理 (1)边界标识法 (Boundary_tag_method) (2)伙伴系统 (Buddy_system) (3)紧缩无用单元 (Storage_compaction) 10. 静态查找 (1)顺序查找(Search_Seq) (2)折半查找 (Serch_Bin) (3)插值查找 (Search_Ins) (4)斐波那契查找 (Search_Fib) (5)次优查找树(BiTree_SOSTree) 11. 动态查找 (1)在二叉排序树上进行查找(bstsrch)、插入结点(ins_bstree)和删除结点(del_bstree) (2)在二叉平衡树上插入结点(ins_AVLtree) 和删除结点(del_AVLtree) (3)在 B-树上插入结点(Ins_BTree) 和 删除结点(Del_BTree) (4)在 B+树上插入结点(Ins_PBTree) 和 删除结点(Del_PBTree) 12. 内部排序 (1)简单排序法  直接插入排序(Insert_sort)  表插入排序(内含插入(Ins_Tsort) 重排(Arrange)两个算法)  起泡排序(BubbleSort)  简单选择排序(SelectSort) (2)复杂排序法  堆排序(HeapSort)  快速排序(QuickSort)  锦标赛排序(Tournament) (3)其他  快速地址排序(QkAddrst)  基数排序(RadixSort) 13. 外部排序 (1)多路平衡归并排序(K-Merge) (2)置换-选择排序(Repl_Selection) 三、 运行环境 1. 硬件:Pentium100以上PC机。 2. 软件:Windows95及以上版本的操作系统。 四、 运行 本系统的执行文件为DSDEMOW.EXE。 五、 如何使用本课件 读者可以利用鼠标移动光标选择“演示算法”或“菜单命令”来控制课件的运行过程。 1. 课件的演示算法菜单为页式菜单。第一级菜单中的各项与上述“系统内容”中各大项相对应,读者运行“算法演示课件”后, 即进入“算法选择一级菜单”画面,此时可移动光标进行选择,当光标所在菜单项改为红色时,单击鼠标即进入“算法选择二级菜单”,进行相同操作之后,或进入算法选择三级菜单(如图1所示),或进入算法演示的执行状态(如图2所示)。 图1 图2 在算法选择菜单画面中,形如 的图标意为尚有下级菜单,形如 的图标则表示将直接进入算法演示状态。此时也可直接单击一级菜单或二级菜单的标题直接返回之,注意:菜单右侧上方的“退出”按钮意为退出整个演示课件。 2. 算法演示执行状态下的屏幕分为三部分:第一行为“标题行”,第二行为“菜单命令”,以下为算法演示屏上各菜单的说明。 菜单命令中各项自左至右的功能分别为:  数据——设置算法演示的数据(数据结构)。  调用栈——察看当前函数(或过程)嵌套或递归的历程。  说明——察看算法说明。  暂停——中断演示过程。  执行——连续执行算法直至所设断点或至算法执行完毕。  单步——执行一行算法,遇到子程序调用时,连续执行完子程序。  跟踪——执行一行算法,遇到子程序调用时,进入子程序。  执行到——演示算法到当前所设最近的断点或算法窗口中的当前行。  恢复——重置屏幕为当前算法执行前的初始状态。  断点——在算法窗口的当前选择行设置断点或清除断点。  设置——设置连续演示时的速度或开/闭背景音乐(或动作音效)开关。  返回——返回算法选择菜单。 3. 断点的设置方法为:移动光标至“断点语句”所在行,点击鼠标后即出现绿色光条,之后单击“断点”菜单中的“设置断点”命令项即可,此时该断点语句所在行上将出现红色光条。 六、 算法演示屏的详细说明 本系统对屏幕设计的基本原则是集数据结构、算法和其他重要信息(如栈等)于同一屏幕。一般情况下演示屏由图示、算法和变量三个窗口组成,特殊情况下将根据演示内容适当增加。一般情况下, 左侧图示窗口显示演示数据的逻辑结构或存储结构,右侧上方窗口显示算法文本,右侧下方窗口显示当前算法中各变量的值或递归工作栈的状态。各窗口间的边界大小均可自由调节,且可按需扩大至全屏。 算法窗口显示当前演示的算法文本,并以深蓝色的光条覆盖将要执行的语句。若算法中含有函数或过程调用语句,则当光条覆盖到该过程调用语句时,随即自动隐去原算法文本而显示子过程的文本,而从此过程返回时再重新显示原算法文本。类似地,在演示递归算法执行过程时,每当执行递归调用本过程的语句时,随即隐去当前层次的算法文本而显示下一层的算法文本,并且以不同颜色的算法文本表示递归的不同层次。如第一层的算法文本为深绿色,第二层为紫色,第三层为深红色,第四层为深蓝色,第五层为浅蓝色,第六层为玫瑰红色等。 当演示递归算法执行过程中递归工作栈的变化状态时,递归工作栈显示在右侧下窗口,递归工作栈的状态和算法文本窗口中相应语句执行后的结果相对应,栈顶记录为当前递归层的参量值。每进入一层递归时,就产生一个新的工作记录(包括调用语句行号、变量参数或全程变量、数值参数和局部变量)压入栈顶;每退出一层递归时,先根据栈顶的调用语句行号返回至上层,然后在传递完变量参数的值后退栈。 各个算法演示屏的补充说明如下: 1. 顺序表和链表的插入、删除和链表的生成 算法演示屏由显示顺序表或链表的图示、算法文本及变量等三个窗口组成。在演示算法之前,需先在弹出的小窗口中输入线性表的数据元素及算法参数 i(插入或删除的位置)和 b(被插的数据元素)的值。顺序表的图示窗口在演示屏的上方,链表的图示窗口在左侧。 2. 有序表的操作 算法演示屏的状态和 1 中所述相同。 3. 汉诺塔问题 算法演示屏由4个窗口组成。右侧上方为算法文本,在算法中有4个形式参量,其中值参 n 为圆盘个数,x、y、和 z 分别表示3个塔座;右侧下方为递归工作栈,栈中每个记录包含调用语句行号 adr 及值参 n 和 x、y、z;左侧上方显示汉诺塔图形及移动操作结果;左侧下方显示移动操作的记录。 4. 迷宫问题 左侧窗口显示迷宫的逻辑结构,由 N×N 个方格组成,左上[1,1]为入口,右下[N,N]为出口,并且以红色钉子填充表示障碍,空白表示通路,红色交通灯表示已游历过的路,箭头表示继续游历的方向,演示结束时显示一条通路或迷宫不通的信息。右侧下窗口为递归工作栈,栈中每个记录含6个数据项,其中 adr 指示调用语句行号,k 指示步数,(x,y) 表示当前坐标,i 指示路径方向(起始方向为 1,顺时针方向旋转搜索)。 5. 皇后问题 左侧图示窗口包含棋盘和递归工作栈两部分,栈中记录含3个数据项,其中 adr 指示调用语句行号,k 指示列号,i 指示行号。此算法演示可求得所有可行结果,在求得每一种排布的结果之后,均会弹出一个窗口显示“找到第 j (j=1,2,…) 种排布”,单击“确定”按钮将继续进行,直至找到所有可能构成的排布。 6. 背包问题 右侧图示窗口的上方显示背包、物件及其体积。 若有解,则在求得每一组结果之后,均会弹出一个窗口提示求得一组解,单击提示窗口中的小人将继续进行。该窗口的下方为递归工作栈,栈中的记录含3个数据项,其中 adr 指示调用语句所在行号,n 指示物件个数,t 指示背包总体积。 7. 阿克曼函数 整个演示屏只有显示算法文本和显示算法执行过程中栈的状态两个窗口。在执行算法之前,首先应按照提示输入参数 m 和 n 的值。 8. 栈的输出序列 图示窗口的内容为:由算法 Gen 生成的栈的操作序列(列出在窗口的下方)、算法 Perform 执行时栈的操作过程(该窗口的上方)以及算法 Perform 执行的结果——栈的输出序列(列出在图示窗口的右侧)。 9. 表达式求值 图示窗口的内容主要为显示表达式求值过程中操作数栈和运算符栈的变化情况以及主要操作。上方的小窗口显示在算法演示之前设定的表达式。 10. 离散事件模拟 图示窗口分成3部分:中间部分或显示客户流动情况的动画,或显示程序执行过程中事件表和4个队列的数值,上方两个按钮用以切换动画或静态数据,下方则显示客户总人数、客户逗留的累计时间以及调节动画中小人移动速度的指针。 11. 串的模式匹配 上窗口显示算法文本,下窗口显示串的匹配过程或求 next 函数的过程。 12. 稀疏矩阵 图示窗口显示矩阵的状态或其三元组的表示。 13. 求广义表的深度 图示窗口显示广义表的存储结构,图中指针 ls 指向当前所求深度的广义表,值为空时不显示。演示结束时弹出窗口显示求得的深度。 14. 复制广义表 图示窗口的上方显示已知广义表的存储结构,图示窗口的下方显示复制求得的广义表的存储结构。递归工作栈中含调用语句行号 adr、变参 nls 和值参 ls。 15. 创建广义表的存储结构 图示窗口显示广义表存储结构的建立过程和算法执行过程中参数Sub的当前值。 16. 遍历二叉树 图示窗口显示二叉树的逻辑结构和遍历结果输出的结点序列,图中指针 bt 指向当前遍历的二叉树的根结点。 17. 线索二叉树 图示窗口显示二叉树的存储结构,但结点中只含标志域,而以结点间的黑色连线表示指针,红色连线表示前驱线索,蓝色连线表示后继线索。在二叉树线索化的过程中,图中指针 p 指向当前层二叉树的根结点,指针 pre 指向当前被访问的结点的前驱。在演示线索树的插入和删除过程时,图示窗口的下方还包括“输入行”和“提示行”。 18. 按先序序列建二叉链表 图示窗口显示输入的先序序列和生成二叉链表的过程。 19. 森林和二叉树的相互转换 图示窗口在显示屏的上方,其左侧为森林,右侧为二叉树。 20. 赫夫曼树和赫夫曼编码 图示窗口显示生成的赫夫曼树的逻辑结构和每个叶子结点的编码。 21. 图的深度优先搜索 图示窗口的上半部分显示图的逻辑结构,初始状态用青色圆圈表示顶点,结点间的黑色连线表示边或弧(连线上画有箭头)。演示过程中用红色覆盖已访问的顶点和边(或弧)。窗口下方显示图的邻接表,演示过程中以红色框边表示已访问过的弧。图示窗口的下方显示遍历后输出的顶点序列。 22. 图的广度优先搜索 与深度优先不同的是,在窗口的下方增加一个队列,其左端为队头,右端为队尾。 23. 求有向图的强连通分量 图示窗口自上而下分别显示有向图的逻辑结构、存储结构和 Finished 数组在算法执行过程中的变化情况。所求得的各个强连通分量,将以不同颜色的顶点组表示。 24. 求关节点和重连通分量 图示窗口的上半部分显示无向图,下半部分自上而下分别显示 Vexnum、Vexdata、Visited、Low、Squlow(求得 low 值的顺序)和 artpoint(关节点)的信息。 25. 有向图的拓扑排序 图示窗口由5部分组成。其中左上显示有向图的邻接表;左下显示有向图,其中顶点和弧的初始状态分别为绿色和黑色,从栈中退出的顶点(i)用红色表示,分别以蓝色和红色指示当前访问的邻接点(k)和它们之间的弧(ik),灰白色表示已经输出的顶点;右下显示顶点的入度;右上显示入度为零的栈。当拓扑排序不成功时,在演示屏的中央将会弹出一个窗口,显示提示信息“网中存在自环!”,此时用户可在左下显示的有向图中由绿色顶点和黑色弧构成的子图中找到这个环。 26. 有向图的关键路径 图示窗口包含5部分信息。左上显示带入度域的邻接表;左下显示有向网的逻辑结构和顶点的入度及各顶点事件的最早发生时间和最迟发生时间;右下显示拓扑排序过程中入度为零的顶点的栈S,右上显示的栈 T 存放拓扑序列,其入栈顺序和栈 S 的出栈顺序相同,从栈顶到栈底的顶点顺序即为顶点的逆拓扑序列。算法执行结束后将弹出窗口列出全部结果,其中红色字体的弧表示关键活动。 27. 普里姆算法 图示窗口包含3部分内容。右上是邻接矩阵;左上是无向网的逻辑结构,图中顶点的初始状态为黄色,算法执行过程中,红色覆盖的顶点和边则表示已加入生成树的顶点和生成树上的边;窗口的下方则显示 closedge 数组中的值。 28. 克鲁斯卡尔算法 图示窗口的左侧为无向网,以红色标定已落在生成树上的边;右侧自上而下列出各条边的信息以及选择生成树的边的执行过程。 29. 边界标识法 图示窗口的初始状态为 64KB 的模拟存储器,演示过程中,以绿色覆盖占用块。各个存储块的头部左侧所示为该块的起始地址,头部结构或其他信息参见教科书。用户可根据弹出窗口的操作提示信息进行操作,输入请求分配的空间大小或释放块的首地址。 30. 伙伴系统 在图示窗口中,左侧为可利用空间链表的逻辑结构,右侧为存储结构,其中红色覆盖部分为占用块。弹出窗口为输入窗口,由用户输入请求分配的空间大小或释放块的首地址。 31. 紧缩无用单元 右侧显示存储空间,空白表示空闲块,其他颜色覆盖表示占用块,在存储空间不足分配时将进行空闲块压缩。左侧显示存储映像。弹出窗口为输入窗口,由用户输入请求分配的空间大小和分配或释放块的块名。 32. 静态查找 上窗口为图示窗口,演示查找过程;左下和右下分别为算法文本和变量窗口。 33. B-树和B+树 整个屏幕分为上、下两个窗口,上窗口演示插入或删除结点过程中B-树或B+ 树结构的变化状况;下窗口内显示如查找关键字、插入位置、结点分裂等操作信息。下窗口上面左侧的小窗口为编辑窗口,由用户输入待插或待删的关键字,输入之后其右侧的操作命令将由隐式状态改为显式状态。 34. 内部排序 图示窗口演示排序过程以及排序过程中关键字之间进行的比较次数和记录移动的次数。 七、 用户自行输入数据指南 算法操作的对象——数据结构,或由用户自行输入,或由系统随机产生,并在获得用户的确认之前,可反复随机产生,直至用户满意,用鼠标点击“OK”按钮确认为止。 多数情况下的输入界面上有足够的提示信息,以指示用户需要进行何种操作。补充说明如下: 1. 表的数据元素为任意的单个字符。 2. 迷宫的输入界面如图3所示。图中砖墙图案表示障碍,连续点击鼠标可将光标所在位置设置成通道或者障碍,建议用户先点击“随机生成”按钮随机生成一个迷宫,然后移动鼠标调整成所需。所设迷宫可以利用“保存数据”按钮生成dat类型文件,并在需要时可以利用“取出数据”按钮读入。 图3 3. 演示背包问题的算法之前,首先需要输入物品个数,之后将出现如图4所示的输入界面,可以利用“随机生成”的按钮或各个相应的小窗口输入物品体积 wi 和背包体积 T 。背包的总体积不得超过 30 ,单个物品的体积不得超过 10 。 图4 4. “表达式求值”和“建表达式树”时的输入界面如图5所示。用户可在窗口内自行输入,并以“Enter”键为结束符;也可以连续点击左侧蓝色的表达式由系统自动生成,直至用户点击右侧的计算器表示确认为止。“求值”可实现带括弧的四则运算和幂次运算,并支持sin、cos、tan、arcsin 和 arccos 等函数计算,其操作数为实数。“建树”的表达式仅限于带括弧的四则运算,其操作数为单个字母的字符。 图5 5. 稀疏矩阵的输入界面如图6所示。用户可随意进行矩阵中任意位置元素的输入,只要将光标移动至待输入的元素位置,单击鼠标后将弹出计算器,单击数字按钮,可进行随意输入,之后点击“OK”按钮表示确认。 图6 6. 广义表的数据输入方式为自左向右顺序输入广义表的字符串。输入过程中,图7所示输入界面中的“确定”为灰色字体,只有当用户正确输入完毕时,“确定”两字才改为黑色字体,此时用户可单击此按钮表示确认。 图7 7. 图的输入界面如图8所示。之前尚需确认是否为有向图和带权图。在用户自行输入图时,首先按下“创建节点”按钮,之后可移动光标至窗口的任意位置单击鼠标创建顶点;然后单击“创建弧”按钮,可在任意两个顶点之间构建弧或边。构建弧(或边)的操作为:先将光标移动至弧尾的顶点,单击一次鼠标,然后移动光标至弧头位置,再单击一次鼠标。对于带权的图,则在构建弧(或边)的同时,在当时弹出的窗口中输入权值,权值的默认值为 1。 图8 8. 内部排序的关键字均为单个字符。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值