实验六——数据的查找与排序

数据结构-查找的实现及其应用

第1关:顺序查找

测试说明

可在右侧文件夹中查看step1/Main.cpp文件,以便于你的操作。

平台会对你编写的代码进行测试。

输入说明: 第一行输入若干记录的关键字,以-1标志结束。 第二行输入待查找的关键字。 输出说明: 第一行输出静态查找表L中各记录的关键字。 第二行输出查找的结果,如果找到,则输出该记录在表中的位置,否则输出not find!

测试输入: 37 21 75 55 64 19 -1 55 //待查找的关键字为55

预期输出: 37 21 75 55 64 19 4 //末尾换行

/*************************************************************
    顺序查找  实现文件    
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "search.h"

int Search_Seq(SSTable L, KeyType key) 
{/*在静态查找表L中采用顺序查找法,查找其关键字等于key的记录,若找到返回该记录在表中位置,否则返回0*/
	// 请在这里补充代码,完成本关任务
    /********** Begin *********/
	int i=0;
    int index=0;
    for(i==1;i<=L.length;i++)
    {
        if(L.r[i].key==key)
            index=i;
    }
    return index;	
    /********** End **********/	
}
void SSTableInput(SSTable &L) /*输入若干记录的关键字,存放到静态查找表L中*/
{
	int i=1; KeyType x;
	scanf("%d",&x);
	while(x!=-1)
	{
		L.r[i++].key=x; scanf("%d",&x);
	}
	L.length=i-1;
}
void SSTableOutput(SSTable L) /*输出静态查找表L中各记录的关键字*/
{
	int i;
	for(i=1;i<=L.length;i++)
		printf("%d ",L.r[i].key);
	printf("\n");
}

 第2关:折半查找

折半查找

算法思想:先确定待查元素所在范围;然后找中间元素;将中间元素与给定值 x 比较:若相等,则查找成功;若 x 小,则缩小至左半区;若 x 大,则缩小至右半区;直到相等或范围的下界﹥上界为止。 适用:有序的顺序表。

编程要求

在右侧编辑器中补充代码,完成Search_Bin函数,以实现顺序查找。具体要求如下:

* Search_Bin:在递增或递减有序的表中查找其关键字等于key的记录,若找到返回该记录在表中位置,否则返回0。

/*************************************************************
    折半查找  实现文件  
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "search.h"	

int Search_Bin(SSTable L, KeyType key)/*在递增有序的顺序表L中折半查找其关键字等于key的记录*/
{
	// 请在这里补充代码,完成本关任务
    /********** Begin *********/
    int i=1;
    int left=1;
    int right=L.length;
    int mid=(left+right)/2;
	while(left<=right)	
    {
        if(key>L.r[mid].key)
        {
            left=mid+1;
            mid=(left+right)/2;
        }
        else if(key<L.r[mid].key)
        {
            right=mid-1;
            mid=(left+right)/2;
        }
        else
            return mid;
    }
    return 0;
    /********** End **********/
}
void SSTableInput(SSTable &L) /*输入若干记录的关键字,存放到静态查找表L中*/
{
	int i=1; KeyType x;
	scanf("%d",&x);
	while(x!=-1)
	{
		L.r[i++].key=x; scanf("%d",&x);
	}
	L.length=i-1;
}
void SSTableOutput(SSTable L) /*输出静态查找表L中各记录的关键字*/
{
	int i;
	for(i=1;i<=L.length;i++)
		printf("%d ",L.r[i].key);
	printf("\n");
}

 第3关:二叉排序树的查找

输入说明: 第一行输入若干记录的关键字,以-1标志结束。 第二行输入待查找的关键字。 输出说明: 第一行输出二叉排序树先序遍历的结果。 第二行输出二叉排序树中序遍历的结果。 第三行输出查找的结果,如果找到,则输出该结点的双亲结点的关键字,否则输出not find!

测试输入: 19 14 66 21 83 27 55 13 10 50 -1 55 //待查找的关键字为55

预期输出: PreOrder:19 14 13 10 66 21 27 55 50 83 //先序遍历的结果 InOrder:10 13 14 19 21 27 50 55 66 83 //中序遍历的结果 27 //末尾换行

