OSDN Git Service

ver1.1
[nysol/mining.git] / lcm / lib / aheap.c
diff --git a/lcm/lib/aheap.c b/lcm/lib/aheap.c
new file mode 100644 (file)
index 0000000..b479554
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+    array-based simple heap (fixex size)
+            12/Apr/2001   by Takeaki Uno  e-mail:uno@nii.jp, 
+    homepage:   http://research.nii.ac.jp/~uno/index.html  */
+/* This program is available for only academic use, basically.
+   Anyone can modify this program, but he/she has to write down 
+    the change of the modification on the top of the source code.
+   Neither contact nor appointment to Takeaki Uno is needed.
+   If one wants to re-distribute this code, do not forget to 
+    refer the newest code, and show the link to homepage of 
+    Takeaki Uno, to notify the news about the codes for the users.
+   For the commercial use, please make a contact to Takeaki Uno. */
+
+#ifndef _aheap_c_
+#define _aheap_c_
+
+#include"aheap.h"
+
+QSORT_TYPE (AHEAP_KEY, AHEAP_KEY)
+QSORT_TYPE (AHEAP_ID, AHEAP_ID)
+AHEAP INIT_AHEAP = {TYPE_AHEAP,NULL,0,0};
+
+/* allocate memory */
+void AHEAP_alloc (AHEAP *H, AHEAP_ID num){
+  AHEAP_ID i;
+#ifdef ERROR_CHECK
+  if ( num<0 ) error_num ("size is out of range", num, EXIT);
+#endif
+  *H = INIT_AHEAP;
+  if ( num>0 ) malloc2 (H->v, num*2, "AHEAP_alloc: H->v", EXIT);
+  H->end = num;
+  ARY_FILL (H->v, 0, num*2, AHEAP_KEYHUGE);
+  for (i=0 ; i<num-1 ; i=i*2+1);
+  H->base = i - num + 1;
+}
+
+/* termination */
+void AHEAP_end (AHEAP *H){
+  free2 (H->v);
+  *H = INIT_AHEAP;
+}
+
+/* return the index of the leaf having the minimum key among the descendants
+  of the given node i. If several leaves with the smallest key are there, 
+  return the minimum index among them if f=0, maximum index if f=1, and
+  random choice if f=2  */
+/* random choice version. choose one child to go down randomly for each node,
+   thus it is not uniformly random */
+AHEAP_ID AHEAP_findmin_node (AHEAP *H, AHEAP_ID i, int f){
+  if ( H->end <= 0 ) return (-1); 
+  while ( i < H->end-1 ){
+    if ( H->v[i*2+1] == H->v[i] )
+      if ( H->v[i*2+2] == H->v[i] )
+        if ( f == 2 ) i = i*2 + 1 + rand()%2;
+        else i = i*2+1+f;
+      else i = i*2+1;
+    else i = i*2+2;
+  }
+  return (AHEAP_IDX(*H, i) );
+}
+AHEAP_ID AHEAP_findmin_head (AHEAP *H){ return (AHEAP_findmin_node (H, 0, 0) ); }
+AHEAP_ID AHEAP_findmin_tail (AHEAP *H){ return (AHEAP_findmin_node (H, 0, 1) ); }
+AHEAP_ID AHEAP_findmin_rnd (AHEAP *H){ return (AHEAP_findmin_node (H, 0, 2) ); }
+
+/* return the index of the leaf having smaller value than a among the
+  descendants of the given node i. If several leaves with the smallest key
+  are there, return the minimum index among them if f=0, maximum index if f=1,
+  and random choice if f=2  */
+AHEAP_ID AHEAP_findlow_node (AHEAP *H, AHEAP_KEY a, AHEAP_ID i, int f){
+  if ( H->end == 0 ) return (-1); 
+  if ( H->v[0] > a ) return (-1);
+  while ( i < H->end-1 ){
+    if ( f == 2 ) {
+      if ( H->v[i*2+1] <= a )
+          if ( H->v[i*2+2] <= a ) i = i*2 + 1 + rand()%2;
+          else i = i*2+1;
+      else i = i*2+2;
+    } else if ( H->v[i*2+1] <= a ) i = i*2+1+f; else i = i*2+2-f;
+  }
+  return (AHEAP_IDX(*H, i) );
+}
+AHEAP_ID AHEAP_findlow_head (AHEAP *H, AHEAP_KEY a){ return (AHEAP_findlow_node (H, a, 0, 0) ); }
+AHEAP_ID AHEAP_findlow_tail (AHEAP *H, AHEAP_KEY a){ return (AHEAP_findlow_node (H, a, 0, 1) ); }
+AHEAP_ID AHEAP_findlow_rnd (AHEAP *H, AHEAP_KEY a){ return (AHEAP_findlow_node (H, a, 0, 2) ); }
+
+/* return the index of the leaf having smaller value than a next/previous to
+  leaf i. return -1 if such a leaf does not exist  */
+AHEAP_ID AHEAP_findlow_nxt (AHEAP *H, AHEAP_ID i, AHEAP_KEY a){
+  if ( H->end == 0 ) return (-1); 
+  for (i=AHEAP_LEAF(*H,i); i>0 ; i=(i-1)/2){
+     /* i is the child of smaller index, and the key of the sibling of i is less than a */
+    if ( i%2 == 1 && H->v[i+1] <= a ) return (AHEAP_findlow_node (H, a, i+1, 0) );
+  }
+  return (-1);
+}
+AHEAP_ID AHEAP_findlow_prv (AHEAP *H, AHEAP_ID i, AHEAP_KEY a){
+  if ( H->end == 0 ) return (-1); 
+  for (i=AHEAP_LEAF(*H,i); i>0 ; i=(i-1)/2){
+     /* i is the child of larger index, and the key of the sibling of i is less than a */
+    if ( i%2 == 0 && H->v[i-1] <= a ) return (AHEAP_findlow_node (H, a, i-1, 1) );
+  }
+  return (-1);
+}
+
+/* change the key of node i to a /Add a to the key of node i, and update heap H */
+void AHEAP_chg (AHEAP *H, AHEAP_ID i, AHEAP_KEY a){
+  i = AHEAP_LEAF (*H, i);
+  H->v[i] = a;
+  AHEAP_update (H, i);
+}
+void AHEAP_add (AHEAP *H, AHEAP_ID i, AHEAP_KEY a){
+  i = AHEAP_LEAF (*H, i);
+  H->v[i] += a;
+  AHEAP_update (H, i);
+}
+
+/* update the ancestor of node i */
+void AHEAP_update (AHEAP *H, AHEAP_ID i){
+  AHEAP_ID j;
+  AHEAP_KEY a = H->v[i];
+  while ( i>0 ){
+    j = i - 1 + (i%2)*2;   /* j = the sibling of i */
+    i = (i-1) / 2;
+    if ( H->v[j] < a ) a = H->v[j];
+    if ( a == H->v[i] ) break;
+    H->v[i] = a;
+  }
+}
+
+/* find the leaf with the minimum key value among the leaves having index 
+ smaller/larger than i, or between i and j */
+AHEAP_ID AHEAP_upper_min (AHEAP *H, AHEAP_ID i){
+  AHEAP_ID fi=0, j = AHEAP_LEAF (*H, H->end - 1);
+  AHEAP_KEY fm = AHEAP_KEYHUGE;
+  if ( i == 0 ) return (AHEAP_findmin_head (H) );
+  i = AHEAP_LEAF (*H, i-1);
+  while ( i != j ){
+    if ( i%2 ){ /* if i is the child with smaller index */
+      if ( fm > H->v[i+1] ){
+        fm = H->v[i+1];
+        fi = i+1;
+      }
+    }
+    i = (i-1)/2;
+    if ( j == i ) break;  /* stop if the right pointer and the left pointer are the same */
+    j = (j-1)/2;
+  }
+  while ( fi < H->end-1 ) fi = fi*2 + (H->v[fi*2+1]<=fm?1:2);
+  return ( AHEAP_IDX(*H, fi) );
+}
+AHEAP_ID AHEAP_lower_min (AHEAP *H, AHEAP_ID i){
+  AHEAP_ID fi=0, j = AHEAP_LEAF (*H, 0);
+  AHEAP_KEY fm = AHEAP_KEYHUGE;
+  if ( i == H->end-1 ) return (AHEAP_findmin_head (H) );
+  i = AHEAP_LEAF (*H, i+1);
+  while ( i != j ){
+    if ( i%2 == 0 ){ /* if i is the child of larger index */
+      if ( fm > H->v[i-1] ){
+        fm = H->v[i-1];
+        fi = i-1;
+      }
+    }
+    j = (j-1)/2;
+    if ( j == i ) break;  /* stop if the right pointer and the left pointer are the same */
+    i = (i-1)/2;
+  }
+  while ( fi < H->end-1 ) fi = fi*2 + (H->v[fi*2+1]<=fm?1:2);
+  return (AHEAP_IDX(*H, fi) );
+}
+
+/* find the index having the minimum among given two indices */
+AHEAP_ID AHEAP_interval_min (AHEAP *H, AHEAP_ID i, AHEAP_ID j){
+  AHEAP_ID fi=0;
+  AHEAP_KEY fm = AHEAP_KEYHUGE;
+  if ( i == 0 ) return (AHEAP_lower_min (H, j) );
+  if ( j == H->end-1 ) return (AHEAP_upper_min (H, i) );
+  i = AHEAP_LEAF (*H, i-1);
+  j = AHEAP_LEAF (*H, j+1);
+  while ( i != j && i != j-1 ){
+    if ( i%2 ){ /* if i is the child of smaller index */
+      if ( fm > H->v[i+1] ){
+        fm = H->v[i+1];
+        fi = i+1;
+      }
+    }
+    i = (i-1)/2;
+    if ( j == i || j == i+1 ) break;  /* stop if the right pointer and the left pointer are the same */
+    if ( j%2 == 0 ){ /* if j is the child of larger index */
+      if ( fm > H->v[j-1] ){
+        fm = H->v[j-1];
+        fi = j-1;
+      }
+    }
+    j = (j-1)/2;
+  }
+  while ( fi < H->end-1 )
+      fi = fi*2 + (H->v[fi*2+1] <= fm?1:2);
+  return (AHEAP_IDX(*H, fi) );
+}
+
+/* print heap keys according to the structure of the heap */
+void AHEAP_print (AHEAP *H){
+  AHEAP_ID i, j=1;
+  while ( j<=H->end*2-1 ){
+    FLOOP (i, j-1, MIN(j, H->end)*2-1) printf (AHEAP_KEYF ",", H->v[i] );
+    printf ("\n");
+    j = j*2;
+  }
+}
+
+#endif