-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathisort2.cc
265 lines (248 loc) · 5.28 KB
/
isort2.cc
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
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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/** @file : isort2.cc
@author Daniel Uber
*/
#include <iostream> // for std::cout
#include <cstdlib> // for rand()
#include <ctime> // for clock
#include <sys/resource.h> // for rlimit
/** singly linked list node structure
*/
struct node {
int value;
node * next;
node(int v) : value(v), next(NULL) {}
};
typedef node * list;
/** insert a single node in order
walk forward until either it's time
to put the item in the list
or you've reached the end
*/
list insert(list &List, node * t){
list head = List;
list prev = NULL;
while(head && t->value > head->value){
prev = head;
head = head->next;
}
if(prev){
prev->next = t;
t->next = head;
}
else {
t->next = head;
List = t;
}
return List;
}
/** insert a number into a list
*/
list insert(list &List, int v){
return List = insert(List, new node(v));
}
/** print items in the list one at a time
then a newline.
*/
void print(list List){
while(List){
std::cout<<List->value<<" ";
List = List->next;
}
std::cout<<"\n";
}
/** insertion sort
a list of one item is sorted
in this case we recursively sort the tail first
and insert in order the node at the head
*/
list isortList(list &List){
if(!(List && List->next))
return List;
//sort tail
List->next = isortList(List->next);
// find a place for head
list tmp = new node(List->value);
list tmp2 = List->next;
delete List;
List = insert(tmp2, tmp);
return List;
}
/** free all memory in nodes */
void empty(list &l){
while(l){
node * tmp = l;
l = l->next;
delete tmp;
}
return;
}
/** add a number to the head of the list */
list push_front(list &List, int v){
list tmp = new node(v);
tmp->next = List;
return List = tmp;
}
/******************************************************/
/** splice: add two lists tail to head
These share cells, and List2's pointer should not be
modified afterward.
not used
*/
list splice(list &List1, list List2){
list t = List1;
if(!t) return List2;
while(t->next)
t = t->next;
t->next = List2;
return List1;
}
/** destructively reverse list
this recycles cells
used in merge
*/
list nreverse(list &L){
list result = NULL;
list t;
while(L){
t = L;
L=L->next;
push_front(result, t->value);
delete t;
}
return L=result;
}
/** non-destructive subsequence generator
makes a copy of data in nodes from start to stop
start and stop are 0 offset similar to array
not used, but working
*/
list subseq(list List, int start, int stop){
list t = NULL;
list result = NULL;
int length = stop - start + 1;
if(length < 0) return NULL;
t = List;
while(start && t){
t = t->next;
start--;
}
while(length && t){
push_front(result, t->value);
t = t->next;
length--;
}
return nreverse(result);
}
/**
nthExists: test if there is an element at n places down
*/
bool nthExists(list List, int n){
if(List && n)
return nthExists(List->next, n-1);
else if (List)
return true;
else
return false;
}
/** merge: given two sorted lists
return a sorted list of the elements of both lists
! this is a terrible idea if these share structure !
*/
list merge(list L1, list L2){
list t1 = L1;
list t2 = L2;
list t3 = NULL;
// we'll add these reversed first, then flip at the end
list result = NULL;
if(!L1)
return L2;
if(!L2)
return L1;
while(t1 && t2)
if(t2->value > t1->value){
t3 = t1;
t1 = t1->next;
push_front(result, t3->value);
delete t3;
} else {
t3 = t2;
t2 = t2->next;
push_front(result, t3->value);
delete t3;
}
while(t1){
t3 = t1;
t1 = t1->next;
push_front(result, t3->value);
delete t3;
}
while(t2){
t3 = t2;
t2 = t2->next;
push_front(result, t3->value);
delete t3;
}
// reverse result and return
return nreverse(result);
}
/* return second part, modify first part */
list split(list List){
list t= List;
list u = List;
while(u && u->next && u->next->next){
t = t -> next;
u = u->next->next;
}
u = t->next;
t->next = NULL;
return u;
}
/** mergesort:
a singleton is sorted,
otherwise split and merge the sorted sublists
*/
list mergesort(list &List){
if(List && List->next){
list t = List;
list u = split(t);
t = mergesort(t);
u = mergesort(u);
List = merge(t,u);
}
return List;
}
/** test the functions above */
int main(){
// an empty list or two
rlimit limit;
clock_t time;
list List = NULL;
int lim = 1;
getrlimit(RLIMIT_STACK, &limit);
limit.rlim_cur=limit.rlim_max;
setrlimit(RLIMIT_STACK, &limit);
for(int p = 0; p < 20; p++){
for(int i = 0; i < lim; i++)
push_front(List, rand() % (2*i + 1));
time = clock();
isortList(List);
time = clock() - time;
// see time(3): POSIX requires 1000000 CLOCKS_PER_SEC
std::cout<<"for "<<lim<<" elements isort took "<<time
<<" microseconds.\n";
empty(List);
List=NULL;
for(int i = 0; i < lim; i++)
push_front(List, rand() % (2*i + 1));
time = clock();
mergesort(List);
time = clock() - time;
// see time(3): POSIX requires 1000000 CLOCKS_PER_SEC
std::cout<<"for "<<lim<<" elements msort took "<<time
<<" microseconds.\n";
empty(List);
List=NULL;
lim *= 2;
}
return 0;
}