/*************************************************************
    二叉排序树的查找  实现文件
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "search.h"	

BiTree Search_BST(BiTree T, KeyType key, BiTree &parent)
{/*在二叉排序树T上查找其关键字等于key的记录结点。若找到返回该结点指针,parent指向其双亲;否则返回空指针,parent指向访问路径上最后一个结点。*/
	// 请在这里补充代码,完成本关任务
    /********** Begin *********/
    while(T)
    {
        if(T->data.key==key)
            return T;
        else
        {
            parent=T;
            T=(key>T->data.key)?T->rchild:T->lchild;
        }
    }
    return NULL;

    /********** End **********/	
}
void Insert_BST(BiTree &T, RedType r)/*若二叉排序树T中没有关键字为r.key的记录,则插入*/
{
	BiTree p,q,parent;
	parent=NULL;
	p=Search_BST(T,r.key,parent); /*查找*/
	if(p) printf("BST中有结点r,无需插入\n");
	else
	{
		p=parent;
		q=(BiTNode *)malloc(sizeof(BiTNode)); q->data=r; q->lchild=q->rchild=NULL;
		if(T==NULL) T=q; /*若T为空,则q为新的根*/
		else if(r.key<p->data.key) p->lchild=q;
		else p->rchild=q;
	}
}
void Create_BST(BiTree &T ) /*二叉排序树的构造*/
{/*输入若干记录的关键字(以-1标志结束),生成一棵BST,采用二叉链表存储,返回其根指针T*/
    RedType r;
	T=NULL; /*建空树*/
	scanf("%d",&r.key);
	while(r.key!=-1)
	{
		Insert_BST(T, r);
		scanf("%d",&r.key);
	}
}
void PreOrder(BiTree bt) /*先序遍历*/
{
	if(bt)
	{
		printf("%d ",bt->data.key);
		PreOrder(bt->lchild);
		PreOrder(bt->rchild);
	}
}
void InOrder(BiTree bt) /*中序遍历*/
{
	if(bt)
	{
		InOrder(bt->lchild);
		printf("%d ",bt->data.key);
		InOrder(bt->rchild);
	}
}

 数据结构-排序的实现及其应用

第1关:直接插入排序

输入说明: 输入若干记录的关键字,以-1标志结束。

输出说明: 前三行输出前三趟排序后的关键字序列。 最后一行输出排序之后的关键字序列。

平台会对你编写的代码进行测试。

测试输入: 7 1 4 6 8 9 5 2 3 10 -1

预期输出: 1 7 4 6 8 9 5 2 3 10 1 4 7 6 8 9 5 2 3 10 1 4 6 7 8 9 5 2 3 10 1 2 3 4 5 6 7 8 9 10 //末尾换行

/*************************************************************
    直接插入排序  实现文件  
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sort.h"
	
void InsertSort(SeqList  &L) /*直接插入排序*/
{	
	int i,j;
	for(i=2;i<=L.length;i++)
	// 请在这里补充代码,完成本关任务
    /********** Begin *********/
	{
        int temp=L.r[i].key;
        j=i-1;
        while(j>0 && L.r[j].key>temp){
            L.r[j+1].key=L.r[j].key;
            j--;
        }
        L.r[j+1].key=temp;
        if(i<=4)
            SeqListOutput(L);
        
        
    }
    /********** End **********/	
}
void SeqListInput(SeqList &L) /*输入若干记录的关键字,存放到顺序表L中*/
{
	int i=1; KeyType x;
	scanf("%d",&x);
	while(x!=-1)
	{
		L.r[i++].key=x; scanf("%d",&x);
	}
	L.length=i-1;
}
void SeqListOutput(SeqList L) /*输出顺序表L中各记录的关键字*/
{
	int i;
	for(i=1;i<=L.length;i++)
		printf("%d ",L.r[i].key);
	printf("\n");
}

 第2关:希尔排序

输入说明: 输入若干记录的关键字,以-1标志结束。

输出说明: 第一行输出排序之前的各记录的关键字。 第二行输出排序之后的各记录的关键字。

平台会对你编写的代码进行测试。

测试输入: 49 38 65 97 76 13 27 49 -1

预期输出: 49 38 65 97 76 13 27 49 13 27 38 49 49 65 76 97 //末尾换行

/*************************************************************
    希尔排序  实现文件    
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sort.h"
	
void ShellInsert(SeqList &L, int d) /*对顺序表L作一趟增量为d的希尔插入排序*/
{
	// 请在这里补充代码,完成本关任务
    /********** Begin *********/
	int i,j,temp;
    for(i=d+1;i<=L.length;i++){
        temp=L.r[i].key;
        j=i-d;

        while(j>0 && L.r[j].key>temp){
            L.r[j+d].key=L.r[j].key;
            j-=d;
        }
        L.r[j+d].key=temp;
    }
	/********** End **********/	
}
void ShellSort(SeqList &L) /*希尔排序*/
{
	int d;
	d=L.length/2;
	while(d!=0)  /*调用一趟增量为d的希尔插入排序*/
	{
		ShellInsert(L,d); d=d/2;
	}
}
void SeqListInput(SeqList &L) /*输入若干记录的关键字,存放到顺序表L中*/
{
	int i=1; KeyType x;
	scanf("%d",&x);
	while(x!=-1)
	{
		L.r[i++].key=x; scanf("%d",&x);
	}
	L.length=i-1;
}
void SeqListOutput(SeqList L) /*输出顺序表L中各记录的关键字*/
{
	int i;
	for(i=1;i<=L.length;i++)
		printf("%d ",L.r[i].key);
	printf("\n");
}

 第3关:快速排序

