LinuxQuestions.org
Help answer threads with 0 replies.
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 06-19-2023, 03:47 AM   #1
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Rep: Reputation: 4
Quicksort algorithm's incomplete implementation in book, in the C language.


Want to generate a complete code to the program for Quicksort code, given incomplete in the book: Algorithms in a nutshell, by George T. Heineman.
The book states the below parts, leaving out the main(), cmp(), selectPivotIndex functions' implementation to the user.
Code:
void sortPointers(void **vals, int total_elems, int(*cmp)(const void *, const void *))
{
    do_qsort(vals, cmp, 0, total_elems-1);
}

void do_qsort(void **ar, int(*cmp)(const void *, const void *), int left, int right)
//left is for the start/left index position in the array/sub-array. Similarly, for the right variable.
{
   int pivotIndex;
   if(right<=left) return;
   
   //partition
   pivotIndex = selectPivotIndex(ar, left, right);
   pivotIndex = partition(ar, cmp, left, right, pivotIndex);

   if(pivotIndex - 1 - left<= minSize) //to have a lesser time complexity method, for lesser size of the input array/sub-array.
       insertion(ar, cmp, left, pivotIndex-1);
   else
       do_qsort(ar, cmp, left, pivotIndex-1);
   if (right - pivotIndex -1 <= minSize)
       insertion(ar, cmp, pivotIndex+1, right);
   else do_qsort(ar, cmp, pivotIndex+1, right);
}

/*partition ar{left, right] around a given pivot element, ar[pivotIndex], in linear time; by storing pivot into its pivot location.
The location of pivot, is given in store , s.t. all ar[left, store) <= pivot, and all ar[store+1, right] > pivot. */
int partition(void **ar, int(* cmp)(const void *, const void *), int left, int right, int pivotIndex)
{
   int idx, store;
   void *pivot = ar[pivotIndex];

   /*move pivot to the end of the array*/
   void *tmp = ar[right];
   ar[right] = ar[pivotIndex];
   ar[pivotIndex] = tmp;

   //all values sorted in two sub-arrays, i.e. <= pivot, and > pivot. The values <= pivot are moved to front of the (sub)array, & pivot inserted just after them.
   store = left;
   for(idx = left; idx < right; idx++)
   {
      if(cmp(ar[idx], pivot) <= 0)
      { 
          tmp = ar[idx]; ar[idx] = ar[store];  ar[store] = tmp;  store++;
      }
   }

   tmp = ar[right]; ar[right] = ar[store]; ar[store] = tmp;
   return store;
}
Will ask few question, in a sequential manner - one at a time, else risk adding to confusion.

The use of: void **vals, as parameter for passing array, seems confusing to me; and request what is the reason for using a double indirection pointer.

I mean the job can be done by a single indirection pointer too, then why was a double indirection pointer needed?

Last edited by ajiten; 06-19-2023 at 03:57 AM.
 
