数据结构实验五 查找算法的实现

广州大学学生实验报告

 

开课实验室:计算机科学与工程实验(电子楼416B)     2019年6月11日

学院

计算机科学与教育软件学院

年级、专业、班

 

姓名

 

学号

 

实验课程名称

数据结构实验

成绩

 

实验项目名称

实验五 查找算法

指导老师

 

一、实验目的

掌握线性的定义及基本操作,用链表实现:遍历、查找、插入、删除、翻转。

二、使用仪器、器材

微机一台

操作系统:WinXP

编程软件:C++

三、实验内容及原理

顺序查找:使用数组或链表结构。用随机函数生成16个不重复的字母(’a’~’z’),键盘输入待查找的字母,返回查找成功与否,若成功则返回该字母所在的位置(序号),并计算比较次数。

折半查找:用数组实现,查找前元素先排序。计算比较次数。分别用查找成功、不成功进行测试。

二叉查找树:手工输入10个字母,生成一棵二叉查找树,用递归算法打印树结构或分别输出先序和中序遍历序列以确认其结构。键盘输入待查找的字母,计算比较次数。分别用查找成功、不成功进行测试。

 

注意:实验报告包含运行测试截屏,内容包括16个数据元素、待查找的元素、查找成功与否、比较的次数等。

  • 实验过程原始数据记录
  1. 顺序查找

// ConsoleApplication73.cpp : 定义控制台应用程序的入口点。

//

 

#include "stdafx.h"

//顺序查找算法

#include<stdlib.h>

#include "SeqSearch.h"

#include "time.h"

 

int main()

{

    time_t t;   // 定义时间变量

    srand((unsigned)time(&t));  //由时间确定随机序列,执行一次

    int a[26];

    int sjzm[16];

 

    int w, tt;

    for (int i = 0; i<26; i++)

         a[i] = i + 1;

    for (int i = 0; i<16; i++)

    {

         w = rand() % (26 - i) + i;

         tt = a[i];

         a[i] = a[w];

         a[w] = tt;

    }

    for (int i = 0; i < 16; i++)

         sjzm[i] = a[i] + 96;

 

    RecType R[MAXL];

    CreateList(R, sjzm, 16);

    printf("随机生成的16个不重复的字母为:"); DispList(R, 16);

    int time = 0;

    int flag;

    char search;

    int result;

    printf("进入查询请输入非零数字,退出查询请输入0\n");

    scanf_s("%d", &flag);

    getchar();

    while (flag) {

         printf("请输入要查找的字母:");

         scanf_s("%c", &search);

         result=SeqSearch(R, 16, search, time);

         getchar();

         if (result != 0) {

             printf("要查找的字母的位置为:%d \n", result);

         }

         else

             printf("查询非法\n");

         printf("进入查询请输入非零数字,退出查询请输入0\n");

         scanf_s("%d",& flag);

         getchar();

    }

    return 1;

}

 

 

#pragma once

#include <stdio.h>

#define MAXL 100      //最大长度

typedef int KeyType//定义关键字类型为int

typedef char InfoType;

 

typedef struct

{

    KeyType key;      //关键字项

    InfoType data;        //其他数据项,类型为InfoType

} RecType;                //查找元素的类型

void CreateList(RecType R[], KeyType keys[], int n);//创建顺序表

void DispList(RecType R[], int n); //输出顺序表

 

int SeqSearch(RecType R[], int n, KeyType k, int& time);

 

 

 

#include "stdafx.h"

#include"SeqSearch.h"

