001      /*    Author Malte Pagel    */
002      
003      #include <stdio.h>
004      #include <stdlib.h>
005      #include <time.h>
006      #include <math.h>
007      
008      
009      #define NUM_ELEMENTS 500000
010      #define LIMIT 5000000
011      
012      #define DEBUG_OUTPUT 0
013      
014      
015      
int elements[NUM_ELEMENTS];
016      
017      
struct list_element {
018          
int value;
019          
struct list_element *previous;
020          
struct list_element *next;
021      };
022      
struct list_element *global_first_element;
023      
struct list_element *global_last_element;
024      
struct element_pair {
025          
struct list_element *first;
026          
struct list_element *last;
027      };
028      
029      
030      
void show_elements(int[], int);
031      
void show_list_elements(struct list_element*, struct list_element*);
032      
void show_partially_sorted_list(struct list_element*, struct list_element*, struct list_element*, struct list_element*, struct list_element*);
033      
034      
int std_compare(const void*, const void*);
035      
036      
void fill_elements(int);
037      
038      
039      
struct element_pair reverse_list(struct list_element**, struct list_element**);
040      
struct element_pair surreal_sort(struct list_element**, struct list_element**);
041      
042      
043      
/*        */
044      
045      
void show_elements (int the_elements[], int num) {
046          
int i;
047          for ( 
0numi++ )
048              if ( 
< (num 1) )
049                  
printf("%d, "the_elements[i]);
050              else
051                  
printf("%d"the_elements[i]);
052          
printf("\n");
053      }
054      
void show_list_elements(struct list_elementfirststruct list_elementlast) {
055          
struct list_element *actual first;
056              
057          while ( 
actual != NULL ) {
058              
printf("%d"actual->value);
059              if ( 
actual == last )
060                  break;
061              
printf(", ");
062              
actual actual->next;
063          }
064          
printf("\n");
065      }
066      
void show_partially_sorted_list (struct list_elementfirststruct list_elementlow_leftstruct list_elementlow_rightstruct list_elementhigh_leftstruct list_elementhigh_right) {
067              
068          
struct list_element *actual first;
069          
int special_element 0;
070              
071          while ( 
actual != NULL ) {
072                      
073              if ( 
actual == low_left || actual == high_left )
074                  
special_element 1;
075                      
076              if ( 
special_element )
077                  
printf("(%d)"actual->value);
078              else
079                  
printf("%d"actual->value);
080                      
081              if ( 
actual->next == NULL )
082                  break;
083              if ( !
special_element )
084                  
printf(", ");
085                      
086              if ( 
actual == low_right || actual == high_right )
087                  
special_element 0;
088                      
089              
actual actual->next;
090          }
091          
printf("\n");
092      }
093      
094      
/*        */
095      
096      
int std_compare (const voidvalue1, const voidvalue2) {
097          return (*(
int*)value1 - *(int*)value2);
098      }
099      
100      
/*        */
101      
102      
103      
void fill_elements (int method) {
104              
105          
int idistanceindexaddcountremember;
106          
int indices[NUM_ELEMENTS];
107              
108          
distance LIMIT NUM_ELEMENTS;
109              
110          switch (
method) {
111                      case 
1:
112                              
elements[0] = rand() % distance 1;
113                              for ( 
1NUM_ELEMENTSi++ )
114                                      
elements[i] = elements[1] + (rand() % distance);
115                              break;
116                      case 
2:
117                              
elements[0] = LIMIT - (rand() % distance 1);
118                              for ( 
1NUM_ELEMENTSi++ )
119                                      
elements[i] = elements[1] - (rand() % distance);
120                              break;
121                      case 
3:
122                              for ( 
0NUM_ELEMENTSi++ )
123                                      
elements[i] = (rand() % LIMIT) + 1;
124                              break;
125                      case 
4:
126                              for ( 
0NUM_ELEMENTSi++ )
127                                      
indices[i] = i;
128                              for ( 
count 0count sqrt((double) NUM_ELEMENTS); count++ ) {
129                                      
add rand() % (NUM_ELEMENTS 2) + (NUM_ELEMENTS 4);
130                                      
index rand() % (NUM_ELEMENTS 2) + (NUM_ELEMENTS 4);
131                                      for ( 
0NUM_ELEMENTSi++ ) {
132                                              
remember indices[i];
133                                              if ( 
count == ) {
134                                                      
indices[i] = indices[(add) % NUM_ELEMENTS];
135                                                      
indices[(add) % NUM_ELEMENTS] = remember;
136                                              } else {
137                                                      
indices[i] = indices[(NUM_ELEMENTS add) % NUM_ELEMENTS];
138                                                      
indices[(NUM_ELEMENTS add) % NUM_ELEMENTS] = remember;
139                                              }
140                                      }
141                              }
142                              for ( 
0NUM_ELEMENTSi++ )
143                                      
elements[i] = (indices[i] + 1) * distance;
144                              break;
145          }
146              
147          
global_first_element malloc(sizeof(struct list_element));
148          
global_first_element->value elements[0];
149          
global_first_element->previous NULL;
150              
151          
struct list_element *tmp global_first_element;
152          for ( 
1NUM_ELEMENTSi++ ) {
153              
tmp->next malloc(sizeof(struct list_element));
154              
tmp->next->value elements[i];
155              
tmp->next->previous tmp;
156              
tmp tmp->next;
157          }
158          
tmp->next NULL;
159          
global_last_element tmp;
160      }
161      
162      
/*        */
163      
164      
struct element_pair reverse_list (struct list_element **first_elementstruct list_element **last_element) {
165              
166          
struct list_element *first = *first_element;
167          
struct list_element *last = *last_element;
168              
169          
//struct list_element *before = first->previous;
170          
struct list_element *after last->next;
171              
172          
struct list_element *tmp first;
173          
struct list_element *tmp_next;
174              
175          while ( 
tmp && tmp != after ) {
176              
tmp_next tmp->next;
177              
tmp->next tmp->previous;
178              
tmp->previous tmp_next;
179              
tmp tmp_next;
180          }
181              
182          
//before->next = last;
183          //last->previous = before;
184          //after->previous = first;
185          //first->next = after;
186              
187          
struct element_pair solution;
188              
189          
solution.first last;
190          
solution.last first;
191              
192          return 
solution;
193      }
194      
struct element_pair surreal_sort (struct list_element **firststruct list_element **last) {
195              
196          
struct element_pair solution;
197          
solution.first = *first;
198          
solution.last = *last;
199              
200          
struct list_element *first_element = *first;
201          
struct list_element *last_element = *last;
202          
struct list_element *low_left = *first;
203          
struct list_element *low_right = *first;
204          
struct list_element *high_left = *last;
205          
struct list_element *high_right = *last;
206          
struct list_element *low_tmp NULL;
207          
struct list_element *high_tmp NULL;
208              
209          
first_element->previous NULL;
210          
last_element->next NULL;
211              
212          
int direction_counter;
213          
struct element_pair tmp_solution;
214              
215              
216          if ( 
first_element == last_element )
217              return 
solution;
218          if ( 
first_element->next == last_element ) {
219              if ( 
first_element->value <= last_element->value )
220                  return 
solution;
221              else {
222                  
last_element->previous NULL;
223                  
last_element->next first_element;
224                  
first_element->previous last_element;
225                  
first_element->next NULL;
226                  
solution.first last_element;
227                  
solution.last first_element;
228                  return 
solution;
229              }
230          }
231              
232              
233          if ( 
first_element->value last_element->value ) {
234              
low_tmp first_element->next;
235              
high_tmp last_element->previous;
236              
low_tmp->previous last_element;
237              
last_element->next low_tmp;
238              
high_tmp->next first_element;
239              
first_element->previous high_tmp;
240              
first_element low_tmp->previous;
241              
last_element high_tmp->next;
242              
first_element->previous NULL;
243              
last_element->next NULL;
244                      
245              
low_left first_element;
246              
low_right first_element;
247              
high_left last_element;
248              
high_right last_element;
249          }
250              
251              
252          
/*        */
253              
254          
while ( ) {
255                      
256              
// LEFT SIDE
257              
low_tmp low_right->next;
258                      
259              if ( 
low_tmp == high_left )
260                  break;
261                      
262              if ( 
low_tmp->value >= low_right->value && low_tmp->value <= high_left->value ) {                                                // inside middle; ordered
263                  
low_right low_tmp;
264                  while ( 
low_right->next != high_left && low_right->next->value >= low_right->value && low_right->next->value <= high_left->value )
265                      
low_right low_right->next;
266              } else {
267                  
high_tmp low_tmp;
268                  
direction_counter 0;
269                  if ( 
low_tmp->value low_right->value ) {                                                                                   // small
270                      
if ( low_tmp->value low_left->value ) {                                                                                // very small
271                          
while ( high_tmp->next != high_left && high_tmp->next->value low_left->value ) {
272                              
direction_counter += (high_tmp->next->value high_tmp->value) ? -1;
273                              
high_tmp high_tmp->next;
274                          }
275                                              
276                          
low_tmp->previous->next high_tmp->next;
277                          
high_tmp->next->previous low_tmp->previous;
278                          if ( 
direction_counter )
279                              
tmp_solution reverse_list(&low_tmp, &high_tmp);
280                          else {
281                              
tmp_solution.first low_tmp;
282                              
tmp_solution.last high_tmp;
283                          }
284                          
tmp_solution.last->next first_element;
285                          
first_element->previous tmp_solution.last;
286                          
first_element tmp_solution.first;
287                          
first_element->previous NULL;
288                      } else {                                                                                                                                                                                      
// inside left ordered part
289                          
while ( high_tmp->next != high_left && high_tmp->next->value low_right->value && high_tmp->next->value >= low_left->value )
290                              
high_tmp high_tmp->next;
291                                              
292                          
low_right->previous->next low_right->next;
293                          
low_right->next->previous low_right->previous;
294                          
low_right->next high_tmp->next;
295                          
low_right->next->previous low_right;
296                          
high_tmp->next low_right;
297                          
low_right->previous high_tmp;
298                                              
299                          
low_left low_right;
300                      }
301                  } else {                                                                                                                                                                                              
// high
302                      
if ( low_tmp->value high_right->value ) {                                                                               // very high
303                          
while ( high_tmp->next != high_left && high_tmp->next->value high_right->value ) {
304                              
direction_counter += (high_tmp->next->value high_tmp->value) ? -1;
305                              
high_tmp high_tmp->next;
306                          }
307                                              
308                          
low_tmp->previous->next high_tmp->next;
309                          
high_tmp->next->previous low_tmp->previous;
310                          if ( 
direction_counter )
311                              
tmp_solution reverse_list(&low_tmp, &high_tmp);
312                          else {
313                              
tmp_solution.first low_tmp;
314                              
tmp_solution.last high_tmp;
315                          }
316                          
tmp_solution.first->previous last_element;
317                          
last_element->next tmp_solution.first;
318                          
last_element tmp_solution.last;
319                          
last_element->next NULL;
320                      } else {                                                                                                                                                                                      
// inside right ordered part
321                          
while ( high_tmp->next != high_left && high_tmp->next->value high_left->value && high_tmp->next->value <= high_right->value )
322                              
high_tmp high_tmp->next;
323                                              
324                          
low_tmp->previous->next high_tmp->next;
325                          
high_tmp->next->previous low_tmp->previous;
326                          
high_left->next->previous high_tmp;
327                          
high_tmp->next high_left->next;
328                          
high_left->next low_tmp;
329                          
low_tmp->previous high_left;
330                                              
331                          
high_right high_left;
332                      }
333                  }
334              }
335                      
336              
// RIGHT SIDE
337              
high_tmp high_left->previous;
338                      
339              if ( 
high_tmp == low_right )
340                  break;
341                      
342              
high_tmp high_left->previous;
343                      
344              if ( 
high_tmp->value >= low_right->value && high_tmp->value <= high_left->value ) {                                        // inside middle; ordered
345                  
high_left high_tmp;
346                  while ( 
high_left->previous != low_right && high_left->previous->value <= high_left->value && high_left->previous->value >= low_right->value )
347                      
high_left high_left->previous;
348              } else {
349                  
low_tmp high_tmp;
350                  
direction_counter 0;
351                  if ( 
high_tmp->value low_right->value ) {                                                                            // small
352                      
if ( high_tmp->value low_left->value ) {                                                                         // very small
353                          
while ( low_tmp->previous != low_right && low_tmp->previous->value low_left->value ) {
354                              
direction_counter += (low_tmp->previous->value low_tmp->value) ? -1;
355                              
low_tmp low_tmp->previous;
356                          }
357                                              
358                          
low_tmp->previous->next high_tmp->next;
359                          
high_tmp->next->previous low_tmp->previous;
360                          if ( 
direction_counter )
361                              
tmp_solution reverse_list(&low_tmp, &high_tmp);
362                          else {
363                              
tmp_solution.first low_tmp;
364                              
tmp_solution.last high_tmp;
365                          }
366                          
tmp_solution.last->next first_element;
367                          
first_element->previous tmp_solution.last;
368                          
first_element tmp_solution.first;
369                          
first_element->previous NULL;
370                      } else {                                                                                                                                                                                      
// inside left ordered part
371                          
while ( low_tmp->previous != low_right && low_tmp->previous->value low_right->value && low_tmp->previous->value >= low_left->value  )
372                              
low_tmp low_tmp->previous;
373                                              
374                          
low_tmp->previous->next high_tmp->next;
375                          
high_tmp->next->previous low_tmp->previous;
376                          
low_right->previous->next low_tmp;
377                          
low_tmp->previous low_right->previous;
378                          
high_tmp->next low_right;
379                          
low_right->previous high_tmp;
380                                              
381                          
low_left low_right;
382                      }
383                  } else {                                                                                                                                                                                              
// high
384                      
if ( high_tmp->value high_right->value ) {                                                                       // very high
385                          
while ( low_tmp->previous != low_right && low_tmp->previous->value high_right->value ) {
386                              
direction_counter += (low_tmp->previous->value low_tmp->value) ? -1;
387                              
low_tmp low_tmp->previous;
388                          }
389                                              
390                          
low_tmp->previous->next high_tmp->next;
391                          
high_tmp->next->previous low_tmp->previous;
392                          if ( 
direction_counter )
393                              
tmp_solution reverse_list(&low_tmp, &high_tmp);
394                          else {
395                              
tmp_solution.first low_tmp;
396                              
tmp_solution.last high_tmp;
397                          }
398                          
tmp_solution.first->previous last_element;
399                          
last_element->next tmp_solution.first;
400                          
last_element tmp_solution.last;
401                          
last_element->next NULL;
402                      } else {
403                          while ( 
low_tmp->previous != low_right && low_tmp->previous->value high_left->value && low_tmp->previous->value <= high_right->value )
404                              
low_tmp low_tmp->previous;
405                                              
406                          
high_left->next->previous high_left->previous;
407                          
high_left->previous->next high_left->next;
408                          
high_left->previous low_tmp->previous;
409                          
high_left->previous->next high_left;
410                          
low_tmp->previous high_left;
411                          
high_left->next low_tmp;
412                                              
413                          
high_right high_left;
414                      }
415                  }
416              }
417                      
418          }
419              
420          
/*        */
421              
422          
if ( low_left->previous ) {
423              
tmp_solution surreal_sort(&first_element, &low_left->previous);
424                      
425              
first_element tmp_solution.first;
426              
//first_element->previous = NULL;
427              
tmp_solution.last->next low_left;
428              
low_left->previous tmp_solution.last;
429          }
430              
431          if ( 
high_right->next ) {
432              
tmp_solution surreal_sort(&high_right->next, &last_element);
433                      
434              
last_element tmp_solution.last;
435              
//last_element->next = NULL;
436              
tmp_solution.first->previous high_right;
437              
high_right->next tmp_solution.first;
438          }
439              
440              
441          
solution.first first_element;
442          
solution.last last_element;
443              
444          return 
solution;
445      }
446      
447      
448      
int main (int argc, const char argv[]) {
449              
450          
global_first_element NULL;
451          
global_last_element NULL;
452          
struct element_pair solution;
453              
454          
clock_t startend;
455          
double used_time;
456              
457          
time_t t;
458          
time(&t);
459          
srand((unsigned intt);
460              
461              
462          
char c '?';
463              
464          
char welcome[] = "\t 1 - Ascending\n\t 2 - Decending\n\t 3 - Random\n\t 4 - Cards\n\t q - Quit\n";
465              
466          
printf("\n%s\n"welcome);
467              
468          while ( 
!= '1' && != '2' && != '3' && != '4' && != 'q' && != 'Q' ) {
469              
scanf("%s", &c);
470              if ( 
!= '1' && != '2' && != '3' && != '4' && != 'q' && != 'Q' )
471                  
printf("\nOnce again!\n%s"welcome);
472          }
473              
474          if ( 
== 'q' || == 'Q' )
475              return 
0;
476              
477              
478          
fill_elements(48);
479              
480          
printf("\n");
481              
482              
483          if ( 
DEBUG_OUTPUT )
484              
show_elements(elementsNUM_ELEMENTS);
485          
//show_list_elements(global_first_element, global_last_element);
486              
487          
start clock();
488          
qsort(elementsNUM_ELEMENTSsizeof(int), std_compare);
489          
end clock();
490          
used_time = (float) (end start) / (float) CLOCKS_PER_SEC;
491          if ( !
DEBUG_OUTPUT )
492              
printf("\n\t %d elements sorted using qsort() in %.2f seconds"NUM_ELEMENTSused_time);
493              
494          
start clock();
495          
solution surreal_sort(&global_first_element, &global_last_element);
496          
end clock();
497          
used_time = (float) (end start) / (float) CLOCKS_PER_SEC;
498          if ( !
DEBUG_OUTPUT )
499              
printf("\n\t %d elements sorted using surreal_sort() in %.2f seconds \n\n"NUM_ELEMENTSused_time);
500              
501              
502          
//show_elements(elements, NUM_ELEMENTS);
503          
if ( DEBUG_OUTPUT )
504              
show_list_elements(solution.firstsolution.last);
505              
506              
507          
global_first_element global_first_element->next;
508          while ( 
global_first_element ) {
509              
free(global_first_element->previous);
510              
global_first_element global_first_element->next;
511          }
512          
free(solution.last);
513              
514              
515              
516              
517          return 
0;
518      }
519