暴力法:根据问题的描述和所涉及的概念,简单直接的解决问题的方法。
暴力法是可以用来解决广阔领域的各种问题,它也可能也是唯一一种几乎什么问题都能解决的一般性方法。在输入数据的规模并不巨大的情况下,我们可以使用暴力法来解决一些问题。
冒泡排序和选择排序就是两个很好的例子,它们就是从直观上出发,根据排序的定义做出的直观算法。
选择排序算法描述:假设我们有一个元素个数为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²),在实际的较大输入下是不行的。