package heap;
import java.util.NoSuchElementException;
import java.util.Vector;
import trees.BinTree;
public class IntSkewHeap {
private BinTree root;
private int size;
public IntSkewHeap() {
this.root = null;
this.size = 0;
}
public boolean isEmpty() {
return this.size == 0;
}
public int size() {
return this.size;
}
private static BinTree merge(BinTree t1, BinTree t2) {
if (t1 == null) return t2;
if (t2 == null) return t1;
if (t1.value <= t2.value)
return new BinTree(merge(t1.right, t2), t1.value, t1.left);
else
return new BinTree(merge(t2.right, t1), t2.value, t2.left);
}
public void add(int x) {
this.root = merge(this.root, new BinTree(null, x, null));
this.size++;
}
public int getMin() {
if (this.isEmpty()) throw new NoSuchElementException();
return this.root.value;
}
public int removeMin() {
if (this.isEmpty()) throw new NoSuchElementException();
int res = this.root.value;
this.root = merge(this.root.left, this.root.right);
this.size--;
return res;
}
public void merge(IntSkewHeap that) {
this.root = merge(this.root, that.root);
this.size += that.size;
}
@SuppressWarnings("unused")
private static BinTree nonRecursiveMerge(BinTree t1, BinTree t2) {
if (t1 == null && t2 == null) return null;
Vector<BinTree> v = new Vector<BinTree>();
// sorts the right paths, using merge sort
while (t1 != null || t2 != null) {
if (t2 == null || (t1 != null && t1.value <= t2.value)) { // take from t1
v.add(new BinTree(t1.left, t1.value, null));
t1 = t1.right;
} else { // take from t2
v.add(new BinTree(t2.left, t2.value, null));
t2 = t2.right;
}
}
// recombine the last two elements, until one is left
while (v.size() > 1) {
int i = v.size() - 2;
BinTree t = v.get(i);
t.right = t.left;
t.left = v.get(i + 1);
v.setSize(i + 1); // drop last
}
return v.get(0);
}
public String toString() {
return BinTree.stringOfTree(this.root);
}
}
class TestIntSkewHeap {
static boolean is_sorted(int[] a) {
for (int i = 1; i < a.length; i++)
if (!(a[i - 1] <= a[i]))
return false;
return true;
}
static final int M = 10; // les éléments sont dans 0..M-1
static int[] occurrences(int[] a) {
int[] occ = new int[M];
for (int i = 0; i < a.length; i++)
occ[a[i]]++;
return occ;
}
static boolean is_permut(int[] occ1, int[] occ2) {
for (int i = 0; i < M; i++)
if (occ1[i] != occ2[i])
return false;
return true;
}
static String print(int[] a) {
String s = "[";
for (int i = 0; i < a.length; i++)
s += (i == 0 ? "" : ", ") + a[i];
return s + "]";
}
static int[] random_array(int len) {
int[] a = new int[len];
for (int i = 0; i < len; i++)
a[i] = (int) (M * Math.random());
return a;
}
static void test(int[] a) {
System.out.println(" test avec a = " + print(a));
int[] occ1 = occurrences(a);
heapsort(a);
int[] occ2 = occurrences(a);
System.out.println(" heapsort(a) => a = " + print(a));
if (!is_sorted(a)) {
System.out.println("ÉCHEC : le résultat n'est pas trié");
System.exit(1);
}
if (!is_permut(occ1, occ2)) {
System.out.println("ÉCHEC : les éléments diffèrent");
System.exit(1);
}
}
static void heapsort(int[] a) {
IntSkewHeap h = new IntSkewHeap();
for (int x : a) h.add(x);
for (int i = 0; i < a.length; i++) {
a[i] = h.getMin();
h.removeMin();
}
}
public static void main(String[] args) {
IntSkewHeap h = new IntSkewHeap();
h.add(1);
h.add(2);
h.add(2);
h.add(3);
assert (h.size() == 4);
assert (h.getMin() == 1);
h.removeMin();
assert (h.size() == 3);
assert (h.getMin() == 2);
h.removeMin();
assert (h.size() == 2);
assert (h.getMin() == 2);
h.removeMin();
assert (h.size() == 1);
assert (h.getMin() == 3);
h.removeMin();
assert (h.isEmpty());
System.out.println("test de heapsort");
for (int len = 0; len < 10; len++)
for (int j = 0; j <= len; j++)
test(random_array(len));
System.out.println("SUCCÈS");
IntSkewHeap p1 = new IntSkewHeap();
IntSkewHeap p2 = new IntSkewHeap();
for (int i = 0; i < 30; i++)
(i % 2 == 0 ? p1 : p2).add(i);
p1.merge(p2);
System.out.println(p1);
while (!p1.isEmpty()) System.out.print(p1.removeMin() + " ");
System.out.println();
System.out.println("TestIntSkewHeap");
}
}