LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-14-2010, 10:58 PM   #1
bvkim
LQ Newbie
 
Registered: Apr 2010
Posts: 23

Rep: Reputation: 15
Question Generic case in C?


As you know that GNU-C provides qsort() function in <cstdlib> in this prototype

Code:
void qsort ( void * base, size_t num, size_t size, int ( * comparator ) ( const void *, const void * ) );
You may know about Selection Sort Algorithm already, I want to write a function to perform Selection Sort but it can apply generally for many type: int, long, float, double... like qsort() above.
How can I do that?
 
Old 05-14-2010, 11:10 PM   #2
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by bvkim View Post
As you know that GNU-C provides qsort() function in <cstdlib> in this prototype

Code:
void qsort ( void * base, size_t num, size_t size, int ( * comparator ) ( const void *, const void * ) );
You may know about Selection Sort Algorithm already, I want to write a function to perform Selection Sort but it can apply generally for many type: int, long, float, double... like qsort() above.
How can I do that?
Rewrite qsort in generic way first - in C++.
 
Old 05-14-2010, 11:18 PM   #3
bvkim
LQ Newbie
 
Registered: Apr 2010
Posts: 23

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by Sergei Steshenko View Post
Rewrite qsort in generic way first - in C++.
No, I don't wanna use C++ template.
I want a pure C curiously, either generic through void* or Macro
 
Old 05-14-2010, 11:24 PM   #4
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by bvkim View Post
No, I don't wanna use C++ template.
I want a pure C curiously, either generic through void* or Macro
If you want a generic type and just one function, in "C" you'll have to specify the type at runtime and use a chain of ifs or 'switch' to acti according to the specified type.

It won't look nice.
 
Old 05-15-2010, 12:17 AM   #5
bvkim
LQ Newbie
 
Registered: Apr 2010
Posts: 23

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by Sergei Steshenko View Post
If you want a generic type and just one function, in "C" you'll have to specify the type at runtime and use a chain of ifs or 'switch' to acti according to the specified type.

It won't look nice.
I'm not looking for whether it is nice or not, I just want to learn to know how to do it.
Would you mind giving the sample on my request above?
 
Old 05-15-2010, 12:48 AM   #6
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by bvkim View Post
I'm not looking for whether it is nice or not, I just want to learn to know how to do it.
Would you mind giving the sample on my request above?
Add a 'type' parameter.

Define a number of macros - like

Code:
#define INT 0
#define LONG 1
#define LONGLONG 2
,

etc.

Then in the rewritten 'qsort' write:

Code:
switch(type)
  {
  INT: <your_code_for_to_sort_ints>
  LONG: <your_code_for_to_sort_ints>
  ...
  }
 
Old 05-15-2010, 12:55 AM   #7
bvkim
LQ Newbie
 
Registered: Apr 2010
Posts: 23

Original Poster
Rep: Reputation: 15
@Sergei: thanks for macro guiding. However, what if my data-type is a structure?
 
Old 05-15-2010, 01:13 AM   #8
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by bvkim View Post
@Sergei: thanks for macro guiding. However, what if my data-type is a structure?
You add a macro per structure you are going to use as array to be sorted element and the corresponding case to 'switch' statement.

Because of questions/issues like this 'qsort' implies a user provided comparison routine. The same approach is used in, for example, Perl WRT its built-in 'sort'.

No program can know beforehand all possible types to be used.
 
Old 05-15-2010, 03:15 AM   #9
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,379

Rep: Reputation: 148Reputation: 148
I'm probably missing some subtle point given that I'm more of a C++ than C programmer but the key to this is the compare function that you pass in. All of the data is provided without having to pass in the type of the data being sorted. You have a pointer to the array, the number of elements and the size of each element.

create a character array that overlays the array passed in
char *a = base;

set up a key for comparison
void * key;
key = (char *)malloc(size); // check this allocation worked

assign the value to be compared in to key
memcpy(key, &a[j*size],size);
Where j is the element you are interested in

repeat for the second element, since a compare will require two element, throw in you appropriate loops and, do a swap on the array when you have found the minimum value using memcpy().

Finally free up all memory allocated, ie the key(s).
 
Old 05-15-2010, 04:06 AM   #10
posixculprit
Member
 
Registered: May 2010
Posts: 136

Rep: Reputation: 42
Why do you need the key in the first place?
 
Old 05-15-2010, 04:14 AM   #11
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,379

