1、冒泡排序

for(int i=0;i<n;i++){
   for(int j=0;j<n-1-i;j++){
        if(temp[j]>temp[j+1]){
           int t=temp[j];
           temp[j]=temp[j+1];
           temp[j+1]=t;
        }
   }
}

2、快速排序

public void quicksort(int[] array,int left,int right){
		if(left<right){
			int key = array[left];
			int low = left;
			int high = right;

			while(low<high){
				while(low<high && array[high]>=key){
					high--;
				}
				array[low] = array[high];
				while(low<high && array[low]<=key){
					low++;
				}
				array[high] = array[low];
			}
			array[low] = key;
	        quicksort(array,left,low-1);
	        quicksort(array,low+1,right);
		}
	}

  

3、一致性hash

一致性hash算法可以解决容错性和扩展性的问题。

系统中增加更多的虚拟节点,可以更好的解负载均衡问题。

public class Shard<S> {     // S类封装了机器节点的信息 ,如name、password、ip、port等   

    private TreeMap<Long, S> circle;  // 将整个hash值空间组成一个虚拟的环
    private List<S> shards;           // 真实机器节点
    private final int NODE_NUM = 100; // 每个机器节点关联的虚拟节点个数
    private final HashFunction hashFunction;  // 选择一个碰撞率低的hash()函数

    public Shard(List<S> shards,HashFunction hashFunction) {
        super();
        this.shards = shards;
        this.hashFunction = hashFunction;
        init();
    }  

    private void init() {  // 初始化一致性hash环
    	circle = new TreeMap<Long, S>();
        for (int i = 0; i<shards.size(); ++i) { // 每个真实机器节点都需要关联虚拟节点
            final S shardInfo = shards.get(i);
            add(shardInfo);
        }
    }  

    public void add(S node) {
		for (int i = 0; i < NODE_NUM; i++) {
			// 虚拟节点用一些特定的hash值来替代,这样形成了hash值到真实节点的映射
			circle.put(hashFunction.hash(node.toString() + i), node);
		}
	}

	public void remove(S node) {
		for (int i = 0; i < NODE_NUM; i++) {
			// 移除真实节点下对应的所有虚拟节点(特定的一些hash值)
			circle.remove(hashFunction.hash(node.toString() + i));
		}
	}

    public S getShardInfo(String key) {
//        SortedMap<Long, S> tail = circle.tailMap(hash(key)); // 沿环的顺时针找到一个虚拟节点
//        if (tail.size() == 0) {
//            return circle.get(circle.firstKey());
//        }
//        return tail.get(tail.firstKey()); // 返回该虚拟节点对应的真实机器节点的信息
    	if (circle.isEmpty()) {
			return null;
		}
		Long hash = hashFunction.hash(key);

		// 如果当前hash值没有定位到虚拟节点
		if (!circle.containsKey(hash)) {
			SortedMap<Long, S> tailMap = circle.tailMap(hash);
			hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();
		}

		return circle.get(hash);
    }
}

  

class Machine {
	String ip;
	String name;

	public Machine(String ip, String name) {
		this.ip = ip;
		this.name = name;
	}

	public String getIp() {
		return ip;
	}

