Page 1 of 2 12 LastLast
Results 1 to 20 of 22

Thread: Sorting a QVector

  1. #1
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Sorting a QVector

    Hi,
    I have created a vector of structs like this:

    Qt Code:
    1. struct Review {
    2. QString title;
    3. QString page;
    4. };
    To copy to clipboard, switch view to plain text mode 

    I filled it with data from a database; now I need to sort alphabetically by title this vector; I made a bubbleSort function:

    Qt Code:
    1. void MagazineWidget::bubbleSort(QVector<Review> vector)
    2. {
    3. bool swap = true;
    4.  
    5. for(int j = 0; swap; j++)
    6. {
    7. swap = false;
    8. for(int k = vector.size()-1; k > j; k--)
    9. {
    10. if(vector.at(k).title < vector.at(k-1).title)
    11. {
    12. Review temp;
    13. temp.title = vector.at(k).title;
    14. temp.page = vector.at(k).page;
    15. vector.at(k).title = vector.at(k-1).title;
    16. vector.at(k).page = vector.at(k-1).page;
    17. vector.at(k-1).title = temp.title;
    18. vector.at(k-1).page = temp.page;
    19. swap = true;
    20. }
    21. }
    22. }
    23. }
    To copy to clipboard, switch view to plain text mode 

    and call it with this statement:

    Qt Code:
    1. QVector<Review> reviews;
    2. // ...
    3. // Filling the vector
    4. // ...
    5. bubbleSort(reviews);
    To copy to clipboard, switch view to plain text mode 

    During compilation I got the following error on lines 15-18:

    Qt Code:
    1. error: passing ‘const QString’ as ‘this’ argument of ‘QString& QString::operator=(const QString&)’ discards qualifiers
    To copy to clipboard, switch view to plain text mode 

    Thanks
    Giuseppe CalÃ

  2. #2
    Join Date
    Mar 2006
    Location
    The Netherlands
    Posts
    300
    Thanks
    9
    Thanked 29 Times in 29 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: Sorting a QVector

    QVector only has a const version of at(). In other words, you can't use QVector::at() as a left-hand value. Use the subscript operator:

    Qt Code:
    1. vector[k].title = vector.at(k-1).title;
    2. vector[k].page = vector.at(k-1).page;
    3. vector[k-1].title = temp.title;
    4. vector[k-1].page = temp.page;
    To copy to clipboard, switch view to plain text mode 

    Also, as it is now, your function only sorts a local copy. You have to pass the parameter by reference.

    Also, Qt already has some sorting algorithms for you. Look at this one.
    "The strength of a civilization is not measured by its ability to wage wars, but rather by its ability to prevent them." - Gene Roddenberry

  3. The following user says thank you to Michiel for this useful post:

    jiveaxe (9th August 2007)

  4. #3
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Sorting a QVector

    Hi Michiel,
    thank you for your post; i have corrected the function with your code and now works great; thanks also for mentioning qSort: now read the manual and give it a try.

    Regards
    Giuseppe CalÃ

  5. #4
    Join Date
    Aug 2007
    Posts
    3
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Sorting a QVector

    Quote Originally Posted by jiveaxe View Post
    Hi Michiel,
    thank you for your post; i have corrected the function with your code and now works great; thanks also for mentioning qSort: now read the manual and give it a try.

    Regards
    Except of already implemented and tested sort implementation, qSort also gives you faster solution with O(n*log(n)) complexity instead of O(n*n) in your case.

  6. #5
    Join Date
    Mar 2006
    Location
    The Netherlands
    Posts
    300
    Thanks
    9
    Thanked 29 Times in 29 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: Sorting a QVector

    Yes, bubblesort is never used in serious applications. It is now mainly used for educational purposes.

    Edit:

    Another thing about your code (if you choose to keep it). You can shave off some lines of code by using struct assignment.

    Qt Code:
    1. Review temp;
    2. temp = vector.at(k);
    3. vector[k] = vector.at(k-1);
    4. vector[k-1] = temp;
    To copy to clipboard, switch view to plain text mode 

    And, well, you can also just use the standard C++ swap() or the Qt qSwap() function. (They're identical. One wonders why Qt has its own version.)

    Qt Code:
    1. qSwap(vector[k], vector[k-1]);
    To copy to clipboard, switch view to plain text mode 
    Last edited by Michiel; 10th August 2007 at 20:32.
    "The strength of a civilization is not measured by its ability to wage wars, but rather by its ability to prevent them." - Gene Roddenberry

  7. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Sorting a QVector

    Quote Originally Posted by jiveaxe View Post
    Hi,
    I have created a vector of structs like this:

    Qt Code:
    1. struct Review {
    2. QString title;
    3. QString page;
    4. };
    To copy to clipboard, switch view to plain text mode 

    I filled it with data from a database; now I need to sort alphabetically by title this vector; I made a bubbleSort function
    How about:

    Qt Code:
    1. struct Review {
    2. QString title;
    3. QString page;
    4. bool operator<(const Review &other) const {
    5. return (title < other.title);
    6. }
    7. };
    To copy to clipboard, switch view to plain text mode 

    and then:

    Qt Code:
    1. QVector<Review> reviews;
    2. //...
    3. qSort(reviews);
    4. // or std::sort(reviews.begin(), reviews.end());
    To copy to clipboard, switch view to plain text mode 

  8. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Sorting a QVector

    Quote Originally Posted by Michiel View Post
    And, well, you can also just use the standard C++ swap() or the Qt qSwap() function. (They're identical. One wonders why Qt has its own version.)
    They are not identical. qSwap() is better than most swap() implementations.

  9. #8
    Join Date
    Mar 2006
    Location
    The Netherlands
    Posts
    300
    Thanks
    9
    Thanked 29 Times in 29 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: Sorting a QVector

    Quote Originally Posted by wysota View Post
    They are not identical. qSwap() is better than most swap() implementations.
    Interesting. How (in)efficient can a swap function be? Does it swap at bit-level using xor or something?
    "The strength of a civilization is not measured by its ability to wage wars, but rather by its ability to prevent them." - Gene Roddenberry

  10. #9
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Sorting a QVector

    Well, I don't know about its performance:
    Qt Code:
    1. template <typename T>
    2. inline void qSwap(T &value1, T &value2)
    3. {
    4. T t = value1;
    5. value1 = value2;
    6. value2 = t;
    7. }
    To copy to clipboard, switch view to plain text mode 
    I think it is compiler dependent. It is up to the compiler to optimize this code.
    Basically, there are 3 memcpy's, since that is what is going on.

    Maybe a good compiler will optimize that using mmx, sse or whatever instruction sets are available.

    Regards

  11. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Sorting a QVector

    Quote Originally Posted by Michiel View Post
    Interesting. How (in)efficient can a swap function be? Does it swap at bit-level using xor or something?
    The trivial implementation of swap is something like:

    Qt Code:
    1. template< typename T> void swap(T& x, T& y){
    2. T tmp = x;
    3. x = y;
    4. y = tmp;
    5. }
    To copy to clipboard, switch view to plain text mode 

    Drawbacks:
    - three operations
    - uses assignment operator that can be quite complex (for example for trivial vector implementation)

    qSwap() tries to be smarter, for instance it can detect if operator=() needs to be used or if it can use memcpy() or similar, thus it is faster for movable types.

  12. #11
    Join Date
    Mar 2006
    Location
    The Netherlands
    Posts
    300
    Thanks
    9
    Thanked 29 Times in 29 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: Sorting a QVector

    Quote Originally Posted by wysota View Post
    The trivial implementation of swap is something like:
    I wasn't thinking of the trivial implementation. Because of exactly the drawbacks you describe.

    Quote Originally Posted by wysota View Post
    qSwap() tries to be smarter, for instance it can detect if operator=() needs to be used or if it can use memcpy() or similar, thus it is faster for movable types.
    operator=() should never be used for a swap operation. Why use deep copies if, after the function call, you still end up with exactly the same dynamic data? A shallow copy only moves the pointers around (and the primitive types). For the swap function this should be enough. And I'd be surprised if the standard C++ implementation did it differently.

    Of course, this is only true for reasonable implementations of operator=(). But one can't assume that operator=() is going to be used in swap(). All that is required after the swap is that X behaves as Y did and Y behaves as X did.
    Last edited by Michiel; 10th August 2007 at 23:28.
    "The strength of a civilization is not measured by its ability to wage wars, but rather by its ability to prevent them." - Gene Roddenberry

  13. #12
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Sorting a QVector

    operator=() should never be used for a swap operation. Why use deep copies if, after the function call, you still end up with exactly the same dynamic data? A shallow copy only moves the pointers around (and the primitive types). For the swap function this should be enough. And I'd be surprised if the standard C++ implementation did it differently.
    But it will use the =() operator if the type T provides it(qSwap is a template function).
    Otherwise it is just a memcpy over the destination.

  14. #13
    Join Date
    Mar 2006
    Location
    The Netherlands
    Posts
    300
    Thanks
    9
    Thanked 29 Times in 29 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: Sorting a QVector

    Quote Originally Posted by marcel View Post
    But it will use the =() operator if the type T provides it(qSwap is a template function).
    Otherwise it is just a memcpy over the destination.
    Exactly. And it should just be a memcpy. When would you want a swap function to use operator=()?
    "The strength of a civilization is not measured by its ability to wage wars, but rather by its ability to prevent them." - Gene Roddenberry

  15. #14
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Sorting a QVector

    When you can't memcpy objects. And you can't memcpy most complex objects... As far as I understand the compiler will only "memcpy" PODs.

    http://doc.trolltech.com/latest/qtgl...CLARE_TYPEINFO
    http://doc.trolltech.com/qq/qq19-containers.html (take a look at the paragraph mentioning Q_DECLARE_TYPEINFO)

    And answering your question about wanting to use an assignment operator for swapping - for instance when you have a class that is to be used in multithreaded environment. Swaping using memcpy() and modifying the object from within another thread at the same time will break it completely. You have to use operator=() there to be certain you're blocking access with mutexes.
    Last edited by wysota; 11th August 2007 at 00:06. Reason: Added some content

  16. #15
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Sorting a QVector

    I can't imagine a reason right now.
    However, even structure assignment is implemented in the language as member by member assignment.

    So, in wysota's example above, no memcpy will occur(although it would work), but the two QString members will be assigned one by one, causing QString:perator=() to intervene.

    Regards

  17. #16
    Join Date
    Mar 2006
    Location
    The Netherlands
    Posts
    300
    Thanks
    9
    Thanked 29 Times in 29 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: Sorting a QVector

    Quote Originally Posted by wysota View Post
    And answering your question about wanting to use an assignment operator for swapping - for instance when you have a class that is to be used in multithreaded environment. Swaping using memcpy() and modifying the object from within another thread at the same time will break it completely. You have to use operator=() there to be certain you're blocking access with mutexes.
    Hm. Yes, I suppose that's true. However, if that is the only reason, deep copies are still being made when they don't have to. You could have a list with 100.000 values that must be copied twice in the name of thread safety.

    If there is another way to isolate the swap operation, things could be much more efficient.
    "The strength of a civilization is not measured by its ability to wage wars, but rather by its ability to prevent them." - Gene Roddenberry

  18. #17
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Sorting a QVector

    If there is another way to isolate the swap operation, things could be much more efficient.
    If you are sure it is doable you can always implement your own using memcpy.

    And answering your question about wanting to use an assignment operator for swapping - for instance when you have a class that is to be used in multithreaded environment. Swaping using memcpy() and modifying the object from within another thread at the same time will break it completely. You have to use operator=() there to be certain you're blocking access with mutexes.
    How is qSwap thread safe?
    You still have to put a lock on the mem locations you want to swap even with qSwap.
    I don't mean about Qt classes that are already thread-safe, but a user class.
    Would one trade performance over implementing locking in the operator=() and not in some other place?
    Last edited by marcel; 11th August 2007 at 00:35.

  19. #18
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Sorting a QVector

    Actually qSwap doesn't use memcpy directly (4.3 beta):
    Qt Code:
    1. template <typename T>
    2. inline void qSwap(T &value1, T &value2)
    3. {
    4. if (!QTypeInfo<T>::isComplex || QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
    5. T t = value1;
    6. value1 = value2;
    7. value2 = t;
    8. } else {
    9. const void * const t = reinterpret_cast<const void * const &>(value1);
    10. const_cast<const void *&>(reinterpret_cast<const void * const &>(value1)) =
    11. reinterpret_cast<const void * const &>(value2);
    12. const_cast<const void *&>(reinterpret_cast<const void * const &>(value2)) = t;
    13. }
    14. }
    To copy to clipboard, switch view to plain text mode 

    I admit I don't understand those spells with casting, but they look smart

    It's not that qSwap is thread safe, it's that you can use such classes with it. You have to care about locking your class on your own. It's a general assumption about using operator=(), not about swapping items.

    Anyway we're highly offtopic here It doesn't really matter if you use qSwap or swap for sorting QVector.

  20. #19
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Sorting a QVector

    Quote Originally Posted by wysota View Post
    Actually qSwap doesn't use memcpy directly (4.3 beta):
    Weird enough. It must have remained a beta .
    I can't really find this implementation anywhere in 4.3.0 ( not beta ).

    I even made small test and stepped in qSwap. The one I posted above is used for all types.

    EDIT:
    I think those casts only switch the base addresses of the variables without actually swapping any memory or calling =() operators.

    Regards
    Last edited by marcel; 11th August 2007 at 11:23.

  21. #20
    Join Date
    Jul 2007
    Posts
    39
    Thanks
    10

    Default Re: Sorting a QVector

    Hi all

    I am trying to sort a QList. I am using a custom type with overloaded < operator but then to check out the source of error, I changed the list to a interger one.

    My code now is just this:
    QList<int> list;
    list << 10 << 5 << 4;
    qsort(list.begin(), list.end());
    I am getting the following error.
    Cannot convert QList<int>::iterator to void* argument for '1' to 'void qsort(void* ,size_t, size_t, int (*) (const void*, const void*))'
    Can anyone suggest what would be the possible error?

Similar Threads

  1. Model sorting vs. selection
    By VlJE in forum Qt Programming
    Replies: 2
    Last Post: 25th October 2006, 16:46
  2. QVector problem
    By kingslee in forum Qt Programming
    Replies: 5
    Last Post: 19th October 2006, 10:42
  3. Column Sorting
    By sumsin in forum Qt Programming
    Replies: 1
    Last Post: 16th June 2006, 07:48
  4. QT4: Sorting in QTreeWidget (subclass)
    By Michiel in forum Qt Programming
    Replies: 21
    Last Post: 29th March 2006, 18:08
  5. [QT4] QTreeView, QAbstractItemModel and sorting
    By KShots in forum Qt Programming
    Replies: 3
    Last Post: 24th March 2006, 20:16

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.