【数据结构】查找与排序(一)—>“监视哨”的学习

一、前言

本篇以学生信息管理系统为背景,主要学习简单的查找与排序功能。

高级查找与排序会在接下来的文章中再做介绍,欢迎大家关注并留意博主动态。

查找主要涉及顺序查找、二分查找。

排序主要涉及直接插入排序、直接选择排序、冒泡排序。

 二、查找讲解

1、顺序查找

(1)普通的顺序查找

 顺序查找就是依托顺序表的存储特点:顺序存储,利用其相邻的存储位置进行查找操作。

void SqSearch(SqList L)
{
	int i = 0;
	int flag = 0;
	cout << "请输入你要查找的学生姓名>:";
	char arr[10] = "\0";
	scanf("%s", arr);
	for (i = 0; i < L.length; i++)
	{
		if (strcmp(L.elem[i].name, arr) == 0)
		{
			flag = 1;
			cout << "该学生信息如下>:" << endl;
			OutList(L, i);
			break;
		}
	}
	if (flag == 0)
		cout << "未找到该学生!" << endl;
}

根据函数我们可以清晰地了解到,这种普通的顺序查找方式每次循环都需要进入判断i<L.length。即这一算法需要进行两次判断,一是查找位置是否合法:i<L.length,二是该位置的元素是否是我们要查找的元素:strcmp(L.elem[i].name, arr) == 0,那么我们是否可以每次进行一次判断就得到我们想要的结果呢,答案是肯定的,请看下文“监视哨”顺序查找的介绍。

(2)“监视哨”顺序查找

“监视哨”就是在顺序表中留出一个位置,不管是头部还是尾部,每次只需要将待比较的元素与“监视哨”位置的元素比较即可,这样每次都能节省一次判断,算法如下:

int SqSearch(SqList L)
{
	int i = 0;
	cout << "请输入你要查找的学生姓名>:";
	char arr[10] = "\0";
	scanf("%s", arr);
    strcpy(L.elem[0].name,arr);
	for (i = L.length; strcmp(L.elem[i].name, arr) != 0; i--)
    {
        ;//空语句
    }
	return i;
}

 当返回值为0时,证明查找失败。 

利用监视哨的方式进行查找,只需要留出一个顺序表中的位置,所带来的效率提升还是比较明显的,尤其是在数据庞大的时候。

2、二分查找 

二分查找适用的是有序表,即原始数据必须有序,他的思想就是从表的中间记录开始,用给定值与中间值比较,如果相等,则查找成功,如果给定值大于或小于中间值,则在表中大于或小于的那一半中继续查找。

//二分查找
void binaryFld(SqList L)
{
	cout << "请输入你要查找的学生学号>:";
	int id = 0;
	cin >> id;
	int low = 0;
	int high = L.length - 1;
	int flag = 0;
	while (low <= high)
	{
		int mid = (low + high) / 2;//mid的赋值位置尤为重要
		if (L.elem[mid].stu_id < id)
		{
			low = mid + 1;
		}
		else if (L.elem[mid].stu_id > id)
		{
			high = mid - 1;
		}
		else
		{
			flag = 1;
			cout << "你要查找的学生信息如下>:" << endl;
			OutList(L, mid);
			break;
		}
	}
	if (flag == 0)
		cout << "未找到该学生!" << endl;
}

需要尤其注意的是,mid赋值的位置尤为重要,如果你不小心将mid的复制位置放在了循环外,就会引起程序错误,进入死循环。 

三、排序讲解

1、直接插入排序

直接插入排序的思想是将数据分为两部分,一部分为已排序部分,另一部分为待排序部分,每次从待排序部分的第一个元素插入到已排序部分中。

//直接插入排序
void Insert_sorting(SqList &L)
{
	int i = 0;
	for (i = 1; i < L.length; i++)//默认单个元素为有序,所以从第二个元素开始
	{
		Stu t={0};
		if (strcmp(L.elem[i].name,L.elem[i - 1].name)<0)比较元素大小
		{
			t= L.elem[i];
			L.elem[i]= L.elem[i - 1];
			//寻找插入位置
			int j = 0;
			for (j = i - 1; strcmp(L.elem[j].name,t.name)>0 ; j--)
			{
				L.elem[j + 1]= L.elem[j];//元素后移
			}
			L.elem[j + 1]= t;插入元素
		}
	}
}

思想滤清后,我们得到以下步骤 :

 分析直接插入排序思想,我们需要解决的问题为三个,一是将待排序元素与已排序元素比较大小,二是寻找合适的插入位置,三是元素后移并插入。

