Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 601
Expand file tree
/
Copy pathHashedArrayTree.java
More file actions
Latest commit
121 lines (96 loc) · 3.08 KB
/
Copy pathHashedArrayTree.java
File metadata and controls
121 lines (96 loc) · 3.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
packageds;
/**
* Created by sherxon on 5/23/17.
*/
/**
* This is the implementation of Hashed Array Tree (HAT) data structure that is the same as Dynamic
* Array (ArrayList in Java) in terms of time complexity, however, it wastes O(SQRT(N)) extra space
* when increasing capacity.
*
* Although name implies hashing, HAT does not use any hash.
*
* Initially, we start with base array that stores only references to leaf arrays whose size is
* the same as base array. Every time current leaf array is full we create new leaf array and start
* to insert data into newly created leaf array.
*
* When increasing capacity, we double size of base array and leaf create leaf arrays with doubles
* size and copy entries from previous HAT. In this way, only quarter of newly created HAT is full
* and other leaf arrays will be null.
*/
publicclassHashedArrayTree {
privateObject[][] data; // base array, used to store references to leaf arrays
privateintsize;
privateintiPointer = -1;
privateintjPointer = 17;
publicHashedArrayTree() {
this.data = newObject[16][]; // should be power of 2, all leaf arrays are not initialized
}
publicvoidadd(Integerelem) {
ensureCapacity();
Object[] leaf = getLeaf();
leaf[jPointer++] = elem;
size++;
}
/**
* this method checks capacity and extend it if needed.
* all data copied to new storage and only one empty leaf will be available to insert
* Extra wasted space is equal to 2*SQRT(n);
*/
privatevoidensureCapacity() {
if (iPointer + 1 < data.length || jPointer < data[iPointer].length) {
return;
}
intprevLength = data.length;
Object[][] newData = newObject[prevLength * 2][];
iPointer = prevLength / 2;
for (inti = 0; i < iPointer; i++) {
newData[i] = newObject[prevLength * 2];
for (intj = 0; j < newData[i].length; j++) {
newData[i][j] = data[i % prevLength + j / prevLength][j % prevLength];
}
}
jPointer = 0;
newData[iPointer] = newObject[prevLength * 2];
this.data = newData;
}
/**
* helper method to see capacity and number of entries in HAT
*/
publicvoidprintStats() {
intbusy = 0;
intcap = 0;
for (inti = 0; i < data.length; i++) {
if (data[i] != null) {
for (intj = 0; j < data[i].length; j++) {
if (data[i][j] != null) {
busy++;
}
cap++;
}
}
}
System.out.println("Size: " + size + "; Capacity: " + cap + "; Busy: " + busy);
}
publicObjectget(intindex) {
if (index < 0 || index >= size) {
thrownewIndexOutOfBoundsException();
}
intiiPointer = index / data.length;
intjjPointer = index % data.length;
returndata[iiPointer][jjPointer];
}
publicintsize() {
returnsize;
}
/**
* returns available leaf to insert data.
* if current leaf is already full,creates new leaf and returns it
*/
privateObject[] getLeaf() {
if (jPointer >= data.length) {
data[++iPointer] = newObject[data.length];
jPointer = 0;
}
returndata[iPointer];
}
}