zoukankan      html  css  js  c++  java
  • 暴力法

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

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

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

    选择排序算法描述:假设我们有一个元素个数为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] << "	";
    	}
    	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] << "	";
    	}
    	cout << "
    ";
    	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²),在实际的较大输入下是不行的。

  • 相关阅读:
    hadoop_05
    分布式集群时间同步
    crontab定时任务
    操作系统笔记五:输入输出系统
    操作系统笔记四:文件管理与磁盘存储器管理
    操作系统笔记三:存储器管理
    操作系统笔记二:进程与调度(2)
    操作系统笔记二:进程与调度(1)
    可能的加分项
    对老师的建议
  • 原文地址:https://www.cnblogs.com/zy666/p/10504300.html
Copyright © 2011-2022 走看看