1.二分查找(非递归)
- 二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
- 代码实现
package com.qin.Algorithm;
public class BinarySearchNoRecursion {
public static void main(String[] args) {
int arr[] = {1,3,8,10,11,67,100};
int index = binarySearch(arr,100);
if (index==-1){
System.out.println("没有找到");
}else {
System.out.println("被查找的数下标为:"+index);
}
}
public static int binarySearch(int[] arr,int target){
int left = 0;
int right = arr.length-1;
while (left<=right){
int mid = (left+right)/2;
if (arr[mid] == target){
return mid;
}else if(arr[mid]>target){
right = mid - 1 ;
}else {
left = mid + 1;
}
}
return -1;
}
}
2.分治算法
- 分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,简单问题可用二分法完成
package com.qin.Algorithm;
public class DivideAndConquer {
public static void main(String[] args) {
hanoiTower(2,'A','B','C');
}
public static void hanoiTower(int num,char a,char b,char c){
if (num==1){
System.out.println("第1个盘从"+a+"->"+c);
}else {
hanoiTower(num - 1,a,c,b);
System.out.println("第"+num+"个盘从"+a+"->"+c);
hanoiTower(num-1,b,a,c);
}
}
}
3.动态规划算法
- 动态规划(Dynamic Programming,DP)是运筹学的一个分支,是求解决策过程最优化的过程。20世纪50年代初,美国数学家贝尔曼(R.Bellman)等人在研究多阶段决策过程的优化问题时,提出了著名的最优化原理,从而创立了动态规划。动态规划的应用极其广泛,包括工程技术、经济、工业生产、军事以及自动化控制等领域,并在背包问题、生产经营问题、资金管理问题、资源分配问题、最短路径问题和复杂系统可靠性问题等中取得了显著的效果
package com.qin.Algorithm;
public class KnapsackProblem {
public static void main(String[] args) {
int[] w = {1,4,3} ;
int[] val = {1500,3000,2000};
int m = 4 ;
int n = val.length;
int[][] path = new int[n+1][m+1];
int[][] v = new int[n+1][m+1];
for (int i = 0; i < v.length; i++) {
v[i][0] = 0 ;
}
for (int i = 0; i < v[0].length; i++) {
v[0][i] = 0;
}
for (int i = 1; i < v.length; i++) {
for (int j = 1; j < v[0].length; j++) {
if (w[i-1]>j) {
v[i][j] = v[i-1][j] ;
}else {
if (v[i-1][j]<val[i-1]+v[i-1][j-w[i-1]]){
v[i][j] = val[i-1]+v[i-1][j-w[i-1]];
path[i][j] = 1;
}else {
v[i][j] = v[i-1][j];
}
}
}
}
System.out.println("建表情况");
for (int[] a : v){
for (int i = 0; i < a.length; i++) {
System.out.printf("%d\t",a[i]);
}
System.out.println();
}
System.out.println("============");
for (int[] i:path){
for (int j = 0; j < i.length; j++) {
System.out.printf("%d\t",i[j]);
}
System.out.println();
}
System.out.println("在一定重量下的最大价值存放方案");
int i= path.length-1;
int j = path[0].length-1;
while (i>0){
if (path[i][j]==1){
System.out.printf("第%d个商品放入到背包\n",i);
j-=w[i-1];
}
i--;
}
}
}
4.KMP算法
- KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n)
- 代码实现
package com.qin.Algorithm;
public class ViolenceMatch {
public static void main(String[] args) {
String str1 = "秦小东是张伟爸爸的爷爷";
String str2 = "张伟爸爸的";
int i = violenceMatch(str1, str2);
if (i == -1){
System.out.println("信息不匹配");
}else {
System.out.println("开始下标为"+i);
}
}
public static int violenceMatch(String str1,String str2){
char[] s1 = str1.toCharArray();
char[] s2 = str2.toCharArray();
int s1len = s1.length;
int s2len = s2.length;
int i = 0;
int j = 0;
while (i < s1len && j < s2len){
if (s1[i] == s2[j]){
i++;
j++;
}else {
i = i - (j - 1);
j=0;
}
}
if (j==s2len){
return i - j;
}else {
return -1;
}
}
}
package com.qin.Algorithm;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import java.util.Arrays;
public class KMP {
public static void main(String[] args) {
String str1 = "BBC ABCDAB ABCDABCDABDE";
String str2 = "ABCDABD";
int[] next = kmpNext(str2);
System.out.println("next="+ Arrays.toString(next));
System.out.println("====================");
int i = kmpSearch(str1, str2, next);
if (i==-1){
System.out.println("没有找到");
}else {
System.out.println("开始下标为"+i);
}
}
public static int[] kmpNext(String dest){
int[] next = new int[dest.length()];
next[0] = 0;
for (int i = 1,j = 0; i < dest.length(); i++) {
while (j>0 && dest.charAt(i)!=dest.charAt(j)){
j = next[j - 1];
}
if (dest.charAt(i)==dest.charAt(j)){
j++;
}
next[i] = j;
}
return next;
}
public static int kmpSearch(String s1,String s2,int[] next){
for (int i = 0,j = 0; i < s1.length(); i++) {
while (j>0 && s1.charAt(i)!=s2.charAt(j)){
j = next[j-1];
}
if (s1.charAt(i)==s2.charAt(j)){
j++;
}
if(j==s2.length()){
return i-j+1;
}
}
return -1;
}
}
- 结果
5.贪心算法
- 贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解
- 贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择。也就是说,不从整体最优上加以考虑,做出的只是在某种意义上的局部最优解
package com.qin.Algorithm;
import javax.print.DocFlavor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
public class GreedyAlgorithm {
public static void main(String[] args) {
HashMap<String, HashSet<String>> broadcasts= new HashMap<>();
HashSet<String> hashSet1 = new HashSet<>();
hashSet1.add("北京");
hashSet1.add("上海");
hashSet1.add("天津");
HashSet<String> hashSet2 = new HashSet<>();
hashSet2.add("广州");
hashSet2.add("北京");
hashSet2.add("深圳");
HashSet<String> hashSet3 = new HashSet<>();
hashSet3.add("成都");
hashSet3.add("上海");
hashSet3.add("杭州");
HashSet<String> hashSet4 = new HashSet<>();
hashSet4.add("上海");
hashSet4.add("天津");
HashSet<String> hashSet5 = new HashSet<>();
hashSet5.add("杭州");
hashSet5.add("大连");
broadcasts.put("k1",hashSet1);
broadcasts.put("k2",hashSet2);
broadcasts.put("k3",hashSet3);
broadcasts.put("k4",hashSet4);
broadcasts.put("k5",hashSet5);
HashSet<String> allAreas = new HashSet<>();
allAreas.add("北京");
allAreas.add("上海");
allAreas.add("天津");
allAreas.add("广州");
allAreas.add("深圳");
allAreas.add("成都");
allAreas.add("杭州");
allAreas.add("大连");
ArrayList<String> selects = new ArrayList<>();
HashSet<String> tempSet = new HashSet<>();
String maxKey = null;
while (allAreas.size()!=0){
maxKey = null;
for (String key:broadcasts.keySet()){
tempSet.clear();
HashSet<String> areas = broadcasts.get(key);
tempSet.addAll(areas);
tempSet.retainAll(allAreas);
if (tempSet.size()>0&&
(maxKey==null||tempSet.size()>broadcasts.get(maxKey).size())){
maxKey = key;
}
}
if (maxKey!=null){
selects.add(maxKey);
allAreas.removeAll(broadcasts.get(maxKey));
}
}
System.out.println("得到的选择结果"+selects);
}
}
6.普利姆算法
package com.qin.Algorithm;
import java.util.Arrays;
public class Prim {
public static void main(String[] args) {
char[] data = new char[]{'A','B','C','D','E','F','G'};
int num = data.length;
int[][] weight = new int[][]{
{10000,5,7,10000,10000,10000,2} ,
{5,10000,10000,9,10000,10000,3} ,
{7,10000,10000,10000,8,10000,10000} ,
{10000,9,10000,10000,10000,4,10000} ,
{10000,10000,8,10000,10000,5,4} ,
{10000,10000,10000,4,5,10000,6} ,
{2,3,10000,10000,4,6,10000}
};
MGraph graph = new MGraph(num);
MinTree minTree = new MinTree();
minTree.createGraph(graph,num,data,weight);
minTree.showGraph(graph);
minTree.prim(graph,1);
}
}
class MGraph{
int num;
char[] data;
int[][] weight;
public MGraph(int num) {
this.num = num;
data = new char[num];
weight = new int[num][num];
}
}
class MinTree{
public void createGraph(MGraph graph,int num,char data[],int[][] weight){
int i,j;
for (i=0;i<num;i++){
graph.data[i] = data[i];
for (j=0;j<num;j++){
graph.weight[i][j] = weight[i][j];
}
}
}
public void showGraph(MGraph graph){
for (int[] link:graph.weight) {
System.out.println(Arrays.toString(link));
}
}
public void prim(MGraph graph,int v){
int[] visited = new int[graph.num];
visited[v] = 1;
int h1 = -1;
int h2 = -1;
int minWeight = 10000;
for (int k = 1; k < graph.num; k++) {
for (int i = 0; i < graph.num; i++) {
for (int j = 0; j < graph.num; j++) {
if (visited[i]==1&&visited[j]==0&&graph.weight[i][j]<minWeight){
minWeight = graph.weight[i][j];
h1 = i;
h2 = j;
}
}
}
System.out.println("边<"+graph.data[h1]+","+graph.data[h2]+">权值:"+minWeight);
visited[h2] = 1;
minWeight = 10000;
}
}
}
7. 克鲁斯卡尔算法
package com.qin.Algorithm;
import java.util.Arrays;
public class KruskalCase {
private int edgeNum;
private char[] vertexs;
private int[][] matrix;
private static final int INF = Integer.MAX_VALUE;
public KruskalCase(char[] vertexs,int[][] matrix) {
int vlen = vertexs.length;
this.vertexs = new char[vlen];
for (int i = 0; i < vertexs.length ; i++) {
this.vertexs[i] = vertexs[i];
}
this.matrix = new int[vlen][vlen];
for (int i = 0; i< vlen;i++){
for (int j = 0; j < vlen ; j++) {
this.matrix[i][j] = matrix[i][j];
}
}
for (int i = 0; i < vlen; i++) {
for (int j = i+1; j < vlen ; j++) {
if (this.matrix[i][j]!=INF){
edgeNum++;
}
}
}
}
public void print(){
System.out.println("邻接矩阵为:\n");
for (int i = 0; i < vertexs.length; i++) {
for (int j = 0; j < vertexs.length; j++) {
System.out.printf("%10d\t",matrix[i][j]);
}
System.out.println();
}
}
private void sortEdges(EData[] edges){
for (int i = 0; i < edges.length-1; i++) {
for (int j = 0; j < edges.length-1-i; j++) {
if (edges[j].weight>edges[j+1].weight){
EData tmp = edges[j];
edges[j] = edges[j+1];
edges[j+1] = tmp;
}
}
}
}
private int getPosition(char ch){
for (int i = 0; i < vertexs.length; i++) {
if (vertexs[i] == ch){
return i;
}
}
return -1;
}
private EData[] getEdges(){
int index = 0;
EData[] edges= new EData[edgeNum];
for (int i = 0; i < vertexs.length ; i++) {
for (int j = i+1; j < vertexs.length; j++) {
if (matrix[i][j]!=INF){
edges[index++] = new EData(vertexs[i],vertexs[j],matrix[i][j]);
}
}
}
return edges;
}
private int getEnd(int[] ends,int i){
while (ends[i]!=0){
i = ends[i];
}
return i;
}
public void kruskal() {
int index = 0;
int[] ends = new int[edgeNum];
EData[] rets = new EData[edgeNum];
EData[] edges = getEdges();
System.out.println("图的边的集合=" + Arrays.toString(edges) + "共" + edges.length);
sortEdges(edges);
for (int i = 0; i < edgeNum; i++) {
int p1 = getPosition(edges[i].start);
int p2 = getPosition(edges[i].end);
int m = getEnd(ends,p1);
int n = getEnd(ends,p2);
if (m!=n){
ends[m] = n;
rets[index++] = edges[i];
}
}
for (int i = 0; i < index; i++) {
System.out.println(rets[i]);
}
}
public static void main(String[] args) {
char[] vertexs = {'A','B','C','D','E','F','G'};
int[][] matrix= {
{0,12,INF,INF,INF,16,14},
{12,0,10,INF,INF,7,INF},
{INF,10,0,3,5,6,INF},
{INF,INF,3,0,4,INF,INF},
{INF,INF,5,4,0,2,8},
{16,7,6,INF,2,0,9},
{14,INF,INF,INF,8,9,0}
};
KruskalCase kruskalCase = new KruskalCase(vertexs, matrix);
kruskalCase.print();
EData[] edges = kruskalCase.getEdges();
System.out.println("=====================");
System.out.println("未排序");
System.out.println(Arrays.toString(kruskalCase.getEdges()));
System.out.println("排序后");
kruskalCase.sortEdges(edges);
System.out.println(Arrays.toString(edges));
kruskalCase.kruskal();
}
}
class EData{
char start ;
char end;
int weight ;
public EData(char start, char end, int weight) {
this.start = start;
this.end = end;
this.weight = weight;
}
@Override
public String toString() {
return "EData{" +
"start=" + start +
", end=" + end +
", weight=" + weight +
'}';
}
}
8. 迪杰斯特拉算法
- 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。
package com.qin.Algorithm;
import com.sun.java.swing.plaf.windows.WindowsDesktopIconUI;
import java.util.Arrays;
public class DijkstraAlgorithm {
public static void main(String[] args) {
char[] vertex = {'A','B','C','D','F','E','G'};
int[][] matrix = new int[vertex.length][vertex.length];
final int N = 65535 ;
matrix[0] = new int[]{N,5,7,N,N,N,2};
matrix[1] = new int[]{5,N,N,9,N,N,3};
matrix[2] = new int[]{7,N,N,N,8,N,N};
matrix[3] = new int[]{N,9,N,N,N,4,N};
matrix[4] = new int[]{N,N,8,N,N,5,4};
matrix[5] = new int[]{N,N,N,4,5,N,6};
matrix[6] = new int[]{2,3,N,N,4,6,N};
Graph graph = new Graph(vertex, matrix);
System.out.println("打印邻接矩阵");
graph.showGraph();
System.out.println("============");
System.out.println("测试迪杰斯特拉算法");
graph.djs(6);
graph.showDijkstra();
}
}
class Graph{
private char[] vertex;
private int[][] matrix;
private VisitedVertex vv;
public Graph(char[] vertex, int[][] matrix) {
this.vertex = vertex;
this.matrix = matrix;
}
public void showGraph(){
for(int i = 0; i < matrix.length ; i++){
for (int j = 0; j < matrix[i].length ; j++) {
System.out.printf("%7d\t",matrix[i][j]);
}
System.out.println();
}
}
public void djs(int index){
vv = new VisitedVertex(vertex.length, index);
update(index);
for (int i = 1; i < vertex.length; i++) {
index = vv.updateArr();
update(index);
}
}
private void update(int index){
int len = 0;
for (int i = 0; i < matrix[index].length; i++) {
len = vv.getDis(index) + matrix[index][i];
if (!vv.in(i) && len < vv.getDis(i)){
vv.updatePre(i,index);
vv.updateDis(i,len);
}
}
}
public void showDijkstra(){
vv.show();
}
}
class VisitedVertex{
public int[] already_arr;
public int[] pre_visited;
public int[] dis;
public VisitedVertex(int length,int index) {
this.already_arr = new int[length];
this.pre_visited = new int[length];
this.dis = new int[length];
Arrays.fill(dis,65535);
this.already_arr[index] = 1;
this.dis[index] = 0;
}
public boolean in(int index){
return already_arr[index] == 1;
}
public void updateDis(int index,int len){
dis[index] = len;
}
public void updatePre(int pre,int index){
pre_visited[pre] = index;
}
public int getDis(int index){
return dis[index];
}
public int updateArr(){
int min = 65535,index = 0;
for (int i = 0; i < already_arr.length; i++) {
if (already_arr[i] == 0 && dis[i] < min){
min = dis[i];
index = i;
}
}
already_arr[index] = 1;
return index;
}
public void show(){
for (int i:already_arr ) {
System.out.print(i + " ");
}
System.out.println();
System.out.println("前驱节点");
for (int i:pre_visited ) {
System.out.print(i + " ");
}
System.out.println();
System.out.println("到出发顶点的最短距离");
for (int i:dis ) {
System.out.print(i + " ");
}
}
}
9. 弗洛伊德算法
- Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。
package com.qin.Algorithm;
import java.util.Arrays;
public class FloydAlgorithm {
public static void main(String[] args) {
char[] vertex = {'A','B','C','D','E','F','G'};
int[][] matrix = new int[vertex.length][vertex.length];
final int N = 65535;
matrix[0] = new int[]{0,5,7,N,N,N,2};
matrix[1] = new int[]{5,0,N,9,N,N,3};
matrix[2] = new int[]{7,N,0,N,8,N,N};
matrix[3] = new int[]{N,9,N,0,N,4,N};
matrix[4] = new int[]{N,N,8,N,0,5,4};
matrix[5] = new int[]{N,N,N,4,5,0,6};
matrix[6] = new int[]{2,3,N,N,4,6,0};
Graph1 graph = new Graph1(vertex.length, matrix, vertex);
graph.floyd();
graph.show();
}
}
class Graph1 {
private char[] vertex;
private int[][] dis;
private int[][] pre;
public Graph1(int length,int[][] matrix,char[] vertex) {
this.vertex = vertex;
this.dis = matrix;
this.pre = new int[length][length];
for (int i = 0; i < length; i++) {
Arrays.fill(pre[i],i);
}
}
public void show(){
char[] vertex = {'A','B','C','D','E','F','G'};
System.out.println("打印各个顶点到其他顶点的最短距离");
for (int k = 0; k < dis.length ; k++) {
for (int i = 0; i < dis.length; i++) {
System.out.printf(vertex[pre[k][i]]+" ");
}
System.out.println();
}
System.out.println("打印各个顶点的前驱节点");
for (int k = 0; k < dis.length; k++) {
for (int i = 0; i < dis.length ; i++) {
System.out.print("("+vertex[k]+"到"+vertex[i]+"的最短路径是"+dis[k][i]+")\t");
}
System.out.println();
}
}
public void floyd(){
int len = 0;
for (int k = 0; k < dis.length ; k++) {
for (int i = 0; i < dis.length ; i++) {
for (int j = 0; j < dis.length; j++) {
len = dis[i][k] + dis[k][j];
if (len<dis[i][j]){
dis[i][j] = len;
pre[i][j] = pre[k][j] ;
}
}
}
}
}
}
10.马踏棋盘,骑士周游世界算法
package com.qin.Algorithm;
import javax.print.DocFlavor;
import java.awt.*;
import java.util.ArrayList;
public class HorseChessBoard {
private static int X;
private static int Y;
private static boolean visited[];
private static boolean finished;
public static void main(String[] args) {
X= 8;
Y= 8;
int row = 1;
int column = 1;
int[][] chessBoard = new int[X][Y];
visited = new boolean[X*Y] ;
long start = System.currentTimeMillis();
traversalChessBoard(chessBoard,row-1,column-1,1);
long end = System.currentTimeMillis();
System.out.println("共耗时"+(end-start)+"毫秒");
for (int[] rows:chessBoard){
for (int step:rows){
System.out.print(step+"\t");
}
System.out.println();
}
}
public static ArrayList<Point> next(Point curPoint){
ArrayList<Point> ps = new ArrayList<>();
Point p1 = new Point();
if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y - 1) >= 0){
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x -1) >= 0 && (p1.y = curPoint.y - 2) >= 0){
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y - 2) >= 0){
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y - 1) >= 0){
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y + 1) < Y){
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y + 2) < Y){
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y + 2) < Y){
ps.add(new Point(p1));
}
if ((p1.x = curPoint.x -2 ) >= 0 && (p1.y = curPoint.y + 1) < Y){
ps.add(new Point(p1));
}
return ps;
}
public static void traversalChessBoard(int[][] chessBoard,int row, int column,int step){
chessBoard[row][column] = step;
visited[row*X+column] = true;
ArrayList<Point> ps = next(new Point(column, row));
while (!ps.isEmpty()){
Point p = ps.remove(0);
if (!visited[p.y*X+p.x]){
traversalChessBoard(chessBoard,p.y,p.x,step+1);
}
}
if (step < X*Y && !finished){
chessBoard[row][column] = 0;
visited[row*X+column] = false;
}else {
finished = true;
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)