// swap two integer elements inline void exch(int &a, int &b) { int t = a; a = b; b = t; } // sort an array of integers using bubble sort void bsort(int data[], int N) { int p, i; for(p=N-1;p>0;p--) for(i=0;i<p;i++) if( data[i] > data[i+1] ) exch(data[i], data[i+1]); }
Our question is: what do we need to change to sort not an array of integers, but an array or floating point numbers? And the answer is very simple - all we need to do is to change the data type from int to double.
// swap two floating point elements inline void exch(double &a, double &b) { double t = a; a = b; b = t; } // sort an array of floating point numbers using bubble sort void bsort(double data[], int N) { int p, i; for(p=N-1;p>0;p--) for(i=0;i<p;i++) if( data[i] > data[i+1] ) exch(data[i], data[i+1]); }
What do we need to do to sort an array of character? Same thing - just change the data type from int to char.
What do we do if we need to sort an array of C-strings? This case is a little bit more difficult, because it is not enough to change the data type from int to char*. The small problem is - the comparison operation is not defined for this type of data. More exactly, it is defined, but it compares addresses not the strings located at these addresses. To overcome this problem we need to use a special comparing function named strcmp() that takes two strings and returns a positive number if the first string is greater than the second, zero if they are equal, and a negative number if the first is less than the second. So, we need to do two things:
Now let's consider a more general question. What do we need to do if we need to sort an array of some structures, for example
struct Record { int ssn; char fname[32]; char lname[32]; };To sort this kind of data we of course need to consider an array of Record and we also need an appropriate comparison operator. That is, we still need to make the same modifications, that actually didn't modify the sorting method itself, but require us to make these little modifications to the functions.
// swaps two element of any type template <class Element> inline void exch(Element &a, Element &b) { Element t = a; a = b; b = a; }Basically this construction tells the compiler that the exch() function knows how to swap two elements of any type. We can rewrite the sort function the similar way:
// sort an array of element of any type using bubble sort template <class Element> void bsort(Element data[], int N) { int p, i; for(p=N-1;p>0;p--) for(i=0;i<p;i++) if( data[i] > data[i+1] ) exch(data[i], data[i+1]); }Now we are done. The new function can sort array of elements of any data type, but we need to be sure that the comparison operator(s) we use inside the function are defined for the data type we use.
For example, if we need to sort an array of the structures Record mentioned earlier, we need to define the comparison operator > for those structures. We can define this operator like this
bool operator>(const Record &a, const Record &b) { return a.ssn > b.ssn; }We can similarly define operators <, >=, etc. Once we defined the operator we can use the new template function to sort an array of Records:
Record *data = new Record[N];
// get some data into the array
bsort(data, N);
Please find the complete example here.
|
|
|
||||||||||||||||||||||||||||||||||||
As you can see from the table the runtime grows as well as the size of the string part of the structure grows. (In the notation 4+256 4 is the size of the integer part and 256 is the size of the strong part.) Since we are using the Bubble sort method, the number of comparison stays the same and always equal to N*(N-1)/2. Because the price of each comparison also stays the same (we use only the integer part of the structure to compare two elements and we pass elements by reference to the comparison operator), we can conclude that the price of exchange grows up.
To avoid the exchanging those big elements of the arrays we will use the idea of index. We will create a separate array of integers index[], such that the element index[i] will contain the number of the right spot for the element data[i]. During the sorting process we will swap only the indexes; that is, elements of the original array data[] will b used only for comparisons. Thus, the initial picture will look like
class Index { private: int value; public: TIndex() { value=0; }; TIndex(int v) { value=v; }; operator =(int v) { return (value=v); }; operator int() const { return value; }; };As you can see, the Index element contains nothing but an integer value. This integer value will contain the number of the element in the original array data[]. For this class we defined two constructors and we also defined two operators:
Index ind = 5;
Index ind = 5;
if( data[ind] < ... )
Now we need to recall that when we compare two elements from the index array (e.g. elements 0 and 1 from pictures), we actually need to compare the corresponding elements from the array data[]. In other words, we have to define comparisons operators for the new type Index as something like
// Remember: when comparing two elements of the Index type we are NOT interested // in comparing the values of these Index elements, instead we have to compare // the corresponding records in the array data[] bool operator>(const Index &i, const Index &j) { return data[i] > data[j]; }
Now we are ready to sort the indexes instead of the real data records. The only thing we need to do is the initialization of Index array:
// initialize the index array Index *index = new Index[N]; for(i=0;i<N;i++) index[i] = i; // sort the array of indexes bsort(index, N); // print the data[] array back in the sorted order for(i=0;i<N;i++) cout<<data[ index[i] ];
If we measure runtime of the index sorting, then we can see that the time doesn't really depend now on the size of the data elements:
|
|
|
||||||||||||||||||||||||||||||||||||
Since the index array contains all information about the right order of the elements in the data array, we can use that information to rearrange the array for just one pass through the data array. The algorithm that does it is simple to explain. Since index[i] contains the index of the element that has to take position i in the array data[], then to place all elements at their places, we need