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. NodeMCU之旅(一):构建、刷入固件,上传代码

    扬帆起航 本系列文章将试图实现,使用Web页面远程点亮led.具体包括: 在NodeMCU上搭建HTTP服务器,使其可以通过Web页面配置要接入的网络. 在配置页面可以显示附近中英网络名与信号强度. ...

  2. easelJS - Cache_vday

    easelJS - Cache_vday $(function() { init(); }); // Cache_vday var canvas; var stage; var container; ...

  3. C语言中strcpy,strcmp,strlen,strcat函数原型

    //strcat(dest,src)把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0' char *strcat(char * strDest, const char ...

  4. RestTemplate.getForObject返回List的时候处理方式

    ...... User[] users = restTemplate.getForObject(url, User[].class); ......

  5. loadrunner:关联操作

    文章以实例讲解loadrunner中的关联操作,内容包括:自动关联.手动关联和关联规则的设置. 1.1.1     准备工作 在web tours项目默认设置里,登录操作是没有生成sessionID的 ...

  6. HTML5中将video设置为背景的方法

    主要用到了video标签,css样式,原理是先将video标签利用position:fixed;使video标签脱离文档流,在将他的z-index设置为最低的,比如-9999.再插入的内容自然就覆盖在 ...

  7. KB奇遇记(2):缘起

    最早听到这家公司的名字,大概还是在好几年前. 正是2012年,之前的在一起灿坤待过的同事LY在这家公司当高层,正好公司规模大了,要上ERP项目.苦于公司没有这方面的人才,而内部IT又太差劲支撑不起来. ...

  8. Java多线程基础——Lock类

    之前已经说道,JVM提供了synchronized关键字来实现对变量的同步访问以及用wait和notify来实现线程间通信.在jdk1.5以后,JAVA提供了Lock类来实现和synchronized ...

  9. 一个web应用的诞生--美化一下

    经过上一章的内容,其实就页面层来说已结可以很轻松的实现功能了,但是很明显美观上还有很大的欠缺,现在有一些很好的前端css框架,如AmazeUI,腾讯的WeUI等等,这里推荐一个和flask集成很好的b ...

  10. ML2 配置 OVS VxLAN - 每天5分钟玩转 OpenStack(146)

    今天我们开始学习 OVS 如何实现 Neutron VxLAN,关于 VxLAN 的概念以及 Linux Bridge 实现,大家可以参考前面相关章节. Open vSwitch 支持 VXLAN 和 ...