数据结构排序、查找算法

前言

这是数据结构的实验四的题目。
为了自己能在繁杂的文件中顺利、快速地找到自己熟悉的排序、查找算法代码,故借CSDN平台存放本人写的代码。另外,还请有缘看到此文章的同行们能多多指点。
非常感谢。


1 各种排序算法的实现

用随机函数生成16个2位正整数(10~99),实现 插入排序、 选择排序、 冒泡排序、 双向冒泡、 快速排序、 二路归并排序 等多种排序算法,输出排序中间过程、统计关键字的比较次数和记录的移动次数。

1.1 代码

代码说明:
各排序算法在同一个cpp文件中,要查看某个算法时可以把main函数中的相应排序算法的注释符号“//”去掉即可;

#include<iostream>
#include<ctime>
using namespace std;

const int maxnum = 1000; 

//数组结构
typedef struct sqlist
{
	int l[maxnum];
	int length;
}sqlist;

//------插入排序-----(采用“从后向前比较”策略)
void InsertSort(sqlist list, int length)
{
	int compare_count = 0;					//关键字比较次数
	int remove_count = 0;					//关键字移动次数
	int process = 1;						//第n次中间过程
	for (int i = 2; i <= list.length; i++) {
		compare_count++;					//关键字比较次数+1
		if (list.l[i] < list.l[i - 1]) {
			list.l[0] = list.l[i];			// list.l[0]: 人称“哨兵”
			list.l[i] = list.l[i - 1];		//将list.[i]后移
			int j = 0;
			for (j = i - 2; list.l[0] < list.l[j]; j--) {
				list.l[j + 1] = list.l[j];	//将记录逐个后移
			}			
			list.l[j + 1] = list.l[0];		//将“哨兵”插入到正确的位置
			remove_count++;					//关键字移动次数+1
		}
		//中间过程输出
		cout << "第" << process++ << "次中间过程输出:" << endl;
		for (int i = 1; i <= list.length; i++) {
			cout << list.l[i] << ' ';
		}
		cout << endl;
	}

	//输出关键字比较次数和关键字移动次数
	cout << "关键字比较次数:" << compare_count << "\t"
		<< "关键字移动次数:" << remove_count << endl;
}

//-----选择排序-----
void SelectSort(sqlist& list)
{
	int k = 0;
	int process = 1;							//第n次中间过程
	int compare_count = 0;						//关键字比较次数
	int remove_count = 0;						//关键字移动次数
	for (int i = 1; i < list.length; i++) {
		k = i;
		for (int j = i + 1; j <= list.length; j++) {
			compare_count++;					//关键字比较次数+1
			if (list.l[j] < list.l[k]) k = j;	//寻找数组剩余未排序元素中的值最小元素的下标
			if (k != i) {
				remove_count++;					//关键字移动次数+1
				int temp = list.l[i];
				list.l[i] = list.l[k];
				list.l[k] = temp;
			}
		}
		//中间过程输出
		cout << "第" << process++ << "次中间过程输出:" << endl;
		for (int i = 1; i <= list.length; i++) {
			cout << list.l[i] << ' ';
		}
		cout << endl;
	}

	//输出关键字比较次数和关键字移动次数
	cout << "关键字比较次数:" << compare_count << "\t"
		<< "关键字移动次数:" << remove_count << endl;

}

//-----冒泡排序-----
void BubbleSort(sqlist& list)
{
	int n = list.length;					//作为结束循环的条件之一
	int flag = 1;							//是否排序完成的标记
	int process = 1;						//第n次中间过程
	int compare_count = 0;					//关键字比较次数
	int remove_count = 0;					//关键字移动次数

	//设置两重循环
	while (n--&&flag) {
		flag = 0;
		for (int j = 1; j < list.length; j++) {
			compare_count++;				//关键字比较次数+1
			if (list.l[j] > list.l[j + 1]) {
				remove_count++;				//关键字移动次数+1
				flag = 1;
				int temp = list.l[j];
				list.l[j] = list.l[j + 1];
				list.l[j + 1] = temp;
			}
		}
		//中间过程输出
		cout << "第" << process++ << "次中间过程输出:" << endl;
		for (int i = 1; i <= list.length; i++) {
			cout << list.l[i] << ' ';
		}
		cout << endl;
	}

	//输出关键字比较次数和关键字移动次数
	cout << "关键字比较次数:" << compare_count << "\t"
		<< "关键字移动次数:" << remove_count << endl;
}

