summaryrefslogtreecommitdiff
path: root/lib/BHeap.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/BHeap.cc')
-rw-r--r--lib/BHeap.cc278
1 files changed, 278 insertions, 0 deletions
diff --git a/lib/BHeap.cc b/lib/BHeap.cc
new file mode 100644
index 0000000..4d7cc9e
--- /dev/null
+++ b/lib/BHeap.cc
@@ -0,0 +1,278 @@
+#include <stdio.h>
+#include "config.h"
+#include "BHeap.h"
+#include "CList.h"
+
+static int d, Depths[65536];
+
+void BHeap::Dump(ostream & os)
+{
+ int i;
+
+ if (Degree == -1) {
+ os << _(" * Head cell.\n |\n");
+ for (i = 0; i < 65535; i++)
+ Depths[i] = 1;
+ d = 1;
+ } else {
+ for (i = 1; i <= d; i++)
+ os << (Depths[i] ? " |" : " ");
+ os << (Child ? "_ " : "__ ") << Key << endl;
+ }
+ if (Child) {
+ Depths[d] = (Brother != NULL);
+ d++;
+ Child->Dump(os);
+ d--;
+ }
+ if (Brother) {
+ Brother->Dump(os);
+ }
+}
+
+int BHeap::rn(void)
+{
+ int n = 0;
+
+ if (Degree != -1) {
+ n++;
+ }
+ if (Child) {
+ n += Child->rn();
+ }
+ if (Brother) {
+ n += Brother->rn();
+ }
+ return n;
+}
+
+void BHeap::Link(BHeap * z)
+{
+ Father = z;
+ Brother = z->Child;
+ z->Child = this;
+ z->Degree = z->Degree + 1;
+}
+
+void BHeap::Merge(BHeap * H)
+{
+ BHeap *P1, *P2, *T1, *T2;
+
+ Key += H->Key;
+ H->Key = 0;
+
+ for (P1 = this, P2 = H->Brother; P1->Brother && P2;) {
+ if (P1->Brother->Degree < P2->Degree) { // P1 < P2, jump over P1.
+ P1 = P1->Brother;
+ } else { // P1 >= P2. We will insert P2 after P1.
+ T1 = P1->Brother;
+ T2 = P2->Brother;
+ P1->Brother = P2;
+ P2->Brother = T1;
+ P1 = P2;
+ P2 = T2;
+ }
+ }
+ if (!(P1->Brother))
+ P1->Brother = P2;
+ H->Brother = NULL;
+}
+
+BHeap::BHeap(void):Degree(-1), Father(NULL), Child(NULL), Brother(NULL),
+FP(new CList)
+{
+ type = T_BHEAP;
+}
+
+BHeap::BHeap(Key_t IKey, Datas_t const &IDatas):PriorityList(IKey, IDatas),
+Degree(0), Father(NULL), Child(NULL), Brother(NULL)
+{
+ type = T_BHEAP;
+#ifdef DEBUG
+ nc++;
+#endif
+}
+
+BHeap::~BHeap(void)
+{
+ if (Degree == -1)
+ delete FP;
+
+ if (Child) {
+ delete Child;
+ }
+ if (Brother) {
+ delete Brother;
+ }
+#ifdef DEBUG
+ nd++;
+#endif
+}
+
+Cell BHeap::Min(void)
+{
+ BHeap *x = this, *y = NULL;
+ int min = P_INFINITY;
+
+ for (; x; x = x->Brother) {
+ if ((x->Key < min)) {
+ min = x->Key;
+ y = x;
+ }
+ }
+
+ return y->FP;
+}
+
+Cell BHeap::Insert(BHeap * E)
+{
+ BHeap *H;
+
+ if (Degree != -1)
+ exception(2, _("Insert: not over Head."));
+ if (!(H = new BHeap))
+ exception(5, _("Insert: No more memory."));
+ H->Brother = E;
+ Union(H);
+ delete H;
+
+ return ((E->FP = ((CList *) (FP->Insert(Key, E)))));
+}
+
+Cell BHeap::Insert(Key_t IKey, Datas_t const &IDatas)
+{
+ BHeap *P;
+
+ Key++;
+
+ if (!(P = new BHeap(IKey, IDatas)))
+ exception(5, _("Insert: No more memory."));
+ return (Insert(P));
+}
+
+Key_t BHeap::Extract_Min(Datas_t & Datas)
+{
+ BHeap *x, *y = NULL, *P, *P2, *P3, *Before;
+ Key_t k;
+ int min = P_INFINITY;
+
+ P = Before = this;
+
+ if (!Brother)
+ exception(4, _("Extract_Min: Priority List is empty."));
+
+ Key--;
+
+ for (x = Brother; x; x = x->Brother) {
+ if ((x->Key < min)) {
+ min = x->Key;
+ y = x;
+ Before = P;
+ }
+ P = x;
+ }
+
+ Before->Brother = y->Brother;
+
+ Before = new BHeap;
+
+ for (P = y->Child; P;) {
+ P2 = Before->Brother;
+ P3 = P->Brother;
+ Before->Brother = P;
+ P->Brother = P2;
+ P = P3;
+ }
+
+ Before->Key = 0;
+ Union(Before);
+
+ k = y->Key;
+ y->Brother = y->Child = NULL;
+ FP->Delete(Datas, ((Cell) y->FP));
+ Datas = y->Datas;
+ delete y;
+
+ return k;
+}
+
+PriorityList *BHeap::Union(PriorityList * P)
+{
+ BHeap *x, *Before, *After;
+
+ if ((P->GetType()) != (((PriorityList *) this)->GetType()))
+ return GenericUnion(P);
+
+ Merge((BHeap *) P);
+ if (!(Brother)) {
+ return this;
+ }
+ Before = this;
+ x = Brother;
+ After = x->Brother;
+ while (After) {
+ if ((x->Degree != After->Degree)
+ || ((After->Brother)
+ && (After->Brother->Degree == x->Degree))) {
+ Before = x;
+ x = After;
+ } else {
+ if (x->Key <= After->Key) {
+ x->Brother = After->Brother;
+ After->Link(x);
+ } else {
+ Before->Brother = After;
+ x->Link(After);
+ x = After;
+ }
+ }
+ After = x->Brother;
+ }
+ return this;
+}
+
+bool BHeap::Lower_Key(Cell x, Key_t NKey)
+{
+ BHeap *y, *z, *tx = ((BHeap *) ((CList *) x)->Datas);
+
+ if (NKey > tx->Key)
+ return false;
+ tx->Key = NKey;
+
+ for (y = tx, z = tx->Father; z && (y->Key < z->Key);
+ y = z, z = y->Father) {
+ SWAP(y->Datas, z->Datas);
+ SWAP(y->Key, z->Key);
+ SWAP(y->FP, z->FP);
+ SWAP(((CList *) (y->FP))->Datas, ((CList *) (z->FP))->Datas);
+ }
+
+ return true;
+}
+
+Key_t BHeap::Delete(Datas_t & Datas, Cell x)
+{
+ Key_t K;
+
+ K = ReadKey(x);
+
+ Lower_Key(x, M_INFINITY);
+ Extract_Min(Datas);
+
+ return K;
+}
+
+bool BHeap::IsEmpty(void)
+{
+ return (!(Brother));
+}
+
+Key_t BHeap::ReadKey(Cell C)
+{
+ return ((BHeap *) ((CList *) C)->Datas)->Key;
+}
+
+Datas_t BHeap::ReadDatas(Cell C)
+{
+ return ((BHeap *) ((CList *) C)->Datas)->Datas;
+}