算法思想:首先在待排记录中任取一个记录(通常取第一个记录)作为枢轴,将枢轴放入适当的位置后,待排记录被枢轴分割成两部分,并使得枢轴左边记录的关键字均小于枢轴,右边的均大于枢轴;然后分别对这两部分继续进行快速排序,以达到整个序列有序。

/*************************************************************
    快速排序  实现文件    
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sort.h"
	
void QuickSort(SeqList &L, int low, int high) {
    if (low < high) {
        int i = low, j = high;
        KeyType pivot = L.r[low].key; // Choose the first element as the pivot

        while (i < j) {
            while (i < j && L.r[j].key >= pivot)
                j--;
            if (i < j)
                L.r[i++] = L.r[j];

            while (i < j && L.r[i].key <= pivot)
                i++;
            if (i < j)
                L.r[j--] = L.r[i];
        }

        L.r[i].key = pivot; // Put the pivot in its correct position

        QuickSort(L, low, i - 1);  // Recursively sort the left subarray
        QuickSort(L, i + 1, high); // Recursively sort the right subarray
    }
}

void SeqListInput(SeqList &L) /*输入若干记录的关键字,存放到顺序表L中*/
{
	int i=1; KeyType x;
	scanf("%d",&x);
	while(x!=-1)
	{
		L.r[i++].key=x; scanf("%d",&x);
	}
	L.length=i-1;
}
void SeqListOutput(SeqList L) /*输出顺序表L中各记录的关键字*/
{
	int i;
	for(i=1;i<=L.length;i++)
		printf("%d ",L.r[i].key);
	printf("\n");
}

 第4关:堆排序

(1) Ki​≤K2i​ 且 Ki​≤K2i+1​ ,i=1,2,...,⌊ n/2 ⌋,称为小顶堆;

(2) Ki​≥K2i​ 且 Ki​≥K2i+1​ ,i=1,2,...,⌊ n/2 ⌋,称为大顶堆。

  • 如果用一维数组存放该序列,并把此数组看成是一棵完全二叉树的顺序存储结构,则堆实质上是满足如下性质的完全二叉树:树中所有分支结点的关键字值 Ki​ 均不大于(或不小于)其左右孩子结点的关键字值 K2i​K2i+1​

  • 若序列{ k1,k2,…,kn }是堆,则堆顶元素必为序列中最小值(或最大值)。

算法思想:首先将待排序列建成一个堆,得到关键字最小(或最大)的记录,输出堆顶的最小(大)值;然后将剩余的n-1个元素重新建成一个堆,得到次小值,输出堆顶;如此反复执行,便能得到一个有序序列。这一过程称为“堆排序”。

/*************************************************************
    堆排序  实现文件    
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sort.h"
	
void HeapAdjust(SeqList &L, int low, int high) {
    /*已知L.r[low..high]中记录的关键字除L.r[low].key之外均满足堆的定义,*/
    /*调整L.r[low].key,使L.r[low..high]成为一个新大顶堆。*/

    // 请在这里补充代码,完成本关任务
    /********** Begin **********/
    int i = low, j = 2 * i; // 左孩子结点
    RedType temp = L.r[i];

    while (j <= high) {
        // 比较左右孩子,找到较大的孩子
        if (j < high && L.r[j].key < L.r[j + 1].key) {
            j++;
        }

        // 如果父结点大于等于较大的孩子,调整结束
        if (temp.key >= L.r[j].key) {
            break;
        }

        // 将较大的孩子上移
        L.r[i] = L.r[j];
        i = j;
        j = 2 * i;
    }

    L.r[i] = temp; // 将原先的L.r[i]放入正确位置
    /********** End **********/
}

void HeapSort(SeqList &L) /*堆排序*/
{
	int i;
	for(i=L.length/2;i>0;i--)/*从最后一个分支结点(编号为L.length/2)开始调整,建立初始堆*/
		HeapAdjust(L,i,L.length);
	for(i=L.length;i>1;i--)
	{
		L.r[0]=L.r[1];L.r[1]=L.r[i];L.r[i]=L.r[0];/*将堆顶L.r[1]和当前最后一个记录L.r[i]交换*/
		HeapAdjust(L,1,i-1);/*将剩余记录L.r[1..i-1]重新调整为堆*/
	}
}
void SeqListInput(SeqList &L) /*输入若干记录的关键字,存放到顺序表L中*/
{
	int i=1; KeyType x;
	scanf("%d",&x);
	while(x!=-1)
	{
		L.r[i++].key=x; scanf("%d",&x);
	}
	L.length=i-1;
}
void SeqListOutput(SeqList L) /*输出顺序表L中各记录的关键字*/
{
	int i;
	for(i=1;i<=L.length;i++)
		printf("%d ",L.r[i].key);
	printf("\n");
}

 第5关:冒泡排序