Rep: Reputation: 148Reputation: 148
The key is the data item that you use to sort. Technically in a generic algorithm what I called the key is the whole data stored in the array and that could be the key or the key could be a part of that item, or even held elsewhere if the data item is a pointer.

But without a key there would be no way of knowing which item comes before the other and that is delegated to the compare function with two key values passed to it.
 
Old 05-15-2010, 04:22 AM   #12
bvkim
LQ Newbie
 
Registered: Apr 2010
Posts: 23

Original Poster
Rep: Reputation: 15
Problem solved!
I now can make it exactly like qsort() but with selection sort algorithm
Thanks all for helping me so much.
 
Old 05-15-2010, 04:31 AM   #13
posixculprit
Member
 
Registered: May 2010
Posts: 136

Rep: Reputation: 42
What I'm asking is, why can you not do something along these lines:

Code:
void selection_sort(void *base, size_t nmemb, size_t size,
                int (*compar)(const void *, const void*))
{
        unsigned char *p = base;

        for (size_t start = 0; start < nmemb - 1; start++) {
                size_t min = start;

                for (size_t i = start + 1; i < nmemb; i++)
                        if (0 < compar(p + min * size, p + i * size))
                                min = i;

                if (min != start)
                        // swap
        }
 
Old 05-15-2010, 04:35 AM   #14
ArthurSittler
Member
 
Registered: Jul 2008
Distribution: Slackware
Posts: 124

Rep: Reputation: 31
Sorting algorithms in C

The only place where the type of the elements must be used in a sorting function is in the comparison function. Simply using an appropriately constructed comparison function permits the sorting routine to sort any fixed-sized array of fixed-sized objects, whether the sorting key in the object involves integers, floating-point numbers, compiler symbol table entries, or telephone book entries.

The sorting function chooses two elements of the array at each iteration, and puts those two elements in order. The method used to choose which two elements to sort at each step determines what sorting algorithm the sorting function implements.

The sorting function computes the (void *) addresses of the two chosen elements of the array using the (void *) address of the start of the array, the size_t indices of the two elements selected from the size_t number of elements in the array, and the size_t size of an array element.

The sorting function passes these two (void *) addresses of the selected two elements to the comparison routine. Depending on the result of the comparison, the sorting routine may need to swap those two elements.

The swap operation can be implemented in such a way that it needs to know only the size_t size and the (void *) addresses of the two items it needs to swap. The swap operation also needs a temporary storage buffer the size_t size of the array elements. The swap function need not be abstracted as a separate function from the sorting function. It is typically only three lines of code.

Then the sort function selects the next pair of items.

The sort function repeats this process until all items have been compared, swapping items as indicated by the comparison algorithm.

To sort an array of a different type of item, you need only write a comparison function which knows how to compare two items of that type. Separating the comparison function from the sorting function permits functional abstraction of the sorting algorithm from the sorting function so that the same algorithm can be used to sort any sort of items that contain sortable keys.

You can easily change the item selection code to implement other sorting algorithms. If you are sorting more than a few items (a dozen items or so) you should see tremendous performance penalties for using the selection sort compared to quick sort or heap sort algorithms. Insertion sort will become relatively *much* slower than quick sort or heap sort with a thousand items. How many entries are there in a phone book?

Implementing this sorting function in C should give you a clear understanding of how to achieve functional abstraction in C by using pointers to functions.
 
1 members found this post helpful.
Old 05-15-2010, 04:46 AM   #15
bvkim
LQ Newbie
 
Registered: Apr 2010
Posts: 23

Original Poster
Rep: Reputation: 15
@Arthur: yes, u're right. That's what I tried to achieve, and now I can do it ^^!
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
what are initrd.img-2.6.28-11-generic and vmlinuz-2.6.28-11-generic? karuna-bdc Linux - Newbie 11 07-17-2009 05:00 AM
Copying files from case-sensitive Linux to case-insensitive Windows via CIFS? SlowCoder Linux - General 4 05-07-2008 07:03 PM
GART TLB error generic level generic Clydesdale Linux - Software 1 08-13-2007 06:47 PM
GART TLB error generic level generic Clydesdale Linux - Hardware 0 08-13-2007 06:18 PM
Why are all my upper case files being shown as lower case?? [Kernel 2.6.9-1.667 FC3] t3gah Fedora 4 03-11-2005 04:09 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:41 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration