Skip to content

Commit 4ce42eb

Browse files
committed
[Function add]
1Complete binary tree
1 parent 11b7882 commit 4ce42eb

File tree

5 files changed

+470
-0
lines changed

5 files changed

+470
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# 完全二叉树 Complete Binary Tree
2+
* ****就是通过完全二叉树实现的,可以参考排序部分的堆排序。
3+
>当一一棵二叉树的每个结点都大于等于它的两个子结点时,被称为**堆有序**
4+
5+
>完全二叉树是效率很高的数据结构,堆是一种完全二叉树或者近似完全二叉树,所以效率极高,像十分常用的排序算法、Dijkstra算法、Prim算法等都要用堆才能优化,几乎每次都要考到的二叉排序树的效率也要借助平衡性来提高,而平衡性基于完全二叉树。
6+
7+
## 判断完全二叉树
8+
>若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
9+
10+
![CompleteBinaryTree](https://i.imgur.com/YzCQuXP.jpg)
11+
* 对于第n行,最多有2^(n-1)个元素。
12+
13+
## 二叉堆的实现方式
14+
* 通过数组实现二叉堆
15+
```Java
16+
public class CompleteBinaryTree<K extends Comparable<K>> {
17+
private Object[] arr; //因为无法实现泛型数组,我们通过Object数组替代。第一个位置不存储元素
18+
private int N; //树中元素的个数。
19+
public CompleteBinaryTree(int N) {
20+
arr = new Object[N];
21+
}
22+
private void swap(int i, int j){ //交换两个元素的位置
23+
Object temp = arr[i];
24+
arr[i] = arr[j];
25+
arr[j] = temp;
26+
}
27+
@SuppressWarnings("unchecked")
28+
private boolean less(Integer i, Integer j){
29+
return ((K)arr[i]).compareTo(((K)arr[j])) < 0;
30+
}
31+
//上浮方法
32+
private void swin(int k){
33+
//当前节点不是第一个元素并且大于它的父结点,则进行位置的交换。
34+
while(k > 1 && less(k/2, k)){
35+
swap(k/2, k);
36+
k /= 2;
37+
}
38+
}
39+
public Integer size(){
40+
return N;
41+
}
42+
@SuppressWarnings("unchecked")
43+
public K get(int i){
44+
return (K)arr[i];
45+
}
46+
private void sink(int i){
47+
while(i * 2 <= N){
48+
int j = i * 2;
49+
if(j + 1 < N && less(j, j+1)) j++; //取两个子结点中更大的一个。
50+
swap(i, j);
51+
i = j; //在当前子树中继续进行下沉
52+
}
53+
}
54+
}
55+
```
56+
57+
## 完全二叉树的增删改查
58+
*
59+
```Java
60+
public void insert(K k){
61+
arr[++N] = k;
62+
swin(N);
63+
}
64+
```
65+
66+
*
67+
```Java
68+
public K delMax(){
69+
K max = (K)arr[1];
70+
swap(1, N + 1);
71+
arr[N + 1] = null;
72+
sink(1);
73+
N--;
74+
return max;
75+
}
76+
```

DataStructrue/QueueConclusion.md

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
# Queue Conclusion
2+
3+
### Queue interface
4+
> `boolean add(E e);` Add and offer are used to add element into the queue.
5+
>
6+
> `boolean offer(E e);`
7+
>
8+
> `E remove();` Retrieve and remove the head of the queue.
9+
>
10+
> `E poll();`
11+
>
12+
> `E element();` Retrieves, but does not remove, the head of this queue.
13+
>
14+
> `E peek();`
15+
16+
### Blocking and non-blocking
17+
* Concurrent queue有两种实现方法,阻塞和非阻塞。
18+
* 阻塞队列是通过锁实现。
19+
* 非阻塞队列通过AQS实现。
20+
21+
#### ArrayBlockingQueue
22+
* ArrayBlockingQueue :一个由数组支持的有界队列。
23+
* 如果到达了上界,将无法添加新的元素进入。
24+
* FIFO
25+
>ArrayBlockingQueue在构造时需要指定容量, 并可以选择是否需要公平性,如果公平参数被设置true,等待时间最长的线程会优先得到处理(其实就是通过将ReentrantLock设置为true来 达到这种公平性的:即等待时间最长的线程会先操作)。通常,公平性会使你在性能上付出代价,只有在的确非常需要的时候再使用它。它是基于数组的阻塞循环队 列,此队列按 FIFO(先进先出)原则对元素进行排序。
26+
```Java
27+
public boolean offer(E e) {
28+
checkNotNull(e);
29+
final ReentrantLock lock = this.lock;
30+
lock.lock(); //在写入的过程中获取锁
31+
try {
32+
if (count == items.length)
33+
return false;
34+
else {
35+
enqueue(e); //调用私有的enqueue方法
36+
return true;
37+
}
38+
} finally {
39+
lock.unlock(); //释放锁
40+
}
41+
}
42+
```
43+
```Java
44+
/**
45+
* Inserts element at current put position, advances, and signals.
46+
* Call only when holding lock.
47+
*/
48+
private void enqueue(E x) {
49+
// assert lock.getHoldCount() == 1;
50+
// assert items[putIndex] == null;
51+
final Object[] items = this.items;
52+
items[putIndex] = x;
53+
if (++putIndex == items.length)
54+
putIndex = 0;
55+
count++;
56+
notEmpty.signal(); //取消notEmpty的await.
57+
}
58+
```
59+
```Java
60+
public E poll() {
61+
final ReentrantLock lock = this.lock;
62+
lock.lock();
63+
try {
64+
return (count == 0) ? null : dequeue(); //判断当前队列有没有元素。有的话调用deqeueu方法。
65+
} finally {
66+
lock.unlock();
67+
}
68+
}
69+
```
70+
```Java
71+
private E dequeue() {
72+
// assert lock.getHoldCount() == 1;
73+
// assert items[takeIndex] != null;
74+
final Object[] items = this.items;
75+
@SuppressWarnings("unchecked")
76+
E x = (E) items[takeIndex];
77+
items[takeIndex] = null;
78+
if (++takeIndex == items.length)
79+
takeIndex = 0;
80+
count--;
81+
if (itrs != null)
82+
itrs.elementDequeued();
83+
notFull.signal();
84+
return x;
85+
}
86+
```
87+
88+
#### LinkedBlockingQueue
89+
* 一个由链接节点支持的可选有界队列。
90+
* 内部维护了一个Node类
91+
>LinkedBlockingQueue的容量是没有上限的(说的不准确,在不指定时容量为Integer.MAX_VALUE,不要然的话在put时怎么会受阻呢),但是也可以选择指定其最大容量,它是基于链表的队列,此队列按 FIFO(先进先出)排序元素。
92+
```Java
93+
static class Node<E> {
94+
E item;
95+
96+
/**
97+
* One of:
98+
* - the real successor Node
99+
* - this Node, meaning the successor is head.next
100+
* - null, meaning there is no successor (this is the last node)
101+
*/
102+
Node<E> next;
103+
104+
Node(E x) { item = x; }
105+
}
106+
```
107+
```Java
108+
public boolean offer(E e) {
109+
if (e == null) throw new NullPointerException();
110+
final AtomicInteger count = this.count; //此处的count为AtomicInteger,维护了原子性
111+
if (count.get() == capacity)
112+
return false;
113+
int c = -1;
114+
Node<E> node = new Node<E>(e);
115+
final ReentrantLock putLock = this.putLock;
116+
putLock.lock();
117+
try {
118+
if (count.get() < capacity) {
119+
enqueue(node);
120+
c = count.getAndIncrement();
121+
if (c + 1 < capacity)
122+
notFull.signal();
123+
}
124+
} finally {
125+
putLock.unlock();
126+
}
127+
if (c == 0)
128+
signalNotEmpty();
129+
return c >= 0;
130+
}
131+
132+
private void enqueue(Node<E> node) {
133+
// assert putLock.isHeldByCurrentThread();
134+
// assert last.next == null;
135+
last = last.next = node; //在链表的结尾,添加要插入的结点。
136+
}
137+
```
138+
```Java
139+
public E poll() {
140+
final AtomicInteger count = this.count;
141+
if (count.get() == 0)
142+
return null;
143+
E x = null;
144+
int c = -1;
145+
final ReentrantLock takeLock = this.takeLock;
146+
takeLock.lock();
147+
try {
148+
if (count.get() > 0) {
149+
x = dequeue();
150+
c = count.getAndDecrement();
151+
if (c > 1)
152+
notEmpty.signal();
153+
}
154+
} finally {
155+
takeLock.unlock();
156+
}
157+
if (c == capacity)
158+
signalNotFull();
159+
return x;
160+
}
161+
```
162+
163+
#### PriorityBlockingQueue
164+
* 一个由优先级堆支持的无界优先级队列。
165+
>PriorityBlockingQueue是一个带优先级的 队列,而不是先进先出队列。元素按优先级顺序被移除,该队列也没有上限(看了一下源码,PriorityBlockingQueue是对 PriorityQueue的再次包装,是基于堆数据结构的,而PriorityQueue是没有容量限制的,与ArrayList一样,所以在优先阻塞 队列上put时是不会受阻的。虽然此队列逻辑上是无界的,但是由于资源被耗尽,所以试图执行添加操作可能会导致 OutOfMemoryError),但是如果队列为空,那么取元素的操作take就会阻塞,所以它的检索操作take是受阻的。另外,往入该队列中的元 素要具有比较能力。
166+
```Java
167+
public boolean offer(E e) {
168+
if (e == null)
169+
throw new NullPointerException();
170+
final ReentrantLock lock = this.lock;
171+
lock.lock();
172+
int n, cap;
173+
Object[] array;
174+
while ((n = size) >= (cap = (array = queue).length))
175+
tryGrow(array, cap);
176+
try {
177+
Comparator<? super E> cmp = comparator;
178+
if (cmp == null)
179+
siftUpComparable(n, e, array);
180+
else
181+
siftUpUsingComparator(n, e, array, cmp);
182+
size = n + 1;
183+
notEmpty.signal();
184+
} finally {
185+
lock.unlock();
186+
}
187+
return true;
188+
}
189+
```
190+
191+
192+
193+
194+
195+
196+
197+
198+
199+
200+
201+
202+
203+
204+
205+
206+
207+
208+
209+
210+
211+
212+
213+
214+
215+
216+
217+
218+
219+
220+
221+
222+
223+
224+
225+
226+
227+
228+
229+
230+
231+

0 commit comments

Comments
 (0)