4

Hoping I can get a little advice on a sorting method I made.

The purpose of this code is to create a int pointer array and sort the pointers in that array by the contents of regular int array. Then assign values for a different variable based on the location of the original int array.

The strangeness I am experiencing with this code is that the test code which shouldn't effect anything as far as I know... IS actually effecting the contents of my pointers. Perhaps the values aren't changing but the way I'm writing the test code is causing errors.

 //create array
 int c[8] = {3,1,5,7,8,2,6,4};
 //create pointer array
 int *newptr[8];
 for(int k = 0; k<8; k++)
 {
     newptr[k] = &c[k];
 }
//sort pointer array
for(int j = 0; j<8; j++)
{
    for(; j > -1 && *newptr[j] < *newptr[j+1]; j--)
    {
        int *temp = newptr[j+1];
        newptr[j+1] = newptr[j];
        newptr[j] = temp;
    }
}
//set lookuplocation
int lookuplocation;
for(int i = 0; i<8; i++)
{
    cout << *newptr[i];

    if(newptr[i] == &c[0])
    {
        cout << *newptr[i] << endl;

        //If I use endl or \n to test the pointers values I end up with only
        //a part of the correct data. 

        cout << "\nSuccess!\n";
        lookuplocation = 0;
    }
}
//Also for my last test sometimes the first element gets messed up as well
//test arrays
for(int k = 0; k<8; k++)
{
    cout << "Element " << k << ": " << *newptr[k] << endl;
    cout << "Element " << k << ": " << newptr[k] << endl;
}
20
  • 1
    your sorting is messed up Commented Aug 5, 2013 at 7:02
  • Nested loops with the same counter j ? How can it work at all? Commented Aug 5, 2013 at 7:03
  • 1
    Do you need to write the code to sort the array of pointers, or do you need to sort an array of pointers? Please specify which. If you don't need to write your own code, the solution is trivial. Commented Aug 5, 2013 at 7:11
  • 3
    "I wasn't really taught to use them (STL containers) in class." - Of course you weren't, because eveybody knows C++ is best taught by teaching "C with cout" first. ;) Commented Aug 5, 2013 at 9:41
  • 1
    Your code has a bug. In the sorting loop, when j==7 the expression newptr[j+1] accesses an element past the end of the array. Commented Aug 5, 2013 at 15:09

5 Answers 5

10

I figured someone might actually need to sort an array of pointers in a sane way:

#include <iostream>
#include <array>
#include <algorithm>

int main() {
    std::array<int, 8> arr { 3, 5, 4, 1, 2, 7, 6, 8 };
    std::array<int*, 8> p_arr;

    for (unsigned i = 0; i < 8; ++i) {
        p_arr[i] = &arr[i];
    }

    std::sort(p_arr.begin(), p_arr.end(), [](int* a, int* b) { return *a < *b; });

    for (auto i : p_arr) 
        std::cout << *i;
}

The ugly middle loop is totally replace'able by range for over zippped range, but I don't have my own implementation with reference semantics right now, and I am too lazy to check the Boost one.1

Here's a live sample on Coliru.

Also, because I think we should repeat this over and over until newbies understand it:

  • Don't reinvent the sorting wheel (unless it's a toy implementation)
  • Try to avoid using pointers in C++ if reasonably possible.

1This is actually important in order to make sure both ranges (in this case two arrays) have the same length. Different zipping conventions either require the ranges to be of the same length (crashing or throwing otherwise) or fill in the empty data should one of the ranges be too short. While seemingly obvious in such a simple program, be careful in real-world code.

Sign up to request clarification or add additional context in comments.

1 Comment

@user2651901 you should learn Standard Library before pointers.
3

If your array c[n] has for range [1 .. n], you can use the following algorithm which work in O(n) time complexity:

for(int j = 0; j < n; j++)
    while(*newptr[*newptr[j] - 1] != *newptr[j])
        std::swap(newptr[*newptr[j] - 1], newptr[j]);

The idea behind it is to assign the value 1 to the pointer newptr[0], 2 to the pointer newptr[1], ..., and n to the pointer newptr[n-1]. There is no algorithm that is more efficient (especially in C++11, since std::swap will use std::move).

So for int c[8] = {3,1,5,7,8,2,6,4}, you get (disregarding the reference to value table):

1233

Success!
45678


Update: If you want the reverse order:

for(int j = 0; j < n; j++)
    while(*newptr[n - *newptr[j]] != *newptr[j])
        std::swap(newptr[n - *newptr[j]], newptr[j]);

For int c[8] = {3,1,5,7,8,2,6,4}, you get:

8765433

Success!
21

4 Comments

While this does work, it sorts the opposite way which I'm sure can be easily fixed. But my main problem that I'm dealing with is understanding whether or not I can do a comparison of the address of my original int array and the pointers. I'm pretty sure now that is what was messing up my code.
@user2651901: You mean you want the script to sort from 8 to 1 instead of 8 to 1?
yeah 8 to 1 not 1 to 8.
While this has been posted quite a while ago, I think it's necessary to point out that this is not exactly O(n).
1

Popular approach is to implement generic sort function that sorts elements with given comparator, so you can abstract over array elements. There are some ways:

template<typename ElementType, typename CompType>
void sort(ElementType array[], size_t size, CompType cmp);
template<typename ElementType, typename CompType>
void sort(std::vector<ElementType> & array, CompType cmp);
template<typename IteratorType, typename CompType>
void sort(IteratorType first, IteratorType last, CompType cmp);

Last way is preferable because you can abstract over container type too.

Comments

0

Change this first:

for(; j > -1 && *newptr[j] < *newptr[j+1]; j--)

into

for(int i=j; i > -1 && *newptr[i] < *newptr[i+1]; i--)

It seems alot more efficient..

7 Comments

but very confusing. simplicity is more important to me at this point.
it's not, reusing the same j is confusing, it actually might lower the j in your outer loop which is probably not the purpose?
Hmm. Now that I think about it, it does reduce the amount of processing of numbers. It isn't necessary but it is a good idea. Thanks!
@irW "alot" more efficient? link
yes you are right, it won't have a big impact, still it is silly to decrease the j in the outer loop since there is no reason for that. (when I wrote 'alot' I was incorreclty assuming j -> 0 every time)
|
0
void sortList(int* list, const size_t &len)
{
    for(size_t i = 0; i < len; ++i)
    {
        for (size_t j = i+1; j < len; ++j)
        {
            if (list[i] > list[j])
            {
                std::swap(list[i], list[j]);
            }
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.