Skip to content

Commit 951653f

Browse files
committed
Leonardo Heap implementeaton , TODO: Test cases
1 parent 5d21701 commit 951653f

File tree

2 files changed

+250
-209
lines changed

2 files changed

+250
-209
lines changed
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
package com.thealgorithms.datastructures.heaps;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.Collections;
6+
import java.util.List;
7+
8+
import com.thealgorithms.bitmanipulation.SingleBitOperations;
9+
import com.thealgorithms.maths.LeonardoNumber;
10+
11+
public class LeonardoHeap<T extends Comparable<T>> {
12+
13+
private int leonardoLevelTracker;
14+
private int leonardoHeapSize;
15+
private final List<T> leonardoHeap;
16+
17+
public LeonardoHeap() {
18+
this.leonardoHeap = new ArrayList<T>();
19+
this.leonardoLevelTracker = 0;
20+
this.leonardoHeapSize = 0;
21+
}
22+
23+
public static Integer[] getLeonardoNumbers() {
24+
Integer[] leonardoNumbers = {1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465, 753, 1219, 1973, 3193, 5167, 8361, 13529, 21891, 35421, 57313, 92735, 150049, 242785, 392835, 635621, 1028457, 1664079, 2692537, 4356617, 7049155, 1405773, 18454929, 29860703, 48315633, 78176337, 126491971,
25+
204668309, 331160281, 535828591};
26+
27+
return leonardoNumbers;
28+
}
29+
30+
public int getHeapsize() {
31+
return this.leonardoHeapSize;
32+
}
33+
34+
private void decreaseLeonardoLevelTracker() {
35+
int lastTreeLevel = getRightMostTree();
36+
leonardoLevelTracker = SingleBitOperations.clearBit(leonardoLevelTracker, lastTreeLevel);
37+
if (lastTreeLevel != 0 && lastTreeLevel != 1) {
38+
leonardoLevelTracker = SingleBitOperations.setBit(leonardoLevelTracker, lastTreeLevel - 1);
39+
leonardoLevelTracker = SingleBitOperations.setBit(leonardoLevelTracker, lastTreeLevel - 2);
40+
}
41+
}
42+
43+
private void increaseLeonardoLevelTracker() {
44+
Integer[] consecutiveTreeIndices = findConsecutiveLeonardoTreeIndices(leonardoLevelTracker);
45+
if (consecutiveTreeIndices[0] != -1) {
46+
// if 0th or 1st index is -1 that implies there are no concequtive trees
47+
leonardoLevelTracker = SingleBitOperations.clearBit(leonardoLevelTracker, consecutiveTreeIndices[0]);
48+
leonardoLevelTracker = SingleBitOperations.clearBit(leonardoLevelTracker, consecutiveTreeIndices[1]);
49+
leonardoLevelTracker = SingleBitOperations.setBit(leonardoLevelTracker, consecutiveTreeIndices[1] + 1);
50+
} else if ((leonardoLevelTracker & 2) == 0) {
51+
leonardoLevelTracker = SingleBitOperations.setBit(leonardoLevelTracker, 1);
52+
} else {
53+
leonardoLevelTracker = SingleBitOperations.setBit(leonardoLevelTracker, 0);
54+
}
55+
}
56+
57+
private void decreaseHeapSize() {
58+
this.leonardoHeapSize--;
59+
}
60+
61+
private void increaseHeapSize() {
62+
this.leonardoHeapSize++;
63+
}
64+
65+
private void maxHeapifyLeonardoTree(int rootNodeIndex, int currentLeonardoLevel) {
66+
// A leonardo tree of level n is just 1 node(the root) plus the leonardo tree of n-1 level(left child) plus leonardo tree of n-2 level(right child)
67+
// To maxheapify a leonardo tree we need to compare the current root and roots of it's left and right subtree
68+
// We recursively hepify the left and right subtrees using the currentLeonardoLevel
69+
70+
// BASE CASE
71+
if (currentLeonardoLevel == 0 || currentLeonardoLevel == 1) {
72+
return; // Trees with one node are in already max-heapified.
73+
}
74+
75+
int currentRootNodeIndex = rootNodeIndex;
76+
int rightChildIndex = rootNodeIndex - 1;
77+
int leftChildIndex = rootNodeIndex - LeonardoNumber.leonardoNumber(currentLeonardoLevel - 2) - 1;
78+
int childIndexForSwap = -1;
79+
80+
if (leonardoHeap.get(rightChildIndex).compareTo(leonardoHeap.get(leftChildIndex)) >= 0) {
81+
childIndexForSwap = rightChildIndex;
82+
} else {
83+
childIndexForSwap = leftChildIndex;
84+
}
85+
86+
if (leonardoHeap.get(childIndexForSwap).compareTo(leonardoHeap.get(currentRootNodeIndex)) > 0) {
87+
swap(currentRootNodeIndex, childIndexForSwap);
88+
if (childIndexForSwap == rightChildIndex) {
89+
maxHeapifyLeonardoTree(rightChildIndex, currentLeonardoLevel - 2);
90+
} else { // swap happened with the left child
91+
maxHeapifyLeonardoTree(leftChildIndex, currentLeonardoLevel - 1);
92+
}
93+
}
94+
}
95+
96+
private void shiftRootAndRestoreHeap() {
97+
98+
if (getHeapsize() == 0) {
99+
return;
100+
}
101+
102+
Integer[] currentLeonardoTreeLevels = findAllLeonardoTreeIndices();
103+
int previousTreeSizeCumulative = 0;
104+
ArrayList<Integer> rootNodeIndices = new ArrayList<Integer>();
105+
Collections.reverse(Arrays.asList(currentLeonardoTreeLevels)); // To get the Levels in decreasing order of levels
106+
107+
// The number of roots are going to be same the the number of levels
108+
// iterate over the currentLeonardoTreeLevels and get roots
109+
110+
for (int i = 0; i < currentLeonardoTreeLevels.length; i++) {
111+
rootNodeIndices.add(previousTreeSizeCumulative + LeonardoNumber.leonardoNumber(currentLeonardoTreeLevels[i]) - 1);
112+
previousTreeSizeCumulative = previousTreeSizeCumulative + LeonardoNumber.leonardoNumber(currentLeonardoTreeLevels[i]);
113+
}
114+
115+
int rootNodeIndexForHeapify = rootNodeIndices.getLast();
116+
int leonardoTreeLevelforHeapify = currentLeonardoTreeLevels[currentLeonardoTreeLevels.length - 1];
117+
boolean swaped =false;
118+
119+
for (int i = 1; i < rootNodeIndices.size(); i++) {
120+
121+
int currentRootNodeIndex = rootNodeIndices.get(i);
122+
int prevRootNodeIndex = rootNodeIndices.get(i - 1);
123+
int j = i;
124+
while (leonardoHeap.get(prevRootNodeIndex).compareTo(leonardoHeap.get(currentRootNodeIndex)) > 0) {
125+
int currentLeonardoLevel = currentLeonardoTreeLevels[j];
126+
if (currentLeonardoLevel > 1) {
127+
// compare child and swap
128+
129+
int indexOfRightChild = rootNodeIndices.get(j) - 1; // right child is of level n-2
130+
int indexOfLeftChild = rootNodeIndices.get(j) - 1 - LeonardoNumber.leonardoNumber(currentLeonardoLevel - 2);
131+
if (leonardoHeap.get(prevRootNodeIndex).compareTo(leonardoHeap.get(indexOfRightChild)) > 0 && leonardoHeap.get(prevRootNodeIndex).compareTo(leonardoHeap.get(indexOfLeftChild)) > 0) {
132+
swap(prevRootNodeIndex, currentRootNodeIndex);
133+
rootNodeIndexForHeapify = prevRootNodeIndex;
134+
leonardoTreeLevelforHeapify = currentLeonardoTreeLevels[j - 1];
135+
swaped = true;
136+
} else {
137+
maxHeapifyLeonardoTree(currentRootNodeIndex, currentLeonardoLevel);
138+
swaped = false;
139+
}
140+
} else {
141+
swap(prevRootNodeIndex, currentRootNodeIndex);
142+
rootNodeIndexForHeapify = prevRootNodeIndex;
143+
leonardoTreeLevelforHeapify = currentLeonardoTreeLevels[j - 1];
144+
swaped = true;
145+
}
146+
j = j - 1;
147+
if(j > 0) {
148+
currentRootNodeIndex = rootNodeIndices.get(j);
149+
prevRootNodeIndex = rootNodeIndices.get(j - 1);
150+
}
151+
else{
152+
// j = 0 reached the left most tree
153+
break;
154+
}
155+
}
156+
157+
if(swaped) {
158+
maxHeapifyLeonardoTree(rootNodeIndexForHeapify, leonardoTreeLevelforHeapify);
159+
swaped = false;
160+
}
161+
162+
}
163+
164+
maxHeapifyLeonardoTree(rootNodeIndexForHeapify, leonardoTreeLevelforHeapify); // In case of insert and no swap.
165+
166+
}
167+
168+
private int getRightMostTree() {
169+
// Isolate the rightmost set bit
170+
int isolatedBit = leonardoLevelTracker & -leonardoLevelTracker;
171+
int position = 0;
172+
173+
while (isolatedBit > 1) {
174+
isolatedBit >>= 1;
175+
position++;
176+
}
177+
178+
return position;
179+
}
180+
181+
private static Integer[] findConsecutiveLeonardoTreeIndices(int num) {
182+
int prevOneIndex = -1;
183+
int currentLevel;
184+
185+
Integer[] answer = new Integer[] {-1, -1};
186+
for (int i = 0; num > 0; i++) {
187+
currentLevel = num & 1;
188+
if (currentLevel == 1) {
189+
if (prevOneIndex != -1) {
190+
answer[0] = prevOneIndex;
191+
answer[1] = i;
192+
}
193+
prevOneIndex = i;
194+
} else {
195+
prevOneIndex = -1;
196+
}
197+
num >>>= 1;
198+
}
199+
return answer;
200+
}
201+
202+
private void swap(int i, int j) {
203+
T temp = leonardoHeap.get(i);
204+
leonardoHeap.set(i, leonardoHeap.get(j));
205+
leonardoHeap.set(j, temp);
206+
}
207+
208+
// TODO use lists
209+
private Integer[] findAllLeonardoTreeIndices() {
210+
int setBitCount = 0;
211+
for (int i = 0; i < Integer.SIZE; i++) {
212+
if ((leonardoLevelTracker & (1 << i)) != 0) {
213+
setBitCount++;
214+
}
215+
}
216+
217+
Integer[] setBitIndexes = new Integer[setBitCount];
218+
int index = 0;
219+
for (int i = 0; i < Integer.SIZE; i++) {
220+
if ((leonardoLevelTracker & (1 << i)) != 0) {
221+
setBitIndexes[index++] = i;
222+
}
223+
}
224+
return setBitIndexes;
225+
}
226+
227+
228+
public void insertElement(T element) {
229+
increaseLeonardoLevelTracker();
230+
leonardoHeap.add(element);
231+
increaseHeapSize();
232+
shiftRootAndRestoreHeap();
233+
}
234+
235+
public T deleteElement() {
236+
decreaseLeonardoLevelTracker();
237+
decreaseHeapSize();
238+
T element = leonardoHeap.removeLast();
239+
shiftRootAndRestoreHeap();
240+
241+
return element;
242+
}
243+
}

0 commit comments

Comments
 (0)