JAVA高级数据结构学习笔记

枚举Enum

bitset

BitSet中数组大小会随需要增加。

vector

Vector 主要用在事先不知道数组的大小,或者只是需要一个可以改变大小的数组的情况。
JAVA高级数据结构学习笔记_第1张图片

list和map

类型通配符上限
在这里插入图片描述
类型通配符下限
在这里插入图片描述

//对于一个二维数组,根据第一列进行排序
Arrays.sort(narr, (o1, o2) -> o1[0] - o2[0]);

Comparator的用法

参考https://blog.csdn.net/u012250875/article/details/55126531

GC机制:
参考https://segmentfault.com/a/1190000013365885
标记-清楚算法:
标记的时候是标记从root可达的对象
清楚的时候是清楚所有未标记对象
复制算法:
内存一划为二,从一块吧存活的复制到另一块
标记-整理算法:
标记完之后将被标记的移动使得按序排列,将末端之后的内存全部回收;
分代gc:
年轻代,老年代,持久代
年轻代中执行gc时候是把对象从Eden和From移去To
带to满时或者gc超过一定次数还存活的对象,放入老年代
老年代内存大于年轻代,存活率高,使用标记-清楚或整理算法,成为full gc;
持久代主要用来存储类常量和字符常量,也会major gc;

边学边加,没什么顺序

最近做了不少算法题,发现利用这些高级数据类型,有时候变成特别方便,比如

第一道:一个数数组里只有两个数字出现一次,其他的都重复,让你找出来

简简单单的向导哈希一下,几个数,找位数是1 的,然后就用到了map

我用的是这个
Map<Integer, Integer> map = new HashMap<Integer, Integer>();

简单遍历一下

for (int i = 0; i < array.length; i++) {
        	Integer key = array[i];
        	Integer val = map.get(key);
        	if (val == null) {
        		map.put(key, 1);
			} else {
				map.put(key, val+1);
			}
		}

值是出现次数,找为一的就行,是不是很简单。

list肯定也是很常用了,一般就三种list的选择

(元素可重复):要安全?
  是:Vector
  否:ArrayList或者LinkedList
  查询多?:ArrayList
  增删多?:LinkedList
  知道要用List,但是不知道是哪个List,就用ArrayList。

第二题:排序两个列表,可能会有重复元素,本来不是有序的

解决方法:既然排序么,想想set吧,因为set会去重,不太行,就还是arraylist,可是它不会排序,怎么办?简单,先放进去,再调用排序方法

Collections.sort(arrayList);

这样就是有序的了,然后创建一波新链表输出就好了,当时这是机试投机取巧的方法,面试可不行。

队列,

算法中也是很常见了,那么java中一般都是阻塞队列,再调用的时候也会有些差别,不过对于我来说,阻塞不阻塞都能用,为什么会阻塞呢?因为超出队列的长度了

第三题:给一个输入,字符流,然后问你第一个出现的不重复的字符是什么》比如输入g,就是g,输入go,还是g,输入gog就是o.

一看就是先进先出,哈希记次数,队列记先后

static Queue<Character> queue = new LinkedList<>();
	static int[] hasharr = new int[256];

在这里的队列有个四五种吧,比如那个priorQueue,可是我发现那玩意说是队列,,,结果存储的时候根本就不是先进先出,所以选择用LinkedList。
最终代码

while(!queue.isEmpty()) {
			char flag = queue.peek();
//			System.out.println(flag);
			if (hasharr[(int) flag] == 1) {
				return flag;
			}
			queue.poll();
		}

四:set,

排序?
  是:TreeSet或LinkedHashSet
  否:HashSet
  知道要用Set,但是不知道是哪个Set,就用HashSet。

我习惯用TreeSet,涉及到各种去重时候就考虑用这个,编程超快

TreeSet<Integer> t = new TreeSet();

在这里插入图片描述
比如这个,我把重复的都进到treeset,然后每次遍历链表,只要是包含的时候,跳过去就好了。

五、栈更简单,压入弹出,先进后出,题目:给一个入栈序列和一个出栈序列,问这个出栈序列是不是入栈序列的弹出序列

Stack<Integer> stack = new Stack<>();
操作就pop和push

代码如下:
先把入栈序列尝试压进去,如果栈顶元素等于出栈序列,就pop,否则就push,因为出栈序列最前边的一定是栈顶的,最后如果出栈序列遍历完了,入栈序列也弹空说明是可以的,否则不可以。

public boolean IsPopOrder(int [] pushA,int [] popA) {
	    if (pushA == null || pushA.length==0) {	return true;	}
	    Stack<Integer> stack = new Stack<>();
	    int i=0, j=0;
	    while (i < pushA.length) {
			if (pushA[i] != popA[j]) {
				stack.push(pushA[i]);
				i++;
			}
			else {
				++i;
				++j;
				while (!stack.isEmpty() && stack.peek() == popA[j]) {
					stack.pop();
					j++;
				}
			}
		}
		return stack.isEmpty();
    }

StringBuffer

这个也比较重要,之前没注意一直用string,
这玩意处理字符串666的。

StringBuffer sBuffer = new StringBuffer("菜鸟教程官网:");
    sBuffer.append("www");

还有反转,插入删除,char charAt(int index)
返回此序列中指定索引处的 char 值等方法,最后tostring一下,就能得到你需要的string类型,很方便。

你可能感兴趣的:(笔记)