C++数据结构:以不多于3n/2的平均比较次数在顺序表中找出最大值最小值

题目描述:以不多于3n/2的平均比较次数,在一个有n个整数的顺序表中找到最大值和最小值。要求使用的空间尽可能的少。(C++实现)

从本篇文章开始,我们使用C++来实现数据结构的相关问题,本题即是C++数据结构的一个基本问题,首先我们来实现一个顺序表,使用类定义:

class  SeqList
{
private:
	int* data; //元素
	int size; //链表大小

public:
	//构造函数
	SeqList(int n) :size(n) {
		data = new int[size]; //根据输入大小动态分配内存
	}
	SeqList() {
		delete[] data; //释放内存
	}
	void Input() { //输入顺序表中元素
		std::cout << "请输入" << size << "个整数" << std::endl;
		for (int i = 0; i < size; i++) {
			std::cin >> data[i];
		}
	}
	int Get(int index) const { //索引顺序表中某一元素
		if (index >= 0 && index < size) {
			return data[index];
		}
		else std::cout << "错误索引" << std::endl;
		return 1;
	}
};

由于题目设计的框架比较简单,所以这里我们的顺序表只需要实现一个输入元素和一个索引元素的

方法,这里只涉及C++中的一些基本输入输出。

然后就是在表中找出最大值最小值的算法,最简单最容易想到的,即是一次历边,对每个元素,比较它与当前最大、最小值的大小,然后进行修改。(list是创建的顺序表

int max, min;
max = min = list.Get(0);
for (int i = 1; i < n; i++) {
	if (list.Get(i) > max) {
		max = list.Get(i);
	}
	if (list.Get(i) < min) {
		min = list.Get(i);
	}
}

这样的程序简单,但是对每个元素进行了两次比较,使得程序的平均比较次数达到了2(n-1),超出了题目的要求!

这里我们换一种方法,两两比较法。这一方法的原理是将顺序表中的元素两两分组,然后一起与当前的最大、最小值进行比较,我们直接看代码:

	if (n % 2 == 1){  //先根据元素总数奇偶性决定max、min的初始值
		max = min = list.Get(0); //为奇数,直接赋为首元素1
	}
	else{ //为偶数,先比较前两个元素,决出最大最小值
		if (list.Get(0) > list.Get(1)) {
			max = list.Get(0);
			min = list.Get(1);
		}
		else {
			min = list.Get(0);
			max = list.Get(1);
		}
	}
	for (int i = (n % 2 == 0) ? 2 : 1; i < n; i += 2) {
		//每两个为一组,先决出组内的最大最小值,再与当前的最大最小值比较
		if (list.Get(i) > list.Get(i + 1)) { 
			if (list.Get(i) > max) {
				max = list.Get(i);
			}
			if (list.Get(i + 1) < min) {
				min = list.Get(i + 1);
			}
		}
		else {
			if (list.Get(i) < min) {
				min = list.Get(i);
			}
			if (list.Get(i + 1) > max) {
				max = list.Get(i + 1);
			}
		}
	}

 由此,每两个元素进行了三次比较,那么n个整数的顺序表总共比较了3n/2次满足了题目要求。

以下是完整代码:

#include<iostream>
using namespace std;

class  SeqList
{
private:
	int* data; //元素
	int size; //链表大小

public:
	//构造函数
	SeqList(int n) :size(n) {
		data = new int[size]; //根据输入大小动态分配内存
	}
	SeqList() {
		delete[] data; //释放内存
	}
	void Input() { //输入顺序表中元素
		std::cout << "请输入" << size << "个整数" << std::endl;
		for (int i = 0; i < size; i++) {
			std::cin >> data[i];
		}
	}
	int Get(int index) const { //索引顺序表中某一元素
		if (index >= 0 && index < size) {
			return data[index];
		}
		else std::cout << "错误索引" << std::endl;
		return 1;
	}
};

int main() {
	int n;
	std::cout << "输入顺序表的大小:";
	std::cin >> n;
	SeqList list(n);
	list.Input();

	int max, min;
	/*max = min = list.Get(0);
	for (int i = 1; i < n; i++) {
		if (list.Get(i) > max) {
			max = list.Get(i);
		}
		if (list.Get(i) < min) {
			min = list.Get(i);
		}
	}*/
	//每两个元素为一组进行比较
	if (n % 2 == 1){  //先根据元素总数奇偶性决定max、min的初始值
		max = min = list.Get(0); //为奇数,直接赋为首元素1
	}
	else{ //为偶数,先比较前两个元素,决出最大最小值
		if (list.Get(0) > list.Get(1)) {
			max = list.Get(0);
			min = list.Get(1);
		}
		else {
			min = list.Get(0);
			max = list.Get(1);
		}
	}
	for (int i = (n % 2 == 0) ? 2 : 1; i < n; i += 2) {
		//每两个为一组,先决出组内的最大最小值,再与当前的最大最小值比较
		if (list.Get(i) > list.Get(i + 1)) { 
			if (list.Get(i) > max) {
				max = list.Get(i);
			}
			if (list.Get(i + 1) < min) {
				min = list.Get(i + 1);
			}
		}
		else {
			if (list.Get(i) < min) {
				min = list.Get(i);
			}
			if (list.Get(i + 1) > max) {
				max = list.Get(i + 1);
			}
		}
	}
	//每两个元素共比较3次,平均比较次数为3n/2

	std::cout << "最大值:" << max << endl << "最小值:" << min << std::endl;
	return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值