-
Notifications
You must be signed in to change notification settings - Fork 2
/
forest.c
160 lines (137 loc) · 2.97 KB
/
forest.c
1
2
3
4
5
6
7
8
9
10
11
12
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
64
65
66
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
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
/****************************************************************************
* forest.c
*
* Computer Science 50
* Problem Set 6
*
* Implements a forest for Huffman trees.
***************************************************************************/
#include <stdbool.h>
#include <stdlib.h>
#include "forest.h"
#include "tree.h"
/**
* Makes a forest, initially barren, returning pointer thereto
* or NULL on error.
*/
Forest* mkforest(void)
{
// allocate space for forest
Forest *f = malloc(sizeof(Forest));
if (f == NULL)
{
return NULL;
}
// initialize forest as barren
f->first = NULL;
// return forest
return f;
}
/**
* Removes a tree with lowest weight from the forest, returning
* pointer thereto or NULL if forest is barren.
*/
Tree* pick(Forest* f)
{
// ensure source is not NULL
if (f == NULL)
{
return NULL;
}
// check whether forest is barren
if (f->first == NULL)
{
return NULL;
}
// pick tree with lowest weight
Tree* tree = f->first->tree;
// clear tree's plot
Plot* plot = f->first;
f->first = f->first->next;
free(plot);
// return tree
return tree;
}
/**
* Plants a tree in the forest, provided that tree's frequency is non-0.
* Returns true on success and false on error.
*/
bool plant(Forest* f, Tree* t)
{
// ensure destination and source are not NULL
if (f == NULL || t == NULL)
{
return false;
}
// reject useless trees
if (t->frequency == 0)
{
return false;
}
// prepare tree for forest
Plot* plot = malloc(sizeof(Plot));
if (plot == NULL)
{
return false;
}
plot->tree = t;
// find tree's position in forest
Plot* trailer = NULL;
Plot* leader = f->first;
while (leader != NULL)
{
// keep trees sorted first by frequency then by symbol
if (t->frequency < leader->tree->frequency)
{
break;
}
else if (t->frequency == leader->tree->frequency
&& t->symbol < leader->tree->symbol)
{
break;
}
else
{
trailer = leader;
leader = leader->next;
}
}
// either insert plot at start of forest
if (trailer == NULL)
{
plot->next = f->first;
f->first = plot;
}
// or insert plot in middle or at end of forest
else
{
plot->next = trailer->next;
trailer->next = plot;
}
// success!
return true;
}
/**
* Deletes a forest (and all of its trees).
* Returns true on success and false on error.
*/
bool rmforest(Forest* f)
{
// ensure source is not NULL
if (f == NULL)
{
return false;
}
// clear forest's trees
while (f->first != NULL)
{
Plot* plot = f->first;
f->first = f->first->next;
rmtree(plot->tree);
free(plot);
}
// free forest
free(f);
// success!
return true;
}