//-----双向冒泡----
void TwowaybubbleSort(sqlist& list)
{
	int n = list.length;
	int flag = 1;
	int process = 1;						//第n次中间过程
	int compare_count = 0;					//关键字比较次数
	int remove_count = 0;					//关键字移动次数

	int left= 1;							//初始化待排序数组的最左端元素序号
	int right= list.length;					//初始化待排序数组的最右端元素序号
	int temp_right = 0;						//暂存待更新待排序数组的最右端元素序号
	int temp_left = 0;						//暂存待更新待排序数组的最左端元素序号

	//设置两重循环
	while (n--&&flag) {
		flag = 0;
		for ( int j = left; j < right; j++) {
			compare_count++;				//关键字比较次数+1
			if (list.l[j] > list.l[j + 1]) {
				flag = 1;
				remove_count++;				//关键字移动次数+1
				int temp = list.l[j];
				list.l[j] = list.l[j + 1];
				list.l[j + 1] = temp;
				temp_right = j;
			}
		}
		right = temp_right;					//更新待排序数组的最右端元素序号
		for (int j = right; j >left; j--) {
			compare_count++;				//关键字比较次数+1
			if (list.l[j] < list.l[j-1]) {
				flag = 1;
				remove_count++;				//关键字移动次数+1
				int temp = list.l[j];
				list.l[j] = list.l[j - 1];
				list.l[j - 1] = temp;
				temp_left = j;
			}
		}
		left = temp_left;					//更新待排序数组的最左端元素序号
		//中间过程输出
		cout << "第" << process++ << "次中间过程输出:" << endl;
		for (int i = 1; i <= list.length; i++) {
			cout << list.l[i] << ' ';
		}
		cout << endl;
		cout << "left,right:" << left << ' ' << right << endl;
	}

	//输出关键字比较次数和关键字移动次数
	cout << "关键字比较次数:" << compare_count << "\t"
		<< "关键字移动次数:" << remove_count << endl;
}

//-----快速排序-----
int QSort_process = 1;						//第n次中间过程
int QSort_compare_count = 0;				//关键字比较次数
int QSort_remove_count = 0;					//关键字移动次数
void QSort(sqlist& list,int low, int high)
{
	int i, j, pivotkey;
	i = low;
	j = high;
	if (low < high){
		pivotkey = list.l[low];				 //设置枢轴
		while (i != j){
			while (j > i&& list.l[j] >= pivotkey){
				--j;
				QSort_compare_count++;	 //关键字比较次数+1
			}
			if (i < j){
				list.l[i] = list.l[j];	 //交换
				++i;
				QSort_remove_count++;	 //关键字移动次数+1
			}

			while (i < j && list.l[i] <= pivotkey){
				++i;
				QSort_compare_count++;	 //关键字比较次数+1
			}
			if (i < j){
				list.l[j] = list.l[i];	 //交换
				--j;
				QSort_remove_count++;	 //关键字移动次数+1
			}
		}
		list.l[i] = pivotkey;				 //枢轴记录到位
		//中间过程输出
		cout << "第" << QSort_process++ << "次中间过程输出:" << endl;
		for (int n = 1; n <= list.length; n++) {
			cout << list.l[n] << ' ';
		}
		cout << endl;

		//递归
		QSort(list, low, i - 1);
		QSort(list, i + 1, high);
	}
}

//-----二路归并排序-----
int MSort_process = 1;						//第n次中间过程
int MSort_compare_count = 0;				//关键字比较次数
int MSort_remove_count = 0;					//关键字移动次数
void Merge(sqlist &list, int low, int mid, int high)
{
	int len = high - low + 1;
	int* temp = new int[len];
	int i = low; int j = mid + 1;			 //i,j分别为两个子序列的下标
	int k = 0;								 //新合并的数组的下标
		while (i <= mid && j <= high) {
			if (list.l[i] <= list.l[j]) {
				MSort_compare_count++;		 //关键字比较次数+1
				MSort_remove_count++;		 //关键字移动次数+1
				temp[k] = list.l[i];
				i++;
				k++;
			}
			else {
				MSort_compare_count++;		 //关键字比较次数+1
				MSort_remove_count++;		 //关键字移动次数+1
				temp[k] = list.l[j];
				j++;
				k++;
			}
		}
		while (i <= mid) {
			temp[k] = list.l[i];
			i++;
			k++;
		}
		while (j <= high) {
			temp[k] = list.l[j];
			j++;
			k++;
		}
	for (int i = 0; i < len; i++) {
		list.l[low+i] = temp[i];
	}
}

void MSort(sqlist &list,int low,int high)
{
	if (low < high) {
		int mid = (low + high) / 2;
		//递归
		MSort(list, low, mid);
		MSort(list, mid + 1, high);
		//合并左右序列(子树)
		Merge(list, low, mid, high);
	}
	//中间过程输出
	cout << "第" << MSort_process++ << "次中间过程输出:" << endl;
	for (int n = 1; n <= list.length; n++) {
		cout << list.l[n] << ' ';
	}
	cout << endl;
}


