暴力法

版权声明:本文为博主原创文章,转载请注明博客地址: https://blog.csdn.net/zy010101/article/details/81771581

暴力法:根据问题的描述和所涉及的概念,简单直接的解决问题的方法。

暴力法是可以用来解决广阔领域的各种问题,它也可能也是唯一一种几乎什么问题都能解决的一般性方法。在输入数据的规模并不巨大的情况下,我们可以使用暴力法来解决一些问题。

冒泡排序和选择排序就是两个很好的例子,它们就是从直观上出发,根据排序的定义做出的直观算法。

选择排序算法描述:假设我们有一个元素个数为n的序列,对它按照如下的步骤进行排序。从n个元素中找出最小的元素和该序列第一个元素交换位置;从第二个元素开始,在n-1个元素中找出最小的元素和第二个元素交换位置;一直这样做下去,直到没有可以交换的元素为止。下面是具体的代码实现。

#include <iostream>
using namespace std;
void SelectionSort(int *num,int size);	
int main()
{
	int num[10] = { 3,1,4,2,5,8,9,0,6,7 };
	SelectionSort(num, 10);
	for (int i = 0; i < 10; i++)
	{
		cout << num[i] << "\t";
	}
	cout << std::endl;
	system("pause");
}
void SelectionSort(int *num, int size)
{
	int min;
	for (int i = 0; i < size - 1; i++)	//	n个元素做n-1次比较
	{
		min = i;	//假设下标i的元素最小
		for (int j = i + 1; j < size; j++)	//  再 n - j个元素中最小的
		{
			if (num[min] > num[j])
			{
				min = j;	//记录最小元素下标
			}
		}
		//交换位置
		swap(num[min], num[i]);	//使用了using namespace std;之后就可以直接调用这个swap函数
	}
}

做算法分析可知,该算法的时间复杂度是θ(n²)。(基本操作是比较)并且这个时间复杂度是稳定的,对于任何输入都是θ(n²)。

冒泡排序算法描述:同样对于元素个数是n的序列,冒泡排序是将相邻位置逆序的元素交换位置 。一直这样重复做,直到不用交换为止。具体实现如下。

#include <iostream>
using namespace std;
void BubbleSort(int *num, int size);
int main()
{
	int num[10] = { 1,2,3,7,9,0,8,6,4,5 };
	BubbleSort(num, 10);
	for (int i = 0; i < 10; i++)
	{
		cout << num[i] << "\t";
	}
	cout << "\n";
	system("pause");
}
void BubbleSort(int * num, int size)
{
	for (int i = 0; i < size - 1; i++)	//n个元素需要n-1趟比较
	{
		for (int j = 0; j < size - i - 1; j++)	//第i趟需要比较 n - i - 1次
		{
			if (num[j] > num[j + 1])	//将大的元素放在后面
			{
				swap(num[j], num[j + 1]);	//交换位置
			}
		}
	}
}

冒泡排序的时间复杂度(基本操作是比较)和选择排序的时间复杂度是一样的θ(n²)。但是选择排序中swap的次数是n次,而在冒泡排序中swap的次数取决于输入数据是否是有序的,最坏的情况就是遇到一个降序数组,此时需要做n(n-1)/2次swap。所以即便是暴力法解决问题,也不是没有优化的余地。很明显选择排序就比冒泡排序来的更好。

字符串匹配在初学一门编程语言的时候也是常遇到的问题,最简单的办法就是暴力法去一次次匹配。C语言实现的代码如下。str1和str2那个更长是没有关系的。

#include <iostream>
using namespace std;

bool fun(char *str1, char* str2);
int main()
{
	char str1[100];
	char str2[100];
	cout << "please input string1:";
	cin >> str1;
	cout << "please input string2:";
	cin >> str2;
	if (fun(str1,str2))
	{
		cout << "Find it" << endl;
	}
	else
	{
		cout << "Not find!" << endl;
	}
	system("pause");
}
bool fun(char * str1, char* str2)
{
	int m = strlen(str1);
	int n = strlen(str2);
	int j;
	for (int i = 0; i < m - n + 1; i++)    //如果str2更长,循环就不会执行
	{
		
		for (j = 0; j < n; j++)
		{
			if (str1[i + j] == str2[j]);
			else
			{
				break;
			}
		}
		if (j == n)
		{
			return true;
		}
	}
	return false;
}

它的时间复杂度是O(mn)的。不是足够的好。

有两个著名的问题是最近对和凸包问题。最近对问题并不复杂,它要求在包含有n个点的集合S中,找出距离最近的两个点。这就是最近对问题。暴力法就是对每一个点之间的距离都进行求解,然后求出最小值。具体实现如下。

#include <iostream>
#include <complex>
#include <limits>
#include <cmath>
using namespace std;
double Point(complex<int> *num,int size);
int main()
{
	complex<int> n[5];		//这里用复数类型代替点
	for (int i = 0; i < 5; i++)
	{
		cin >> n[i];
	}
	cout << Point(n, 5) << endl;;
	system("pause");
}
double Point(complex<int> *num,int size)
{
	double min = INT_MAX;
	double temp;
	for (int i = 0; i < size - 1; i++)
	{
		for (int j = i + 1; j < size; j++)
		{
			temp = pow((num[j].real() - num[i].real()), 2) + pow(num[j].imag() - num[i].imag(), 2);
			if (min > temp)
			{
				min = temp;
			}
		}
	}
	return sqrt(min);
}

这个算法的时间复杂度是O(n²),在实际的较大输入下是不行的。

猜你喜欢

转载自blog.csdn.net/zy010101/article/details/81771581