2、直接选择排序

直接选择排序的思想就是每次从待排序数据中找到最小值,并从头开始替换。

//直接选择排序
void Choose_sorting(SqList& L)
{
	int i = 0;
	int k = 0;
	int j = 0;
	Stu tmp = {0};
	for (i = 0; i < L.length; i++)
	{
		k = i;
		for (j = i + 1; j < L.length; j++)//寻找最小值
		{
			if (L.elem[k].stru_score > L.elem[j].stru_score)
			{
				k = j;
			}
		}
		if (k != i)//替换数据
		{
			tmp = L.elem[i];
			L.elem[i] = L.elem[k];
			L.elem[k] = tmp;
		}
	}
}

分析直接选择排序思想,我们需要解决的问题为两个,一是将寻找最小值,二是逐个替换。

 3、冒泡排序

冒泡排序的思想是交换,即待排序数据依次两两比较,将较大者保持在每轮的最后一个。

这样每一轮的最大值就交换到了尾部,再进行新一轮的比较,将次大值交换到最大值的钱一个位置,依次循环进行。

void Bubbling_sorting(SqList& L)
{
	int i = 0;
	int m = L.length - 1;
	int flag = 1;
	Stu tmp = { 0 };
	while (m > 0 && flag == 1)
	{
		flag = 0;
		for (i = 0; i < m; i++)
		{
			if (L.elem[i].cpp_score > L.elem[i + 1].cpp_score)
			{
				flag = 1;
				tmp = L.elem[i + 1];
				L.elem[i + 1] = L.elem[i];
				L.elem[i] = tmp;
			}
		}
		--m;
	}
}

四、完整程序

1、头文件

#ifndef _Search_h
#define _Search_h

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

using namespace std;

typedef int Status;

#define MAXSIZE 100
#define OK 1
#define ERROR 0
#define NUM 8//表长
#define OVERFLOW -1

typedef struct
{
	int stu_id;
	char name[10];
	char class_id[10];
	int cpp_score;
	int stru_score;
}Stu;

typedef struct
{
	Stu* elem;
	int length;
}SqList;

//菜单
void menu();
//信息初始化
Status InitList(SqList &L);
//输出数据
void OutList(SqList L, int i);
//输出全部数据
void OutAllList(SqList L);
//顺序查找
void SqSearch(SqList L);
//二分查找
void binaryFld(SqList L);
//直接插入排序
void Insert_sorting(SqList &L);
//冒泡排序
void Bubbling_sorting(SqList &L);
//直接选择排序
void Choose_sorting(SqList& L);
#endif

2、功能函数文件

#include"Search.h"

//菜单
void menu()
{
	printf("*******************学生成绩管理系统*******************\n");
	printf("*        1.信息初始化             2.顺序查找         *\n");
	printf("*        3.二分查找               4.直接插入排序     *\n");
	printf("*        5.冒泡排序               6.直接选择排序     *\n");
	printf("*        0.退出                                      *\n");
	printf("******************************************************\n");
}

//初始化
Status InitList(SqList& L)
{
	L.elem = new Stu[MAXSIZE];
	if (!L.elem)
		exit(OVERFLOW);
	L.length = NUM;
	int i = 0;
	for (i = 0; i < L.length; i++)
	{
		cout << "请依次输入学号,姓名,班级,C++成绩,数据结构成绩>:";
		scanf("%d", &L.elem[i].stu_id);
		scanf("%s", L.elem[i].name);
		scanf("%s", L.elem[i].class_id);
		scanf("%d", &L.elem[i].cpp_score);
		scanf("%d", &L.elem[i].stru_score);
	}
//	L.elem[0] = { 1,"王立","03511",85,76 };
//	L.elem[1] = { 2,"张秋","03511",78,88 };
//	L.elem[2] = { 3,"刘丽","03511",90,79 };
//	L.elem[3] = { 4,"王通","03511",75,86 };
//	L.elem[4] = { 5,"赵阳","03511",60,71 };
//	L.elem[5] = { 6,"李艳","03511",58,68 };
//	L.elem[6] = { 7,"钱娜","03511",95,89 };
//	L.elem[7] = { 8,"孙胜","03511",45,60 };
	return OK;
}

//输出某一数据
void OutList(SqList L, int i)
{
	cout << L.elem[i].stu_id << "\t" << L.elem[i].name << "\t" << L.elem[i].class_id << "\t"
		<< L.elem[i].cpp_score << "\t" << L.elem[i].stru_score << endl;
}

