Fossil

Changes On Branch wrong-branch
Login

Changes On Branch wrong-branch

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch wrong-branch Excluding Merge-Ins

This is equivalent to a diff from 459499b0ea to 0fa917da41

2025-03-10
14:43
Merge the latest trunk enhancements into the comment-markdown-links branch. ... (check-in: 652362e97c user: drh tags: comment-markdown-links)
2025-03-08
12:13
Improved implementation of the PQueue object, with the added option to carry an arbitrary pointer as content. ... (check-in: 4111717eae user: drh tags: min-from-to)
12:04
Improved implementation of the PQueue object, with the added option to carry an arbitrary pointer as content. ... (Leaf check-in: 0fa917da41 user: drh tags: wrong-branch)
2025-03-07
23:19
Merge the latest trunk enhancements into the comment-markdown-links branch. ... (check-in: 459499b0ea user: drh tags: comment-markdown-links)
20:26
Add the /test-title webpage. Accessible to administrators only. ... (check-in: af57f63dee user: drh tags: trunk)
2025-03-05
21:43
Further tweaks to the markdown style formatting in wiki. ... (check-in: 1029539757 user: drh tags: comment-markdown-links)

Changes to src/pqueue.c.
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
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This file contains code used to implement a priority queue.
** A priority queue is a list of items order by a floating point
** value.  We can insert integers with each integer tied to its
** value then extract the integer with the smallest value.

**
** The way this queue is used, we never expect it to contain more
** than 2 or 3 elements, so a simple array is sufficient as the
** implementation.  This could give worst case O(N) insert times,








** but because of the nature of the problem we expect O(1) performance.
**
** Compatibility note:  Some versions of OpenSSL export a symbols
** like "pqueue_insert".  This is, technically, a bug in OpenSSL.
** We work around it here by using "pqueuex_" instead of "pqueue_".
*/
#include "config.h"
#include "pqueue.h"
#include <assert.h>


#if INTERFACE
/*
** An integer can appear in the bag at most once.
** Integers must be positive.
*/
struct PQueue {
  int cnt;   /* Number of entries in the queue */
  int sz;    /* Number of slots in a[] */
  struct QueueElement {

    int id;          /* ID of the element */


    double value;    /* Value of element.  Kept in ascending order */
  } *a;
};
#endif

/*
** Initialize a PQueue structure







|
|
>

<
<
|
>
>
>
>
>
>
>
>
|



















>
|
>
>







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
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This file contains code used to implement a priority queue.
** A priority queue is a list of items order by a floating point
** value.  Each value can be associated with either a pointer or
** an integer.  Items are inserted into the queue in an arbitrary
** order, but are returned in order of the floating point value.
**


** This implementation uses a heap of QueueElement objects.  The
** root of the heap is PQueue.a[0].  Each node a[x] has two daughter
** nodes a[x*2+1] and a[x*2+2].  The mother node of a[y] is a[(y-1)/2]
** (assuming integer division rounded down).  The following is always true:
**
**    The value of any node is less than or equal two the values
**    of both daughter nodes.  (The Heap Property).
**
** A consequence of the heap property is that a[0] always contains
** the node with the smallest value.
**
** Compatibility note:  Some versions of OpenSSL export a symbols
** like "pqueue_insert".  This is, technically, a bug in OpenSSL.
** We work around it here by using "pqueuex_" instead of "pqueue_".
*/
#include "config.h"
#include "pqueue.h"
#include <assert.h>


#if INTERFACE
/*
** An integer can appear in the bag at most once.
** Integers must be positive.
*/
struct PQueue {
  int cnt;   /* Number of entries in the queue */
  int sz;    /* Number of slots in a[] */
  struct QueueElement {
    union {
      int id;          /* ID of the element */
      void *p;         /* Pointer to an object */
    } u;
    double value;    /* Value of element.  Kept in ascending order */
  } *a;
};
#endif

/*
** Initialize a PQueue structure
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






























































/*
** Change the size of the queue so that it contains N slots
*/
static void pqueuex_resize(PQueue *p, int N){
  p->a = fossil_realloc(p->a, sizeof(p->a[0])*N);
  p->sz = N;
}

/*


























** Insert element e into the queue.
*/
void pqueuex_insert(PQueue *p, int e, double v){

















  int i, j;



  if( p->cnt+1>p->sz ){
    pqueuex_resize(p, p->cnt+5);
  }
  for(i=0; i<p->cnt; i++){

    if( p->a[i].value>v ){
      for(j=p->cnt; j>i; j--){


        p->a[j] = p->a[j-1];

      }
      break;
    }
  }
  p->a[i].id = e;
  p->a[i].value = v;
  p->cnt++;
}

/*
** Extract the first element from the queue (the element with
** the smallest value) and return its ID.  Return 0 if the queue
** is empty.
*/
int pqueuex_extract(PQueue *p){
  int e, i;
  if( p->cnt==0 ){
    return 0;
  }
  e = p->a[0].id;
  for(i=0; i<p->cnt-1; i++){
    p->a[i] = p->a[i+1];
  }


  p->cnt--;




  return e;
}







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
|
<
|
>
|
<
>
>
|
>
|
<
<
<
<
<
<