void CreateList(RecType R[], KeyType keys[], int n//创建顺序表

{

    for (int i = 0; i<n; i++)

         R[i].key = keys[i];

}

void DispList(RecType R[], int n//输出顺序表

{

    for (int i = 0; i<n; i++)

         printf("%c ", R[i].key);

    printf("\n");

}

 

int SeqSearch(RecType R[], int n, KeyType k,int& time)

{

    int i = 0;

    while (i < n && R[i].key != k) //从表头往后找

    {

         i++;

         time++;

    }

    if (i >= n)

         return 0;

    else

         return i + 1;

}

 

  1. 折半查找

// ConsoleApplication74.cpp : 定义控制台应用程序的入口点。

//

 

#include "stdafx.h"

#include"BinSearch.h"

 

 

//折半查找算法

int main()

{

    int n = 11;

    RecType R[MAXL];

    KeyType a[] = { 3,2,10,20,15,25,28,29,40,35,30 };

    printf("原始数据:");

    for (int i = 0; i < 11; i++)

         printf("%d  ", a[i]);

    printf("\n");

    CreateList(R, a, n);

    QuickSort(R, 0, 10);

    printf("查找表:"); DispList(R, n);

    int flag,result,search,time=0;

    printf("进入查询请输入非零数字,退出查询请输入0\n");

    scanf_s("%d", &flag);

    getchar();

    while (flag) {

         time = 0;

         printf("请输入要查找的数字:");

         scanf_s("%d", &search);

         result = BinSearch(R, 11, search, time);

         getchar();

         if (result != 0) {

             printf("要查找的字母的位置为:%d \n", result);

             printf("查找次数为:%d \n", time);

         }

         else

             printf("查询非法\n");

         printf("进入查询请输入非零数字,退出查询请输入0\n");

         scanf_s("%d", &flag);

         getchar();

    }

    return 1;

}

 

 

#pragma once

#include <stdio.h>

#define MAXL 100      //最大长度

typedef int KeyType//定义关键字类型为int

typedef char InfoType;

 

typedef struct

{

    KeyType key;      //关键字项

    InfoType data;        //其他数据项,类型为InfoType

} RecType;                //查找元素的类型

                          //顺序表基本运算算法

void CreateList(RecType R[], KeyType keys[], int n); //创建顺序表

void DispList(RecType R[], int n); //输出顺序表

 

int BinSearch(RecType R[], int n, KeyType k, int &time); //折半查找算法

 

int partition(RecType R[], int s, int t);   //一趟划分

void QuickSort(RecType R[], int s, int t); //对R[s..t]的元素进行快速排序

 

 

 

#include "stdafx.h"

#include"BinSearch.h"

//顺序表基本运算算法

void CreateList(RecType R[], KeyType keys[], int n//创建顺序表

{

    for (int i = 0; i<n; i++)

         R[i].key = keys[i];

}

void DispList(RecType R[], int n//输出顺序表

{

    for (int i = 0; i<n; i++)

         printf("%d ", R[i].key);

    printf("\n");

}

 

 

int BinSearch(RecType R[], int n, KeyType k,int &time) //折半查找算法

{

    int low = 0, high = n - 1, mid;

    while (low <= high)            //当前区间存在元素时循环

    {

         mid = (low + high) / 2;

         if (k == R[mid].key)      //查找成功返回其逻辑序号mid+1

         {

             return mid + 1;

             time++;

         }

         if (k < R[mid].key)       //继续在R[low..mid-1]中查找

         {

             high = mid - 1;

             time++;

         }

         else                  //k>R[mid].key

         {

             low = mid + 1;            //继续在R[mid+1..high]中查找

             time++;

         }

    }

    return 0;                      //未找到时返回0(查找失败)

}

 

int count = 0;

int partition(RecType R[], int s, int t)    //一趟划分

{

    int i = s, j = t;

    RecType tmp = R[i];            //以R[i]为基准

    while (i<j)               //从两端交替向中间扫描,直至i=j为止

    {

         while (j>i && R[j].key >= tmp.key)

             j--;              //从右向左扫描,找一个小于tmp.key的R[j]

         R[i] = R[j];              //找到这样的R[j],放入R[i]处

         while (i<j && R[i].key <= tmp.key)

             i++;              //从左向右扫描,找一个大于tmp.key的R[i]

         R[j] = R[i];              //找到这样的R[i],放入R[j]处

    }

    R[i] = tmp;

    return i;

}

void QuickSort(RecType R[], int s, int t) //对R[s..t]的元素进行快速排序

{

    int i;

    RecType tmp;

    if (s<t)                       //区间内至少存在两个元素的情况

    {

         count++;

         i = partition(R, s, t);

         DispList(R, 10);          //调试用

         QuickSort(R, s, i - 1);        //对左区间递归排序

         QuickSort(R, i + 1, t);        //对右区间递归排序

    }

}

 

  1. 二叉查找树

#include "stdafx.h"

 

 

//二叉排序树算法

#include <stdio.h>

#include <malloc.h>

#include"SearchBST.h"

 

int main()

{

BSTNode *bt,*f,*result;

int n = 10;

char in[10];

printf("请依次输入10个不重复的字母:\n");

for(int i=0;i<10;i++)

{

    printf("请依次输入第%d个不重复的字母:\n",i);

    scanf_s("%c", &in[i]);

    getchar();

}

//KeyType a[]={25,18,46,2,53,39,32,4,74,67,60,11};

bt=CreateBST(in,n);

printf("BST:");DispBST(bt);printf("\n");

int flag,search;

printf("进入查询请输入非零数字,退出查询请输入0\n");

scanf_s("%d", &flag);

getchar();

while (flag) {

    int time = 0;

    printf("请输入要查找的字母:");

    scanf_s("%c", &search);

    result = SearchBST1(bt, search , NULL,f,time);

    getchar();

    if (result != NULL&&f !=NULL) {

         printf("%c的双亲是%c\n", search, f->key);

         printf("查找次数为:%d \n", time);

    }

    else if (result != NULL&&f == NULL) {

         printf("%c的双亲是首首元素\n", search);

         printf("查找次数为:1\n");

    }

    else if (result == NULL&&f == NULL)

         printf("查询非法\n");

    printf("进入查询请输入非零数字,退出查询请输入0\n");

    scanf_s("%d", &flag);

    getchar();

}

 

DestroyBST(bt);

return 1;

}

 

 

#pragma once

typedef char KeyType;

typedef char InfoType[10];

typedef struct node

{

    KeyType key;                   //关键字项

    InfoType data;                     //其他数据域

    struct node *lchild, *rchild;  //左右孩子指针

} BSTNode;                         //二叉排序树结点类型

bool InsertBST(BSTNode *&bt, KeyType k);

//在二叉排序树bt中插入一个关键字为k的结点。插入成功返回真,否则返回假

 

BSTNode *CreateBST(KeyType A[], int n); //创建二叉排序树

                                                //返回BST树根结点指针

 

void DispBST(BSTNode *bt); //输出一棵排序二叉树

 

BSTNode *SearchBST(BSTNode *bt, KeyType k);

 

BSTNode *SearchBST1(BSTNode *bt, KeyType k, BSTNode *f1, BSTNode *&f, int &time);

void Delete1(BSTNode *p, BSTNode *&r);  //当被删p结点有左右子树时的删除过程

 

void Delete(BSTNode *&p);  //从二叉排序树中删除p结点

 

int DeleteBST(BSTNode *&bt, KeyType k); //在bt中删除关键字为k的结点

 

void DestroyBST(BSTNode *&bt); //销毁二叉排序树bt

 

 

 

 

#include "stdafx.h"

#include"SearchBST.h"

#include <malloc.h>

bool InsertBST(BSTNode *&bt, KeyType k)//在二叉排序树bt中插入一个关键字为k的结点。插入成功返回真,否则返回假

{

    if (bt == NULL)                         //原树为空,新插入的结点为根结点

    {

         bt = (BSTNode *)malloc(sizeof(BSTNode));

         bt->key = k; bt->lchild = bt->rchild = NULL;

         return true;

    }

    else if (k == bt->key)                  //树中存在相同关键字的结点,返回假

         return false;

    else if (k<bt->key)

         return InsertBST(bt->lchild, k);   //插入到左子树中

    else

         return InsertBST(bt->rchild, k);   //插入到右子树中

}

 

BSTNode *CreateBST(KeyType A[], int n)      //创建二叉排序树

                                                //返回BST树根结点指针

{

    BSTNode *bt = NULL;                //初始时bt为空树

    int i = 0;

    while (i<n)

    {

         InsertBST(bt, A[i]);           //将关键字A[i]插入二叉排序树bt中

         i++;

    }

    return bt;                         //返回建立的二叉排序树的根指针

}

 

void DispBST(BSTNode *bt)      //输出一棵排序二叉树

{

    if (bt != NULL)

    {

         printf("%c ", bt->key);

         if (bt->lchild != NULL || bt->rchild != NULL)

         {

             printf("(");                       //有孩子结点时才输出(

             DispBST(bt->lchild);               //递归处理左子树

             if (bt->rchild != NULL) printf(",");    //有右孩子结点时才输出,

             DispBST(bt->rchild);               //递归处理右子树

             printf(")");                       //有孩子结点时才输出)

         }

    }

}

BSTNode *SearchBST(BSTNode *bt, KeyType k)

{

    if (bt == NULL || bt->key == k)         //递归终结条件

         return bt;

    if (k<bt->key)

         return SearchBST(bt->lchild, k);  //在左子树中递归查找

    else

         return SearchBST(bt->rchild, k);  //在右子树中递归查找

}

BSTNode *SearchBST1(BSTNode *bt, KeyType k, BSTNode *f1, BSTNode *&f,int &time)

/*在bt中查找关键字为k的结点,若查找成功,该函数返回该结点的指针,

f返回其双亲结点;否则,该函数返回NULL。

其调用方法如下:

SearchBST(bt,x,NULL,f);

这里的第3个参数f1仅作中间参数,用于求f,初始设为NULL*/

{

    if (bt == NULL)

    {

         f = NULL;

         return(NULL);

    }

    else if (k == bt->key)

    {

         f = f1;

         time++;

         return(bt);

    }

    else if (k < bt->key)

    {

         time++;

         return SearchBST1(bt->lchild, k, bt, f, time);//在左子树中递归查找

    }

    else

    {

         time++;

         return SearchBST1(bt->rchild, k, bt, f, time);  //在右子树中递归查找

    }

}

 

void Delete1(BSTNode *p, BSTNode *&r//当被删p结点有左右子树时的删除过程

{

    BSTNode *q;

    if (r->rchild != NULL)

         Delete1(p, r->rchild); //递归找最右下结点r

    else                      //找到了最右下结点r

    {

         p->key = r->key;          //将*结点的值赋给结点p

         q = r;

         r = r->lchild;            //直接将其左子树的根结点放在被删结点的位置上

         free(q);              //释放原结点r的空间

    }

}

void Delete(BSTNode *&p)       //从二叉排序树中删除p结点

{

    BSTNode *q;

    if (p->rchild == NULL)    //p结点没有右子树的情况

    {

         q = p;

         p = p->lchild;            //直接将其右子树的根结点放在被删结点的位置上

         free(q);

    }

    else if (p->lchild == NULL)    //p结点没有左子树的情况

    {

         q = p;

         p = p->rchild;            //将p结点的右子树作为双亲结点的相应子树

         free(q);

    }

    else Delete1(p, p->lchild);    //p结点既没有左子树又没有右子树的情况

}

int DeleteBST(BSTNode *&bt, KeyType k//在bt中删除关键字为k的结点

{

    if (bt == NULL)

         return 0;                 //空树删除失败

    else

    {

         if (k<bt->key)

             return DeleteBST(bt->lchild, k);   //递归在左子树中删除为k的结点

         else if (k>bt->key)

             return DeleteBST(bt->rchild, k);   //递归在右子树中删除为k的结点

         else

         {

             Delete(bt);       //调用Delete(bt)函数删除*bt结点

             return 1;

         }

    }

}

void DestroyBST(BSTNode *&bt)      //销毁二叉排序树bt

{

    if (bt != NULL)

    {

         DestroyBST(bt->lchild);

         DestroyBST(bt->rchild);

         free(bt);

    }

}

 

  • 实验结果及分析
  1. 顺序查找

 

2.折半查找

 

 

3.二叉查找树

 

   

  • 0
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值