	public void setIp(String ip) {
		this.ip = ip;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

public class Test {
	public static void main(String[] args) {
		Machine a = new Machine("192.168.0.1", "a");
		Machine b = new Machine("192.168.0.2", "b");
		Machine c = new Machine("192.168.0.3", "c");

		List<Machine> list = Arrays.asList(a, b, c);
		Map<String, Integer> map = new HashMap<String, Integer>();

		Shard<Machine> mcs = new Shard<Machine>(list, new HashFunction());

		// 存储0到2000个数,看存储在各个机器上的数的数量是否大致均匀
		for (int i = 0; i < 2000; i++) {
			String key = i + "";
			Machine m = mcs.getShardInfo(key);
			if (map.get(m.getIp()) == null) {
				map.put(m.getIp(), 0);
			} else {
				map.put(m.getIp(), (int) map.get(m.getIp()) + 1);
			}
		}

		Iterator<Entry<String, Integer>> iterator = map.entrySet().iterator();
		while (iterator.hasNext()) {
			Entry<String, Integer> entry = iterator.next();
			System.out.println(entry.getKey() + "/" + entry.getValue());
		}

	}
}

  

某次运行后的结果如下:

192.168.0.2/599
192.168.0.1/698
192.168.0.3/700

4、LRU最近最少使用算法

要效率的话使用hash搜索,要实现最近最少的话就用双向链表

public class LRUCache {  

    private int cacheSize;
    private HashMap<Object, Entry> nodes; // 缓存容器 ,为了提高查询速度需要这个结构
    private int currentSize;
    private Entry first; // 链表头
    private Entry last;  // 链表尾  

    static class Entry {
        Entry prev;
        Entry next;
        Object key;
        Object value;
    }  

    public LRUCache(int i) {
        currentSize = 0;
        cacheSize = i;
        nodes = new HashMap<Object, Entry>(i);
    }  

    /**
     * 获取缓存中对象,并把它放在最前面
     */
    public Entry get(Object key) {
        Entry node = nodes.get(key);
        if (node != null) {
            moveToHead(node);
            return node;
        } else {
            return null;
        }
    }  

    /**
     * 添加 entry到hashtable, 并把entry
     */
    public void put(Object key, Object value) {
        //先查看hashtable是否存在该entry, 如果存在,则只更新其value
        Entry node = nodes.get(key);  

        if (node == null) {
            //缓存容器是否已经超过大小.
            if (currentSize >= cacheSize) {
                nodes.remove(last.key);
                removeLast();
            } else {
                currentSize++;
            }
            node = new Entry();
        }
        node.value = value;
        //将最新使用的节点放到链表头,表示最新使用的.
        moveToHead(node);
        nodes.put(key, node);
    }  

    /**
     * 将entry删除, 注意:删除操作只有在cache满了才会被执行
     */
    public void remove(Object key) {
        Entry node = nodes.get(key);
        //在链表中删除
        if (node != null) {
            if (node.prev != null) {
                node.prev.next = node.next;
            }
            if (node.next != null) {
                node.next.prev = node.prev;
            }
            if (last == node)
                last = node.prev;
            if (first == node)
                first = node.next;
        }
        //在hashtable中删除
        nodes.remove(key);
    }  

    /**
     * 删除链表尾部节点,即使用最后 使用的entry
     */
    private void removeLast() {
        //链表尾不为空,则将链表尾指向null. 删除连表尾(删除最少使用的缓存对象)
        if (last != null) {
            if (last.prev != null){
            	last.prev.next = null;
            }
            else{
            	first = null;
            }
            last = last.prev;
        }
    }  

    /**
     * 移动到链表头,表示这个节点是最新使用过的
     */
    private void moveToHead(Entry node) {
        if (node == first)
            return;
        if (node.prev != null)
            node.prev.next = node.next;
        if (node.next != null)
            node.next.prev = node.prev;
        if (last == node)
            last = node.prev;
        if (first != null) {
            node.next = first;
            first.prev = node;
        }
        first = node;
        node.prev = null;
        if (last == null){
        	last = first;
        }  

    }
    /*
     * 清空缓存
     */
    public void clear() {
        first = null;
        last = null;
        currentSize = 0;
    }  

}

  

Java面试13|算法的更多相关文章

  1. Java面试常见算法题

    1.实现字符串反转 提供七种方案实现字符串反转 import java.util.Stack; public class StringReverse { public static String re ...

  2. 【java面试】算法篇之堆排序

    一.堆的概念 堆是一棵顺序存储的完全二叉树.完全二叉树中所有非终端节点的值均不大于(或不小于)其左.右孩子节点的值. 其中每个节点的值小于等于其左.右孩子的值,这样的堆称为小根堆: 其中每个节点的值大 ...

  3. 【java面试】算法篇

    1.冒泡排序 /** * 冒泡排序 * 比较相邻的元素.如果第一个比第二个大,就交换他们两个. * 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. ...

  4. Java面试系列

    如果你的面试简历是如下这样写的,请务必准备回答下面的所有问题. 面试职位:Java高级工程师 专业技能: (1)牢固掌握Java基础知识,如集合.并发.I/O等,并对Java源码有一定的研究. (2) ...

  5. 分享13道上海尚学堂拿回来的Java面试真题,这些都是Java核心常见问题,想拿OFFER必看!

    上海尚学堂Java培训学员参加面试带回来的真题,分享出来与大家,希望大家能认真地看看做一遍.后面有详细题解答案,对照下,看看自己做得怎么样,把这些面试遇到的真题全部掌握,做好面试笔试前的准备. 一.1 ...

  6. 编程之法:面试和算法心得(字符串包含java实现)

    内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 给定两个分别由字母组成的字符串A和字符串B,字符串B的长度比字符串A短.请问,如何最快地判断字符串B中所有字母是否都 ...

  7. [转载]java面试中经常会被问到的一些算法的问题

    Java面试中经常会被问到的一些算法的问题,而大部分算法的理论及思想,我们曾经都能倒背如流,并且也能用开发语言来实现过, 可是很多由于可能在项目开发中应用的比较少,久而久之就很容易被忘记了,在此我分享 ...

  8. 编程之法:面试和算法心得(旋转字符串java实现)

    内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,如把字符串“abcdef”前面的2个字符'a'和'b ...

  9. java面试一日一题:java中垃圾回收算法有哪些

    问题:请讲下在java中有哪些垃圾回收算法 分析:该问题主要考察对java中垃圾回收的算法以及使用场景 回答要点: 主要从以下几点去考虑, 1.GC回收算法有哪些 2.每种算法的使用场景 3.基于垃圾 ...

随机推荐

  1. 用fluent模拟内循环床气化燃烧(调试过程记录)

    模拟对象为文献Combined gasification of coal and biomass in internal circulating fluidized bed[1]中的内循环气化炉.[1]h ...

  2. angular指令中,require和transclude同时设置为true时的作用

    最近在学习angularJS指令的时候,对指令对象中require属性和transclude属性同时设置为true比较疑惑,于是自己动手测试一下具体差异 index.html: <simple& ...

  3. 解决xtrabackup command not found no mysqld group 问题

    现象:手动执行xtrabackup没问题,环境变量检查过也没问题.放到执行计划中 会报错: sh: xtrabackup_56: command not found innobackupex: Err ...

  4. RabbitMQ小白菜学习之在window下的安装配置

    RabbitMQ安装 首先需要下载RabbitMQ的平台环境Erlang OTP平台和RabbitMQ Server(windows版): OTP 19.1 Windows 64-bit Binary ...

  5. TV端:通过遥控器的点击实现图片的上下左右抖动的效果

    做TV端有一段时间了,我看到别的TV上有一个通过遥控器的触摸板来控制一张图片的相应方向的抖动,感觉听新奇的,就试着做了一个分享一下: 转载注明出处:http://www.cnblogs.com/hyy ...

  6. javascript学习-目录

    Javascript学习 第1章 Javascript简介 1.1 Javascript简史 1.2 Javascript实现 1.3 Javascript版本 第2章 Javascript入门 2. ...

  7. (@WhiteTaken)设计模式学习——原型模式

    有这样一个需求,两个对象,只是名称以及其他几个属性不一样,而其他的大部分的属性都是相同的. 这时候我们可以用到原型模式,也就是克隆模式. 原型模式:原型模式是一个对象创建型模式,通过克隆原对象,可以使 ...

  8. VS error 全集(error C2664: 'CWnd::MessageBoxW' : cannot convert parameter 1 from 'char *' to 'LPCTSTR'的解决方法)

    我用的是VS2005,在编译MFC时遇到了如下错误: error C2664: 'CWnd::MessageBoxW' : cannot convert parameter 1 from 'char ...

  9. HTML中三种定位relative,absolute,fixed后,盒子的百分比宽度及位置易错点

    1 . 相对定位relative:顾名思义,相对定位是相对于自己的位置来进行偏移,如下图: 以盒子中心为基准,为每条边的正方向,例: 向右移动20px : 代码为left:20px;或者right:- ...

  10. Mock以及Mockito的使用

    mockito http://www.vogella.com/tutorials/Mockito/article.html 原文地址: http://www.open-open.com/lib/vie ...