冒泡排序重复地遍历待排序的数列,每次比较两个相邻元素,如果它们的顺序错误就把它们交换。重复地进行遍历直到没有再需要交换时表示数列已经排序完成。

  • 算法步骤:
  1. 比较相邻的元素:若第一个比第二个大,则交换;
  2. 遍历开始第一对到结尾最后一对,执行步骤1
  3. 重复步骤1~`2`,直到排序完成。
  • 可改进的冒泡排序:第一趟排序之后最后一个元素是最大的,因此下一趟遍历只需执行到倒数第二对。
  • 本关任务:实现冒泡排序算法,并将乱序数列变成升序。要求输出前三趟排序结果和最后一趟排序结果。

 

/*************************************************************
    冒泡排序  实现文件  
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "BubbleSort.h"

void BubbleSort(SeqList &L) {
    /*冒泡排序,输出前三趟排序后的关键字序列*/

    // 请在这里补充代码,完成本关任务
    /********** Begin **********/
    int i, j;
    int time=3;
    for (i = 1; i <L.length; i++) {

        for (j = 1; j <= L.length - i; j++) {
            if (L.r[j].key > L.r[j + 1].key) {
                // 如果前一个元素大于后一个元素,交换它们
                KeyType temp = L.r[j].key;
                L.r[j].key = L.r[j + 1].key;
                L.r[j + 1].key = temp;

            }
        }
        // 输出本趟排序后的结果
        if(time>0){
            SeqListOutput(L);
            time--;
        }

    }
    /********** End **********/
}
void SeqListInput(SeqList &L) /*输入若干记录的关键字,存放到顺序表L中*/
{
	int i=1; KeyType x;
	scanf("%d",&x);
	while(x!=-1)
	{
		L.r[i++].key=x; scanf("%d",&x);
	}
	L.length=i-1;
}
void SeqListOutput(SeqList L) /*输出顺序表L中各记录的关键字*/
{
	int i;
	for(i=1;i<=L.length;i++)
		printf("%d ",L.r[i].key);
	printf("\n");
}

 第6关:选择排序

本关任务:实现选择排序算法,并将乱序数列变成升序,要求输出前三趟排序结果和最后的排序结果。

选择排序算法

选择排序是一种简单直观的排序算法,首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

  • 算法步骤:
  1. 初始状态:无序序列为R[0,n−1],长度n,有序区为空;

  2. 第i=1,..,n−1趟排序从当前无序区R[i−1,n−1]中选出最小的元素R[k],并将它与无序区的第1个记录R[i−1]交换,则R[0,i−1]变为元素个数增加1的新有序区,R[i,n−1]变为元素个数减少1的新无序区;

  3. n−1趟选择交换后结束。

 

/*************************************************************
    选择排序  实现文件  
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SelectSort.h"
void SelectSort(SeqList &L) {
    /*选择排序,并输出前三次选择操作后的序列*/

    // 请在这里补充代码,完成本关任务
    /********** Begin **********/
    int i, j, minIndex;

    for (i = 1; i <= L.length; i++) {
        minIndex = i; // 假设当前位置的元素最小

        // 从未排序部分选择最小的元素
        for (j = i + 1; j <= L.length; j++) {
            if (L.r[j].key < L.r[minIndex].key) {
                minIndex = j;
            }
        }

        // 交换找到的最小元素与当前位置元素
        KeyType temp = L.r[i].key;
        L.r[i].key = L.r[minIndex].key;
        L.r[minIndex].key = temp;

        // 输出前三次选择操作后的序列
        if (i <= 3) {
            SeqListOutput(L);
        }
    }
    /********** End **********/
}
void SeqListInput(SeqList &L) /*输入若干记录的关键字,存放到顺序表L中*/
{
	int i=1; KeyType x;
	scanf("%d",&x);
	while(x!=-1)
	{
		L.r[i++].key=x; scanf("%d",&x);
	}
	L.length=i-1;
}
void SeqListOutput(SeqList L) /*输出顺序表L中各记录的关键字*/
{
	int i;
	for(i=1;i<=L.length;i++)
		printf("%d ",L.r[i].key);
	printf("\n");
}

  • 18
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值