Old 06-19-2023, 04:54 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,866
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
When you need to access the individual pointers within the pointer-array, you can write simply:
Code:
void do_qsort(void **ar, int(*cmp)(const void *, const void *), int left, int right) {
  ar[left] -- the first pointer to work with
  ar[right] -- the last pointer to work with
}
Otherwise you should write:
Code:
void do_qsort(void *ar, int(*cmp)(const void *, const void *), int left, int right) {
  ((void **)ar)[left] -- the first pointer to work with
  ((void **)ar)[right] -- the last pointer to work with
}
Here is a synonym for the original:
Code:
void do_qsort(void *ar[], int(*cmp)(const void *, const void *), int left, int right) {
Another:
Code:
typedef void *AnyPtr;
void do_qsort(AnyPtr ar[], int(*cmp)(const AnyPtr, const AnyPtr), int left, int right) {

Last edited by NevemTeve; 06-19-2023 at 04:55 AM.
 
1 members found this post helpful.
Old 06-19-2023, 05:11 AM   #3
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,863

Rep: Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311
Quote:
Originally Posted by ajiten View Post
The use of: void **vals, as parameter for passing array, seems confusing to me; and request what is the reason for using a double indirection pointer.

I mean the job can be done by a single indirection pointer too, then why was a double indirection pointer needed?
This is the usage of strict types.
void **vals means: vals is a pointer, and the location (where it points) contains also a pointer.
So you declare: vals is a pointer to a pointer

From the other hand: void *vals means vals is just a pointer, but we don't know anything about that location (if it points to a string, integer or what?).
 
Old 06-19-2023, 06:52 AM   #4
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
Quote:
Originally Posted by pan64 View Post
This is the usage of strict types.
void **vals means: vals is a pointer, and the location (where it points) contains also a pointer.
So you declare: vals is a pointer to a pointer

From the other hand: void *vals means vals is just a pointer, but we don't know anything about that location (if it points to a string, integer or what?).
But, I thought that the array pointed to by vals, gives the start location of the array; and the array itself contains the integers.
Seems, the book is using an array of pointers instead; and those pointers in different locations of the array, point to integers.
 
Old 06-19-2023, 07:00 AM   #5
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
Quote:
Originally Posted by NevemTeve View Post
When you need to access the individual pointers within the pointer-array, you can write simply:
Code:
void do_qsort(void **ar, int(*cmp)(const void *, const void *), int left, int right) {
  ar[left] -- the first pointer to work with
  ar[right] -- the last pointer to work with
}
Otherwise you should write:
Code:
void do_qsort(void *ar, int(*cmp)(const void *, const void *), int left, int right) {
  ((void **)ar)[left] -- the first pointer to work with
  ((void **)ar)[right] -- the last pointer to work with
}
Here is a synonym for the original:
Code:
void do_qsort(void *ar[], int(*cmp)(const void *, const void *), int left, int right) {
Another:
Code:
typedef void *AnyPtr;
void do_qsort(AnyPtr ar[], int(*cmp)(const AnyPtr, const AnyPtr), int left, int right) {
Is it a must to have an array of pointers?
It seems from your answer that an array of integers, is not considered in the functions given; or an array of integers is itself an array of pointers!
Am confused as never thought either of the two options to be true, i.e. neither am clear that the given functions operate on an array of pointers; or the second option, which is a fundamental question - i.e. if the array of integers, is implemented as an array of pointers?

Last edited by ajiten; 06-19-2023 at 07:04 AM.
 
Old 06-19-2023, 07:08 AM   #6
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,897

Rep: Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019
Imagine that instead of ints, you're sorting a bunch of large data structures. That's a lot of data to be swapping back and forth, so it makes sense to take the approach of sorting an index array of pointers to those objects rather than throwing the objects themselves about. That said you will need the unsorted index to exist before you start, but in most real-world cases, your code most likely already has one for other reasons.
 
Old 06-19-2023, 07:46 AM   #7
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
Quote:
Originally Posted by GazL View Post
Imagine that instead of ints, you're sorting a bunch of large data structures. That's a lot of data to be swapping back and forth, so it makes sense to take the approach of sorting an index array of pointers to those objects rather than throwing the objects themselves about. That said you will need the unsorted index to exist before you start, but in most real-world cases, your code most likely already has one for other reasons.
Fine, but the need to pass the comparator function: cmp, in all the 3 functions is unclear. Was it really needed, or just the partition function can call the cmp function, with no need for passing it as a parameter, to any of the given 3 functions?
Next, is unclear why the sortPointers function is being used? Its use seems redundant, and unnecessary to me, and just the function do_qsort should be directly called by the main().
 
Old 06-19-2023, 08:06 AM   #8
Guttorm
Senior Member
 
Registered: Dec 2003
Location: Trondheim, Norway
Distribution: Debian and Ubuntu
Posts: 1,453

Rep: Reputation: 447Reputation: 447Reputation: 447Reputation: 447Reputation: 447
Hi

I agree the void ** parameter is a bit confusing. And it doesn't allow other things than pointers to be sorted. I searched, and this is a little better:

https://www.geeksforgeeks.org/generi...lgorithm-in-c/

Here they cast void* to char* so we can do "math" with the pointers. This allows sorting arrays of anything - not just pointers. Notice they also have a function for swap - you need it for big structures.

But you still need a comparison function. It has 2 pointers as parameters. I don't think its possible to make generic functions taking parameters without a type. And it wouldn't always for big structures.
 
1 members found this post helpful.
Old 06-19-2023, 08:44 AM   #9
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,863

Rep: Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311
Quote:
Originally Posted by ajiten View Post
Fine, but the need to pass the comparator function: cmp, in all the 3 functions is unclear. Was it really needed, or just the partition function can call the cmp function, with no need for passing it as a parameter, to any of the given 3 functions?
Next, is unclear why the sortPointers function is being used? Its use seems redundant, and unnecessary to me, and just the function do_qsort should be directly called by the main().
sortPointers is just a helper function.
It needs a list of pointers and a comparator function and will only call do_qsort. Obviously you can call it directly, without sortPointers.
 
1 members found this post helpful.
Old 06-19-2023, 09:35 AM   #10
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
yeah that's show you how to do things books for you, they're incomplete, you'd probably have better luck googling it

https://hackr.io/blog/quick-sort-in-c
https://www.geeksforgeeks.org/quick-sort/

Last edited by BW-userx; 06-19-2023 at 09:38 AM.
 
1 members found this post helpful.
Old 06-19-2023, 10:21 AM   #11
EdGr
Member
 
Registered: Dec 2010
Location: California, USA
Distribution: I run my own OS
Posts: 998

Rep: Reputation: 470Reputation: 470Reputation: 470Reputation: 470Reputation: 470
Sorting arrays of pointers covers 95% of cases (actual count, not a made-up statistic).

A double indirection allows the same parameters to be passed to the swap and comparison functions if one has both.
Ed
 
Old 06-19-2023, 11:21 AM   #12
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,863

Rep: Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311
Quote:
Originally Posted by EdGr View Post
Sorting arrays of pointers covers 95% of cases (actual count, not a made-up statistic).

A double indirection allows the same parameters to be passed to the swap and comparison functions if one has both.
Ed
Yes, usually we have chained list of pointers to structs. Or just an array of pointers to structs.
And we just reorder the pointers, not the structs themselves.
 
Old 06-19-2023, 08:25 PM   #13
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
Quote:
Originally Posted by NevemTeve View Post
When you need to access the individual pointers within the pointer-array, you can write simply:
...
[/code]
Please tell why the pointer to the comparator function need be passed as a parameter, in all of the book's functions.

If possible give an smallish example, for emphasizing.

Last edited by ajiten; 06-19-2023 at 08:31 PM.
 
Old 06-19-2023, 10:35 PM   #14
EdGr
Member
 
Registered: Dec 2010
Location: California, USA
Distribution: I run my own OS
Posts: 998

Rep: Reputation: 470Reputation: 470Reputation: 470Reputation: 470Reputation: 470
Passing the compare function as a parameter makes the C library quicksort generic. A fully generic quicksort would also be passed a swap function.
Ed
 
1 members found this post helpful.
Old 06-20-2023, 01:18 AM   #15
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,863

Rep: Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311
this is all about to have a generic solution. The implemented qsort knows nothing about the structure of the data behind the pointers, therefore you need to pass a list (of pointers) to it and a comparator function which knows exactly how can be the real data evaluated (compared) using those pointers.
The sorting algorithm itself is implemented in the qsort function and the real data type, data structure is completely irrelevant here.
Obviously you can do that in one single function, with embedded comparator functionality, without real cmp function, this is also implemented and used in special cases (for example when the speed is very important).
 
  


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
qsort vs 'Magnetica' Quicksort Sanmayce Programming 19 10-09-2022 01:19 AM
Can't set signature algorithm when using tpm2_import : Signature algorithm is null with error hash avertyr Linux - Software 2 05-23-2022 02:21 AM
[SOLVED] MD5 Algorithm Implementation gfmtech05 Programming 3 04-28-2011 08:06 AM
implementation of RSA algorithm in C / C++ rupa sarda Programming 1 08-02-2010 11:12 AM
token bucket algorithm vs Leaky bucket algorithm xeon123 Linux - Networking 2 03-26-2007 04:57 AM

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

All times are GMT -5. The time now is 11:37 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