int main()
{
	/*
	-----------------------------------------
		说明:
			随机生成数组首元素下标为 1
	-----------------------------------------
	*/

	// 生成随机数组
	srand(unsigned(time));
	sqlist list;
	list.length = 0;
	cout << "请输入生成数组的长度:";
	cin >> list.length;						//输入数组的长度
	cout << "生成的数组为:";
	for (int i = 1; i <=list.length; i++){  
		list.l[i] =(int) rand() % 90 + 10;
		cout << list.l[i]<<' ';
	}
	cout << endl;

	//-----插入排序-----
	//InsertSort(list,list.length);

	//-----选择排序-----
	//SelectSort(list);

	//-----冒泡排序-----
	//BubbleSort(list);

	//-----双向冒泡-----
	//TwowaybubbleSort(list);

	//-----快速排序-----
	//QSort(list, 1, list.length);
	  //输出关键字比较次数和关键字移动次数
	//cout << "关键字比较次数:" << QSort_compare_count << "\t"
	//	<< "关键字移动次数:" << QSort_remove_count << endl;
	
	//-----归并排序-----
	//MSort(list, 1, list.length);
	  //输出关键字比较次数和关键字移动次数
	//cout << "关键字比较次数:" << MSort_compare_count << "\t"
		//<< "关键字移动次数:" << MSort_remove_count << endl;
}

1.2 运行结果

  • 插入排序
    在这里插入图片描述
  • 选择排序
    在这里插入图片描述
  • 冒泡排序
    在这里插入图片描述
  • 双向冒泡排序
    在这里插入图片描述
  • 快速排序
    在这里插入图片描述
  • 归并排序

在这里插入图片描述
在这里插入图片描述

2 各种查找算法的实现

2.1 顺序查找

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

2.1.1 代码
#include<iostream>
#include<ctime>
using namespace std;

//-----顺序查找-----
void Search_Seq(char* s)
{
	cout << "请输入想寻找的字母:";
	char x;
	cin >> x;								//输入想找的字母
	int index = 0;
	int count = 0;							//比较次数,初始化为0
	while (s[index] != '\0') {
		++count;
		if (s[index++] == x) {
			cout << "已找到字母 " << x << " ,它的下标为:" << index - 1 << endl;
			break;
		}
	}
	if (count == 17) {

		cout << "没有找到该字母,共比较了:" << count-1 << " 次"<< endl;
	}
	else cout << "共比较了:" << count << " 次";
}

int main()
{
	/*
	-----------------------------------------
		说明:
			随机生成数组首元素下标为 0
	-----------------------------------------
	*/

	// 生成随机数组
	srand(unsigned(time));
	char* s=new char[17];					//字符数组
	for (int i = 0; i < 16; i++) s[i] = '\0';
	cout << "生成的数组为:";
	int k = 0;
	while (k != 16) {
		int flag = 0;						//用于检测是否有相同的字母出现
		s[k] = 'a' + (rand() % 26);
		for (int i = 0; i < 16; i++) {
			if (k != i) {
				if (s[k] == s[i]) flag = 1;	//若flag=1,则重新加入一个字母
			}
		}
		if (flag == 0) ++k;					//若flag=0,往数组下一个位置添加字母
	}
	for (int i = 0; i < 16; i++) 
		cout << s[i] << " ";				//打印随机生成的字符数组
	s[16] = '\0';							//字符串的最后一位是'\0'
	cout << endl;

	//-----顺序查找-----
	Search_Seq(s);
}
2.1.2 运行结果
  • 查找成功
    在这里插入图片描述
  • 查找失败
    在这里插入图片描述

2.2 折半查找

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

2.2.1 代码
#include<iostream>
#include<ctime>
using namespace std;

//-----顺序查找-----

void TwowaybubbleSort(char* s)
{
	int n = 16;
	int flag = 1;							//检测是否已排序完成

	int left = 1;							//初始化待排序数组的最左端元素序号
	int right = 15;							//初始化待排序数组的最右端元素序号
	int temp_right = 0;						//暂存待更新待排序数组的最右端元素序号
	int temp_left = 0;						//暂存待更新待排序数组的最左端元素序号

	//设置两重循环
	while (n-- && flag) {
		flag = 0;							
		for (int j = left; j < right; j++) {
			if (s[j] > s[j + 1]) {
				flag = 1;
				int temp = s[j];
				s[j] =s[j + 1];
				s[j + 1] = temp;
				temp_right = j;
			}
		}
		right = temp_right;					//更新待排序数组的最右端元素序号
		for (int j = right; j > left; j--) {
			if (s[j] < s[j - 1]) {
				flag = 1;
				int temp = s[j];
				s[j] = s[j - 1];
				s[j - 1] = temp;
				temp_left = j;
			}
		}
	}
}
void Search_Bin(char* s)
{
	TwowaybubbleSort(s);					//先使用双向冒泡进行排序
	int compare_count = 0;					//记录比较次数
	cout << "请输入想寻找的字母:";
	char x;
	cin >> x;								//输入待寻找的字母
	
	int low = 0; int high = 15;
	int mid = 0;
	while (low <= high) {
		mid = (low + high) / 2;
		if (x == s[mid]) {
			compare_count++;
			cout << "已找到字母 " << x << endl;
			break;
		}
		else if (x < s[mid]) {
			compare_count++;
			high = mid - 1;
		}
		else {
			compare_count++;
			low = mid + 1;
		}
	}
	if(low>high&&x!=s[low]) cout<< "未找到该字母,总共比较了 " << compare_count << " 次" << endl;
	else cout << "总共比较了 " << compare_count << " 次" << endl;
}
	

int main()
{
	/*
	-----------------------------------------
		说明:
			随机生成数组首元素下标为 0
	-----------------------------------------
	*/

	// 生成随机数组
	srand(unsigned(time));
	char* s = new char[17];					//字符数组
	for (int i = 0; i < 16; i++) s[i] = '\0';
	cout << "生成的数组为:";
	int k = 0;
	while (k != 16) {
		int flag = 0;						//用于检测是否有相同的字母出现
		s[k] = 'a' + (rand() % 26);
		for (int i = 0; i < 16; i++) {
			if (k != i) {
				if (s[k] == s[i]) flag = 1;	//若flag=1,则重新加入一个字母
			}
		}
		if (flag == 0) ++k;					//若flag=0,往数组下一个位置添加字母
	}
	for (int i = 0; i < 16; i++)
		cout << s[i] << " ";				//打印随机生成的字符数组
	s[17] = '\0';							//字符串的最后一位是'\0'
	cout << endl;

	//-----折半查找-----
	Search_Bin(s);	
}
2.2.2 运行结果
  • 查找成功
    在这里插入图片描述
  • 查找失败
    在这里插入图片描述

2.3 二叉查找树

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

2.3.1 代码
#include<iostream>
using namespace std;

//二叉查找树结构
typedef struct BSTNode
{
	char data;
	BSTNode* lchild, * rchild;
}BSTNode,*BSTree;

//二叉排序树的插入
void InsertBST(BSTree& T, char x)
{
	if (!T) {
		BSTNode* new_tree = new BSTNode;		//生成新结点
		new_tree->data = x;
		new_tree->lchild = new_tree->rchild = NULL;
		T = new_tree;
	}
	else if (x < T->data) InsertBST(T->lchild, x);
	else if (x > T->data) InsertBST(T->rchild, x);
}
//二叉排序树的创建
void CreatBST(BSTree& T)
{
	T = NULL;
	char x;
	cin >> x;
	int i = 0;				//用于提示已经输入了多少个字母
	while (x != '#') {
		InsertBST(T, x);
		cout << "这是输入的第 " << ++i << " 个字母" << endl;
		cin >> x;
	}
}
//二叉树的先序遍历
void Preorder(BSTree T)//前序遍历(递归实现)
{
	if (T != NULL)
	{
		cout << T->data << " ";
		Preorder(T->lchild);
		Preorder(T->rchild);
	}
}
//二叉树的中序遍历
void Mreorder(BSTree T)//前序遍历(递归实现)
{
	if (T != NULL)
	{
		Mreorder(T->lchild);
		cout << T->data << " ";
		Mreorder(T->rchild);
	}
}

//-----二叉查找树-----
int compare_count = 0;				//全局变量。记录比较次数
BSTree SearchBST(BSTree T, char x)
{
	compare_count++;
	if (!T|| x == T->data) {
		if (!T)
			cout << "查询失败,共查找了 " << compare_count << " 次\n";
		else
			cout << "已找到字母 " << T->data << " ,共查找了 " << compare_count << " 次\n";
		return T;
	}
	else if (x < T->data) return SearchBST(T->lchild, x);
	else if (x >= T->data) return SearchBST(T->rchild, x);
}

int main()
{
	//创建二叉查找树
	BSTree T = new BSTNode;
	cout << "请输入十个字母(输入#结束): " << endl;
	CreatBST(T);						
	cout<<"输入完成\n";

	//中序遍历二叉查找树
	cout << "\n先序遍历输出:";
	Preorder(T);

	//中序遍历二叉查找树
	cout << "\n中序遍历输出(按照各字母的ASCⅡ码大小):"; 
	Mreorder(T);

	//输入待查找字母
	cout << "\n请输入想查询的字母(如果想退出查找,请输入$) ";
	char letter;
	cin >> letter;						

	//查找字母
	while (1 && letter != '$') {
		SearchBST(T, letter);
		cout << "\n请输入想查询的字母(如果想退出查找,请输入$) ";
		cin >> letter;
	}
}
2.3.2 运行结果

查找成功和失败都在同一张截图里了。
在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

猫咪钓鱼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值