算法介绍(一)

今天简单总结了几种算法,具体有:
【选择排序,冒泡排序,插入排序,蛮力字符串匹配,顺序查找,凸包问题的蛮力解法】

选择排序:(假定升序,问题规模为n

【步骤】

I、(初始int k = 0),假定第k数为最小min

2、然后将其与其他n-1个数作比较,若有比a[k] 小的,则两数交换位置;

3、k++k<n-1;跳到步骤1

【具体算法】

public static int[] selectSort(int[] array){
		for(int i = 0; i < array.length - 1; i++)
			for(int j = i + 1; j < array.length; j++){
				if(array[i] > array[j])
					array[i] = array[j] + (array[j] = array[i]) * 0;
			}
		return array;

【分析】

I、输入规模为数组的大小n

II、基本操作为“比较”;

III、“比较”的次数仅仅依赖于数组的规模,所以不区分最优、最差效率;

IV、基本操作执行次数:

VT(n) = O(n^2)


冒泡排序:(假定非降序,问题规模为n

【步骤】

1、(初始int k = 0),作第k次冒泡;

2、一次冒泡中,每两个相邻的数作比较,若序号大的数比序号小的数小,则交换位置,截止到下标为n-2-k的数;

3k++k<n-1;跳到步骤1

【具体算法】

<pre name="code" class="java">public static int[] bubbleSort(int[] array){
		for(int i = 0;i <= array.length - 2; i++)
			for(int j = 0;j <= array.length - 2 - i; j++)
				if(array[j] > array[j + 1])
					array[j] = array[j + 1] + (array[j + 1] = array[j]) * 0 ;
		return array;
	}


 
   

【分析】

I、输入规模为数组的大小n

II、基本操作为“比较”;

III、“比较”的次数仅仅依赖于数组的规模,所以不区分最优、最差效率;

IV、基本操作执行次数:

VT(n) = O(n^2)

插入排序

【步骤】

1、(初始int k = 1),作第k趟插入;

2、一次插入排序中,待插入的数依次向下标小的方向扫描,找到合适的位置后,将该位置起的数依次向下标增大方向挪动一个位置,然后将待插入的数插入到合适的位置;

3k++k<n;跳到步骤1

【具体算法】

public static int[] insertSort(int[] array){
		int insertNum = 0;
		for(int i = 1; i < array.length; i++){
			insertNum = array[i];
			int j = i - 1;
			while(j >= 0 && array[j] > insertNum){
				array[j + 1] = array[j];
				j--;
			}
			array[j + 1] = insertNum;		
		}
		return array;
	}

【分析】

I、输入规模为数组的大小n

II、基本操作为“比较” array[j] > insertNum;

III、“比较”的次数不仅依赖于数组的规模,还依赖于特定的输入;

IV、最坏效率(与选择排序相等):

最优效率:

平均效率:约等于 (可看出,插入算法还是优于 选择排序 和 冒泡排序 的)


蛮力字符串匹配

public static int bruteForceStringMatch(String sourceString, String pattern){
		for(int i = 0,j = 0; i < sourceString.length() - pattern.length(); i++){
			j = 0;		
			while(j < pattern.length() && sourceString.charAt(i + j) == (pattern.charAt(j)))
				j++;
			if(j == pattern.length())
				return i;
		}
		return -1;
	}

【分析】

基本操作:比较;

最差效率:O(mn);

平均效率:Θ(n)


顺序查找

【具体算法】
public static <T> int sequenceSearch(List<T> list, T target){
		for(T t : list)
			if(t.equals(target))
				return list.indexOf(t);
		return -1;
	}


凸包问题的蛮力解法

【思路】

I、求出点集的每一线段ax + by = c中的abc值;

II、将其他n-2个点代入ax + by - c中,检查符号是否相同,此处一共有几种情况回发生:

   1)代入后为0,且点在线段之外,则舍弃此线段

   2)代入后为0,且点在线段上,若其他点符号相同,则保留线段,否则舍弃

   3)代入后,有符号不相同的情况,舍弃线段

   4)代入后,符号都相同,则保留线段

【具体算法】

/*array参数代表待求凸包的点集,用二维数组表示,第一维表示的是X轴的数值,第二维表示的是Y轴的数值 */
	public static int[][] bruteForce(int[][] array){
		int[][] arrayResult = {}; // 存放凸包极点和线段的数组,数组只有两列,每行代表一个线段,eg:a[0][0]=0,a[0][1]=1 表示的是端点为结点 0 和结点 1的线段
		int[] value = new int[array.length]; //存放n-2个结点代入某一线段公式后的值
		int valueKey = 0; //记录value数组的下标移动
		
	 // 初始化arrayResult数组,由于arrayResult数组存放的是凸包线段的端点的编号,所以arrayResult的行数就是线段数
		if(array != null)
			arrayResult = new int[array.length * (array.length - 1) / 2][2]; //凸包最多的线段数就是点集(n个结点)所能组成的最大线段数数 (n - 1) * n / 2
		for(int i = 0; i < arrayResult.length;i++)
			for(int j = 0; j < array[0].length; j++)
				arrayResult[i][j] = -1;

	//记录除线段外的n-2个点代入线段公式后的符号是否相同,true为相同
		boolean hasSameSign = true;
		double a = 0, b = 0, c = 0;
		int resultArrayKey = 0, k = 0;
	
	//最外的两层循环是蛮力算出点集中的所有可能线段,i和j代表点的编号
		for(int i = 0; i < array.length - 1; i++)
			for(int j = i + 1; j < array.length; j++){
				a = array[j][1] - array[i][1];
				b = array[i][0] - array[j][0];
				c = array[i][0] * array[j][1] - array[i][1] * array[j][0];
				hasSameSign = true;
				
				//算出线段的X轴和Y轴区间
				int maxX = CompareNumber.max(array[i][0], array[j][0]),
					minX = CompareNumber.min(array[i][0], array[j][0]),
					maxY = CompareNumber.max(array[i][1], array[j][1]),
					minY = CompareNumber.min(array[i][1], array[j][1]);
				
				valueKey = 0;
				//历遍其他n-2个点,将其代入线段公式
				for(k = 0;k < array.length;k++){
					if(k == i || k == j)
						continue;
					value[valueKey] = (int)(array[k][0] * a + array[k][1] * b - c); //代入代入线段公式后的值
					if(value[valueKey] == 0 && ((array[k][0] > maxX) || (array[k][0] < minX) || 
							(array[k][1] > maxY) ||	(array[k][1] < minY))){ //特殊情况一:有点刚好在线段所表示的直线上,且该点在线段之外,则此线段不是凸包的边界
						hasSameSign = false;
						break;
					}else if((value[valueKey] != 0)){
						if((valueKey != 0) && CompareNumber.checkSign(value[valueKey], value[valueKey - 1]) < 0){ //当n-2个点里有其中两个点代入线段公式后,符号不相同,说明此线段不是凸包边界
							hasSameSign = false;
							break;
						}
						else
							valueKey++;
					}				
				}
					
				if(hasSameSign){
					arrayResult[resultArrayKey][0] = i;
					arrayResult[resultArrayKey++][1] = j;
				}
			}	
		return arrayResult;		
	}

【分析】

输入规模:点集的点个数n

基本操作:点代入线段公式求值

时间效率:对于不同点的每一个n(n-1)/2来说,要对其他(n-2)个点求出ax+by-c的符号,所以 T(n) = O()
















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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值