|



|
|
|
|
>
>
|
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

138
139
140

141
142
143
144
145






146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/*
** Change the size of the queue so that it contains N slots
*/
static void pqueuex_resize(PQueue *p, int N){
  p->a = fossil_realloc(p->a, sizeof(p->a[0])*N);
  p->sz = N;
}

/*
** Allocate a new queue entry and return a pointer to it.
*/
static struct QueueElement *pqueuex_new_entry(PQueue *p){
  if( p->cnt+1>p->sz ){
    pqueuex_resize(p, p->cnt+7);
  }
  return &p->a[p->cnt++];
}

/*
** Element p->a[p->cnt-1] has just been inserted.  Shift entries
** around so as to preserve the heap property.
*/
static void pqueuex_rebalance(PQueue *p){
  int i, j;
  struct QueueElement *a = p->a;
  i = p->cnt-1;
  while( (j = (i-1)/2)>=0 && a[j].value>a[i].value ){
    struct QueueElement t = a[j];
    a[j] = a[i];
    a[i] = t;
    i = j;
  }
}

/*
** Insert element e into the queue.
*/
void pqueuex_insert(PQueue *p, int e, double v){
  struct QueueElement *pE = pqueuex_new_entry(p);
  pE->value = v;
  pE->u.id = e;
  pqueuex_rebalance(p);
}
void pqueuex_insert_ptr(PQueue *p, void *pPtr, double v){
  struct QueueElement *pE = pqueuex_new_entry(p);
  pE->value = v;
  pE->u.p = pPtr;
  pqueuex_rebalance(p);
}

/*
** Remove and discard p->a[0] element from the queue.  Rearrange
** nodes to preserve the heap property.
*/
static void pqueuex_pop(PQueue *p){
  int i, j;
  struct QueueElement *a = p->a;
  struct QueueElement tmp;
  i = 0;
  a[0] = a[p->cnt-1];
  p->cnt--;

  while( (j = i*2+1)<p->cnt ){
    if( j+1<p->cnt && a[j].value > a[j+1].value ) j++;
    if( a[i].value < a[j].value ) break;

    tmp = a[i];
    a[i] = a[j];
    a[j] = tmp;
    i = j;
  }






}

/*
** Extract the first element from the queue (the element with
** the smallest value) and return its ID.  Return 0 if the queue
** is empty.
*/
int pqueuex_extract(PQueue *p){
  int e;
  if( p->cnt==0 ){
    return 0;
  }
  e = p->a[0].u.id;
  pqueuex_pop(p);
  return e;
}
void *pqueuex_extract_ptr(PQueue *p){
  void *pPtr;
  if( p->cnt==0 ){
    return 0;
  }
  pPtr = p->a[0].u.p;
  pqueuex_pop(p);
  return pPtr;
}

/*
** Print the entire heap associated with the test-pqueue command.
*/
static void pqueuex_test_print(PQueue *p){
  int j;
  for(j=0; j<p->cnt; j++){
    fossil_print("(%d) %g/%s ",j,p->a[j].value,p->a[j].u.p);
  }
  fossil_print("\n");
}

/*
** COMMAND: test-pqueue
**
** This command is used for testing the PQueue object.  There are one
** or more arguments, each of the form:
**
**     (1)    NUMBER/TEXT
**     (2)    ^
**     (3)    -v
**
** Form (1) arguments add an entry to the queue with value NUMBER and
** content TEXT.  Form (2) pops off the queue entry with the smallest
** value.  Form (3) (the -v option) causes the heap to be displayed after
** each subsequent operation.
*/
void pqueuex_test_cmd(void){
  int i;
  PQueue x;
  const char *zId;
  int bDebug = 0;

  pqueuex_init(&x);
  for(i=2; i<g.argc; i++){
    const char *zArg = g.argv[i];
    if( strcmp(zArg,"-v")==0 ){
      bDebug = 1;
    }else if( strcmp(zArg, "^")==0 ){
      zId = pqueuex_extract_ptr(&x);
      if( zId==0 ){
        fossil_print("%2d: POP     NULL\n", i);
      }else{
        fossil_print("%2d: POP     \"%s\"\n", i, zId);
      }
      if( bDebug) pqueuex_test_print(&x);
    }else{
      double r = atof(zArg);
      zId = strchr(zArg,'/');
      if( zId==0 ) zId = zArg;
      if( zId[0]=='/' ) zId++;
      pqueuex_insert_ptr(&x, (void*)zId, r);
      fossil_print("%2d: INSERT  \"%s\"\n", i, zId);
      if( bDebug) pqueuex_test_print(&x);
    }
  }
  while( (zId = pqueuex_extract_ptr(&x))!=0 ){
    fossil_print("... POP     \"%s\"\n", zId);
    if( bDebug) pqueuex_test_print(&x);
  }
  pqueuex_clear(&x);
}