Crossings Minimization  1.0
sorting.c
Go to the documentation of this file.
1 /**
2  * @file sorting.c
3  * @brief Interface for functions that perform various sorts. All sorts are
4  * stable.
5  * @author Matthias Stallmann
6  * @date 2009/01/03
7  * $Id: sorting.c 76 2014-07-21 21:10:32Z mfms $
8  */
9 
10 #include<stdio.h>
11 #include<stdlib.h>
12 #include<stdbool.h>
13 #include<string.h> /* memcpy() */
14 
15 #include"sorting.h"
16 #include"graph.h"
17 
18 /**
19  * Performs an insertion sort using the same argument types as qsort
20  * @return true if the original order has changed
21  */
22 static bool insertion_sort(void *base, size_t nmemb, size_t size,
23  int (*compar)(const void *, const void *)) {
24  bool changed = false;
25  // used to store the item to be inserted
26  void * tmp = malloc(size);
27  int i = 1;
28  for( ; i < nmemb; i++ ) {
29  // 1. insert the A[i] among A[0],...,A[i-1]
30  // (a) copy A[i] into tmp
31  memcpy( tmp, base + i * size, size );
32  // (b) find largest j for which A[j] <= tmp (or -1 if none exists),
33  // shifting elements to the right as you go
34  int j = i - 1;
35  while( j >= 0 && compar( tmp, base + j * size) < 0 ) {
36  changed = true;
37  memcpy( base + (j + 1) * size, base + j * size, size );
38  j--;
39  }
40 
41  // (c) copy tmp into A[i+1]
42  memcpy( base + (j + 1) * size, tmp, size );
43  }
44  free( tmp );
45  return changed;
46 }
47 
48 /**
49  * Performs an "unstable" insertion sort using the same argument types as
50  * qsort; unstable means that elements with equal keys will be put in reverse
51  * of their original order
52  * @return true if the original order has changed
53  */
54 static bool unstable_insertion_sort(void *base, size_t nmemb, size_t size,
55  int (*compar)(const void *, const void *)) {
56  bool changed = false;
57  // used to store the item to be inserted
58  void * tmp = malloc(size);
59  int i = 1;
60  for( ; i < nmemb; i++ ) {
61  // 1. insert the A[i] among A[0],...,A[i-1]
62  // (a) copy A[i] into tmp
63  memcpy( tmp, base + i * size, size );
64  // (b) find largest i for which A[i] <= tmp (or -1 if none exists),
65  // shifting elements to the right as you go
66  int j = i - 1;
67  while( j >= 0 && compar( tmp, base + j * size) <= 0 ) {
68  changed = true;
69  memcpy( base + (j + 1) * size, base + j * size, size );
70  j--;
71  }
72 
73  // (c) copy tmp into A[i+1]
74  memcpy( base + (j + 1) * size, tmp, size );
75  }
76  free( tmp );
77  return changed;
78 }
79 
80 /**
81  * Comparison function to be used by qsort or insertion_sort to compare the
82  * weights of two nodes. Assumes that each array element is a pointer to a
83  * node. Insertion sort is preferred in most cases because it is stable (and
84  * usually does not increase the asymptotic time).
85  */
86 static int compare_weights( const void * ptr_i, const void * ptr_j ) {
87  Nodeptr * entry_ptr_i = (Nodeptr *) ptr_i;
88  Nodeptr * entry_ptr_j = (Nodeptr *) ptr_j;
89  Nodeptr node_i = * entry_ptr_i;
90  Nodeptr node_j = * entry_ptr_j;
91  if( node_i->weight > node_j->weight ) return 1;
92  else if( node_i->weight < node_j->weight ) return -1;
93  else return 0;
94 }
95 
96 /**
97  * Comparison function to be used by qsort to compare degrees of nodes.
98  */
99 static int compare_degrees( const void * ptr_i, const void * ptr_j ) {
100  Nodeptr * entry_ptr_i = (Nodeptr *) ptr_i;
101  Nodeptr * entry_ptr_j = (Nodeptr *) ptr_j;
102  Nodeptr node_i = * entry_ptr_i;
103  Nodeptr node_j = * entry_ptr_j;
104  int node_i_degree = node_i->up_degree + node_i->down_degree;
105  int node_j_degree = node_j->up_degree + node_j->down_degree;
106  if( node_i_degree > node_j_degree ) return 1;
107  else if( node_i_degree < node_j_degree ) return -1;
108  else return 0;
109 }
110 
111 /**
112  * Comparison function to be used by qsort to compare the weights of two
113  * nodes. Assumes that each array element is a pointer to a node.
114  */
115 static int compare_down_edges( const void * ptr_i, const void * ptr_j ) {
116  Edgeptr * entry_ptr_i = (Edgeptr *) ptr_i;
117  Edgeptr * entry_ptr_j = (Edgeptr *) ptr_j;
118  Edgeptr edge_i = * entry_ptr_i;
119  Edgeptr edge_j = * entry_ptr_j;
120  if( edge_i->down_node->position > edge_j->down_node->position ) return 1;
121  else if( edge_i->down_node->position < edge_j->down_node->position )
122  return -1;
123  else return 0;
124 }
125 
126 /**
127  * Comparison function to be used by qsort to compare the weights of two
128  * nodes. Assumes that each array element is a pointer to a node.
129  */
130 static int compare_up_edges( const void * ptr_i, const void * ptr_j ) {
131  Edgeptr * entry_ptr_i = (Edgeptr *) ptr_i;
132  Edgeptr * entry_ptr_j = (Edgeptr *) ptr_j;
133  Edgeptr edge_i = * entry_ptr_i;
134  Edgeptr edge_j = * entry_ptr_j;
135  if( edge_i->up_node->position > edge_j->up_node->position ) return 1;
136  else if( edge_i->up_node->position < edge_j->up_node->position )
137  return -1;
138  else return 0;
139 }
140 
141 void updateAllPositions( void )
142 {
143  for( int i = 0; i < number_of_layers; i++ )
144  {
145  updateNodePositions( i );
146  }
147 }
148 
149 void updateNodePositions( int layer )
150 {
151  Layerptr layerptr = layers[layer];
152  int i = 0;
153  for( ; i < layerptr->number_of_nodes; i++ )
154  {
155  layerptr->nodes[i]->position = i;
156  }
157 }
158 
159 void layerSort( int layer )
160 {
161  Layerptr layer_ptr = layers[ layer ];
162 #ifdef DEBUG
163  printf( "before layerSort: ");
164  for ( int i = 0; i < layer_ptr->number_of_nodes; i++ ) {
165  printf( "%3d/%3.1f" , layer_ptr->nodes[i]->id, layer_ptr->nodes[i]->weight );
166  }
167  printf( "\n" );
168 #endif
169  insertion_sort( layer_ptr->nodes, layer_ptr->number_of_nodes,
170  sizeof( Nodeptr ), compare_weights );
171 #ifdef DEBUG
172  printf( "after layerSort: ");
173  for ( int i = 0; i < layer_ptr->number_of_nodes; i++ ) {
174  printf( "%3d/%3.1f" , layer_ptr->nodes[i]->id, layer_ptr->nodes[i]->weight );
175  }
176  printf( "\n" );
177 #endif
178  updateNodePositions( layer );
179 }
180 
181 void layerUnstableSort( int layer )
182 {
183  Layerptr layer_ptr = layers[ layer ];
184  unstable_insertion_sort( layer_ptr->nodes, layer_ptr->number_of_nodes,
185  sizeof( Nodeptr ), compare_weights );
186  updateNodePositions( layer );
187 }
188 
189 void layerQuicksort( int layer )
190 {
191  Layerptr layer_ptr = layers[ layer ];
192  qsort( layer_ptr->nodes, layer_ptr->number_of_nodes,
193  sizeof( Nodeptr ), compare_weights );
194  updateNodePositions( layer );
195 }
196 
197 /**
198  * Sort the array of edges by the positions of the nodes on the lower layer
199  */
200 void sortByDownNodePosition( Edgeptr * edge_array, int num_edges )
201 {
202  insertion_sort( edge_array, num_edges, sizeof(Edgeptr),
204 }
205 
206 /**
207  * Sort the array of edges by the positions of the nodes on the upper layer
208  */
209 void sortByUpNodePosition( Edgeptr * edge_array, int num_edges )
210 {
211  insertion_sort( edge_array, num_edges, sizeof(Edgeptr),
213 }
214 
215 void sortByDegree( Nodeptr * node_array, int num_nodes )
216 {
217  qsort( node_array, num_nodes, sizeof(Nodeptr), compare_degrees );
218 }
219 
220 /* [Last modified: 2014 07 21 at 18:21:49 GMT] */
Nodeptr up_node
Definition: graph.h:98
int id
Definition: graph.h:64
Layerptr * layers
Definition: graph_io.c:31
int number_of_nodes
Definition: graph.h:115
static int compare_down_edges(const void *ptr_i, const void *ptr_j)
Definition: sorting.c:115
int position
Definition: graph.h:73
static int compare_up_edges(const void *ptr_i, const void *ptr_j)
Definition: sorting.c:130
Interface for functions that perform various sorts. All sorts are stable.
static bool unstable_insertion_sort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))
Definition: sorting.c:54
int up_degree
Definition: graph.h:74
void updateAllPositions(void)
Definition: sorting.c:141
static bool insertion_sort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))
Definition: sorting.c:22
void sortByDegree(Nodeptr *node_array, int num_nodes)
Definition: sorting.c:215
void layerUnstableSort(int layer)
Definition: sorting.c:181
double weight
Definition: graph.h:82
int down_degree
Definition: graph.h:75
Definition of data structures and access functions for a layered graph.
void sortByUpNodePosition(Edgeptr *edge_array, int num_edges)
Definition: sorting.c:209
void layerSort(int layer)
Definition: sorting.c:159
static int compare_degrees(const void *ptr_i, const void *ptr_j)
Definition: sorting.c:99
Nodeptr * nodes
Definition: graph.h:116
Nodeptr down_node
Definition: graph.h:99
int number_of_layers
Definition: graph_io.c:28
void sortByDownNodePosition(Edgeptr *edge_array, int num_edges)
Definition: sorting.c:200
static int compare_weights(const void *ptr_i, const void *ptr_j)
Definition: sorting.c:86
void layerQuicksort(int layer)
Definition: sorting.c:189
void updateNodePositions(int layer)
Definition: sorting.c:149