//输出全部数据
void OutAllList(SqList L)
{
	int i = 0;
	for (i = 0; i < L.length; i++)
	{
		cout << L.elem[i].stu_id << "\t" << L.elem[i].name << "\t" << L.elem[i].class_id << "\t"
			<< L.elem[i].cpp_score << "\t" << L.elem[i].stru_score << endl;
	}
}

//顺序查找
void SqSearch(SqList L)
{
	int i = 0;
	int flag = 0;
	cout << "请输入你要查找的学生姓名>:";
	char arr[10] = "\0";
	scanf("%s", arr);
	for (i = 0; i < L.length; i++)
	{
		if (strcmp(L.elem[i].name, arr) == 0)
		{
			flag = 1;
			cout << "该学生信息如下>:" << endl;
			OutList(L, i);
			break;
		}
	}
	if (flag == 0)
		cout << "未找到该学生!" << endl;
}

//二分查找
void binaryFld(SqList L)
{
	cout << "请输入你要查找的学生学号>:";
	int id = 0;
	cin >> id;
	int low = 0;
	int high = L.length - 1;
	int flag = 0;
	while (low <= high)
	{
		int mid = (low + high) / 2;
		if (L.elem[mid].stu_id < id)
		{
			low = mid + 1;
		}
		else if (L.elem[mid].stu_id > id)
		{
			high = mid - 1;
		}
		else
		{
			flag = 1;
			cout << "你要查找的学生信息如下>:" << endl;
			OutList(L, mid);
			break;
		}
	}
	if (flag == 0)
		cout << "未找到该学生!" << endl;
}

//直接插入排序
void Insert_sorting(SqList &L)
{
	int i = 0;
	for (i = 1; i < L.length; i++)
	{
		Stu t={0};
		if (strcmp(L.elem[i].name,L.elem[i - 1].name)<0)
		{
			t= L.elem[i];
			L.elem[i]= L.elem[i - 1];
			//寻找插入位置
			int j = 0;
			for (j = i - 1; strcmp(L.elem[j].name,t.name)>0 ; j--)
			{
				L.elem[j + 1]= L.elem[j];
			}
			L.elem[j + 1]= t; 
		}
	}
}



//冒泡排序
void Bubbling_sorting(SqList& L)
{
	int i = 0;
	int m = L.length - 1;
	int flag = 1;
	Stu tmp = { 0 };
	while (m > 0 && flag == 1)
	{
		flag = 0;
		for (i = 0; i < m; i++)
		{
			if (L.elem[i].cpp_score > L.elem[i + 1].cpp_score)
			{
				flag = 1;
				tmp = L.elem[i + 1];
				L.elem[i + 1] = L.elem[i];
				L.elem[i] = tmp;
			}
		}
		--m;
	}
}

//直接选择排序
void Choose_sorting(SqList& L)
{
	int i = 0;
	int k = 0;
	int j = 0;
	Stu tmp = {0};
	for (i = 0; i < L.length; i++)
	{
		k = i;
		for (j = i + 1; j < L.length; j++)
		{
			if (L.elem[k].stru_score > L.elem[j].stru_score)
			{
				k = j;
			}
		}
		if (k != i)
		{
			tmp = L.elem[i];
			L.elem[i] = L.elem[k];
			L.elem[k] = tmp;
		}
	}
}

3、主函数文件

#include"Search.h"

int main()
{
	SqList L;
	int input = 0;
	do
	{
		menu();
		printf("请选择>:");
		cin >> input;
		switch (input)
		{
		case 1:
			//信息初始化
			InitList(L);
			break;
		case 2:
			//顺序查找
			SqSearch(L);
			break;
		case 3:
			//二分查找
			binaryFld(L);
			break;
		case 4:
			//直接插入排序
			cout << "排序前表为>:" << endl;
			OutAllList(L);
			Insert_sorting(L);
			cout << "排序后表为>:" << endl;
			OutAllList(L);
			break;
		case 5:
			//冒泡排序
			cout << "排序前表为>:" << endl;
			OutAllList(L);
			Bubbling_sorting(L);
			cout << "排序后表为>:" << endl;
			OutAllList(L);
			break;
		case 6:
			//直接选择排序
			cout << "排序前表为>:" << endl;
			OutAllList(L);
			Choose_sorting(L);
			cout << "排序后表为>:" << endl;
			OutAllList(L);
			break;
		case 0:
			cout << "退出系统" << endl;
			break;
		}
	} while (input);
	return 0;
}

 四、总结

简单的查找与排序相信大家都很容易理解,博主会持续更新查找排序算法,欢迎大家关注博主动态🔥🔥🔥

  • 30
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

樊梓慕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值