PDA

View Full Version : Sorting using qSort(), - if QList contains POINTERS



joseph
10th October 2007, 06:00
Hi guys,


How to use qSort() if the QList contains pointers like this...


QList < double* > _doubleList;
// this is for simple easyness , you can give QList<employee*>

_doubleList .append( new( 2.22) );
_doubleList .append( new( 1.22) );
_doubleList .append( new( 4.22) );
_doubleList .append( new( 3.22) );

qSort( _doubleList ); // This code will not sort the data properly


while using the above "_doubleList" the data is not sorting .
But if am using the list like this ...




QList < double > _doubleList;
// this is for simple easyness , you can give QList<employee*>

_doubleList .append( 2.22 );
_doubleList .append( 1.22 );
_doubleList .append( 4.22 );
_doubleList .append( 3.22 );

qSort( _doubleList ); // This code WILL SORT the data properly




please tell me how to sort a QList which contains pointers.
thanks in advance

ChristianEhrlicher
10th October 2007, 06:42
You have to implement your own lessThan operator like shown here:

http://doc.trolltech.com/4.3/qtalgorithms.html#qSort-2

joseph
10th October 2007, 09:54
can anybody help me to sort the following code.
My intention is to sort the sudent object in assending order( based on the _rollNo ).


class Student
{
public:
Student()
{ cout<<"\n" << __FUNCTION__; }
Student(int roolNo ):_rolNo( roolNo )
{ cout<<"\n" << __FUNCTION__; }
~Student()
{ cout<<"\n" << __FUNCTION__; }
bool toAssending( Student & s1 , Student & s2 )
{
cout<<"\n" << __FUNCTION__;
return s1.getRollNo() < s2.getRollNo();
}
int getRollNo()
{
return _rolNo;
}
private :
int _rolNo;

};

int main()
{

QList<Student*> studentList ;
studentList.append( new Student(2) );
studentList.append( new Student(4) );
studentList.append( new Student(3) );
studentList.append( new Student(1) );
studentList.append( new Student(5) );
QListIterator<Student*> it( studentList );
Student* val = 0;

cout<<"\n ****** Before SORT ***** " ;
while( it.hasNext() )
{
val = it.next();
cout<<"\n" << val->getRollNo();

}

qSort( studentList.begin() , studentList.end(), toAssending ); // please correct syntax if am wrong

cout<<"\n ****** After SORT ***** " ;
QListIterator<Student*> it_1( studentList );
Student* val_1 = 0;
while( it_1.hasNext() )
{
val_1 = it_1.next();
cout<<"\n" << val_1->getRollNo();
}

qDeleteAll( studentList );



return 0;
}



thanks

jpn
10th October 2007, 10:04
Make toAssending() a non-member function.


class Student
{
...
};

bool toAssending( const Student & s1 , const Student & s2 )
{
cout<<"\n" << __FUNCTION__;
return s1.getRollNo() < s2.getRollNo();
}

int main()
{
...
qSort( studentList.begin() , studentList.end(), toAssending );
...
}

joseph
10th October 2007, 10:22
jpn,

I have tried the same code its not working. i am getting compilation error.
here is my code


class Student
{
public:
Student()
{ cout<<"\n" << __FUNCTION__; }
Student(int roolNo ):_rolNo( roolNo )
{ cout<<"\n" << __FUNCTION__; }
~Student()
{ cout<<"\n" << __FUNCTION__; }
/*
bool toAssending( Student & s1 , Student & s2 )
{
cout<<"\n" << __FUNCTION__;
return s1.getRollNo() < s2.getRollNo();
}*/
int getRollNo() const
{
return _rolNo;
}
private :
int _rolNo;

};

bool toAssending( const Student & s1 , const Student & s2 )
{
cout<<"\n" << __FUNCTION__;
return s1.getRollNo() < s2.getRollNo();
}

int main()
{
QList<Student*> studentList ;
studentList.append( new Student(2) );
studentList.append( new Student(4) );
studentList.append( new Student(3) );
studentList.append( new Student(1) );
studentList.append( new Student(5) );
QListIterator<Student*> it( studentList );
Student* val = 0;
cout<<"\n ****** Before SORT ***** " ;
while( it.hasNext() )
{
val = it.next();
//cout<<"\n" << val;
cout<<"\n" << val->getRollNo();

}

qSort( studentList.begin() , studentList.end(), toAssending ); //here am using the global function. instead of class -member function.

cout<<"\n ****** After SORT ***** " ;
QListIterator<Student*> it_1( studentList );
Student* val_1 = 0;
while( it_1.hasNext() )
{
val_1 = it_1.next();
cout<<"\n" << val_1;
cout<<"\n" << val_1->getRollNo();
}

qDeleteAll( studentList );

return 0;
}



here is the compliation error.
please help me to resolve it.


main.cpp(311) : warning C4101: 'assending' : unreferenced local variable
c:\Qt\4.2.2\include\QtCore\../../src\corelib\tools\qalgorithms.h(355) : error C2664: 'bool (const Student &,const Student &)' : cannot convert parameter 2 from 'Student *' to 'const Student &'
Reason: cannot convert from 'Student *' to 'const Student'
No constructor could take the source type, or constructor overload resolution was ambiguous
c:\Qt\4.2.2\include\QtCore\../../src\corelib\tools\qalgorithms.h(180) : see reference to function template instantiation 'void QAlgorithmsPrivate::qSortHelper<RandomAccessIterator,T,bool(__cdecl *)(const Student &,const Student &)>(RandomAccessIterator,RandomAccessIterator,const T & ,LessThan)' being compiled
with
[
RandomAccessIterator=QList<Student *>::iterator,
T=Student *,
LessThan=bool (__cdecl *)(const Student &,const Student &)
]
main.cpp(312) : see reference to function template instantiation 'void qSort<QList<T>::iterator,bool(__cdecl *)(const Student &,const Student &)>(RandomAccessIterator,RandomAccessIterator,LessTha n)' being compiled
with
[
T=Student *,
RandomAccessIterator=QList<Student *>::iterator,
LessThan=bool (__cdecl *)(const Student &,const Student &)
]
c:\Qt\4.2.2\include\QtCore\../../src\corelib\tools\qalgorithms.h(355) : error C2664: 'bool (const Student &,const Student &)' : cannot convert parameter 1 from 'Student *' to 'const Student &'
Reason: cannot convert from 'Student *' to 'const Student'
No constructor could take the source type, or constructor overload resolution was ambiguous
c:\Qt\4.2.2\include\QtCore\../../src\corelib\tools\qalgorithms.h(360) : error C2664: 'bool (const Student &,const Student &)' : cannot convert parameter 2 from 'Student *' to 'const Student &'
Reason: cannot convert from 'Student *' to 'const Student'
No constructor could take the source type, or constructor overload resolution was ambiguous
c:\Qt\4.2.2\include\QtCore\../../src\corelib\tools\qalgorithms.h(360) : error C2664: 'bool (const Student &,const Student &)' : cannot convert parameter 1 from 'Student *' to 'const Student &'
Reason: cannot convert from 'Student *' to 'const Student'
No constructor could take the source type, or constructor overload resolution was ambiguous
c:\Qt\4.2.2\include\QtCore\../../src\corelib\tools\qalgorithms.h(362) : error C2664: 'bool (const Student &,const Student &)' : cannot convert parameter 2 from 'Student *' to 'const Student &'
Reason: cannot convert from 'Student *' to 'const Student'
No constructor could take the source type, or constructor overload resolution was ambiguous
c:\Qt\4.2.2\include\QtCore\../../src\corelib\tools\qalgorithms.h(362) : error C2664: 'bool (const Student &,const Student &)' : cannot convert parameter 1 from 'Student *' to 'const Student &'
Reason: cannot convert from 'Student *' to 'const Student'
No constructor could take the source type, or constructor overload resolution was ambiguous
c:\Qt\4.2.2\include\QtCore\../../src\corelib\tools\qalgorithms.h(370) : error C2664: 'bool (const Student &,const Student &)' : cannot convert parameter 2 from 'Student *' to 'const Student &'
Reason: cannot convert from 'Student *' to 'const Student'
No constructor could take the source type, or constructor overload resolution was ambiguous
c:\Qt\4.2.2\include\QtCore\../../src\corelib\tools\qalgorithms.h(370) : error C2664: 'bool (const Student &,const Student &)' : cannot convert parameter 1 from 'Student *' to 'const Student &'
Reason: cannot convert from 'Student *' to 'const Student'
No constructor could take the source type, or constructor overload resolution was ambiguous
c:\Qt\4.2.2\include\QtCore\../../src\corelib\tools\qalgorithms.h(373) : error C2664: 'bool (const Student &,const Student &)' : cannot convert parameter 2 from 'Student *' to 'const Student &'
Reason: cannot convert from 'Student *' to 'const Student'
No constructor could take the source type, or constructor overload resolution was ambiguous
c:\Qt\4.2.2\include\QtCore\../../src\corelib\tools\qalgorithms.h(373) : error C2664: 'bool (const Student &,const Student &)' : cannot convert parameter 1 from 'Student *' to 'const Student &'
Reason: cannot convert from 'Student *' to 'const Student'
No constructor could take the source type, or constructor overload resolution was ambiguous
c:\Qt\4.2.2\include\QtCore\../../src\corelib\tools\qalgorithms.h(385) : error C2664: 'bool (const Student &,const Student &)' : cannot convert parameter 2 from 'Student *' to 'const Student &'
Reason: cannot convert from 'Student *' to 'const Student'
No constructor could take the source type, or constructor overload resolution was ambiguous
c:\Qt\4.2.2\include\QtCore\../../src\corelib\tools\qalgorithms.h(385) : error C2664: 'bool (const Student &,const Student &)' : cannot convert parameter 1 from 'Student *' to 'const Student &'
Reason: cannot convert from 'Student *' to 'const Student'
No constructor could take the source type, or constructor overload resolution was ambiguous


logFile - 12 error(s), 10 warning(s)

jpn
10th October 2007, 10:32
Right, the comparator function should naturally take pointers since that's what the container contains:


bool toAssending( const Student * s1 , const Student * s2 )
{
cout<<"\n" << __FUNCTION__;
return s1->getRollNo() < s2->getRollNo();
}

joseph
10th October 2007, 10:59
could you please me , how this qSort() is working .
Are we passing function pointer to qSort() ...??



thanks

jpn
10th October 2007, 12:10
could you please me , how this qSort() is working.
You can always check Qt sources for implementation details. ;) You can find qSort() implementation in src/corelib/tools/qalgorithms.h.

Are we passing function pointer to qSort() ...??
Yes, qSort() calls the passed function to compare items.

joseph
11th October 2007, 11:49
First of all thanks jpn,
But please see the below code for compare <double*>


bool putDoubleListInAscendingOrder( const double * d1 , const double * d2 )
{
cout<<"\n" << __FUNCTION__;
return *d1 < *d2;
}

int main()
{

QList<double*> _doubleList ;
_doubleList.append( new double(5.12) );
_doubleList.append( new double(2.22) );
_doubleList.append( new double(3.22) );
_doubleList.append( new double(1.22) );
_doubleList.append( new double(4.22) );


QListIterator<double*> it( _doubleList );
double* d = 0;
cout<<"\n ****** Before SORT ***** " ;
while( it.hasNext() )
{
d = it.next();
cout<<"\n" << *d;
}
cout<<"\n ****** After SORT ***** " ;
qSort( _doubleList.begin(), _doubleList.end() , putDoubleListInAscendingOrder );
it. toFront(); // Note tat i am using the same iterator
// According to assistant , iterator will move before 1-st item
// if i am calling it.next(), then it is sapposed to return the first item in
// _doubleList .

d= it.next();
cout<<"\n d :" << *d ; // Here the expected result is "1.22"

// N:B => But am getting the reuslt of cout is = "5.12" ...why..????


return 0;
}



but if am changing the code as below. ( with different iterator or _doubleList.first() will return the expected result ie; "1.22" )




int main()
{

QList<double*> _doubleList ;
_doubleList.append( new double(5.12) );
_doubleList.append( new double(2.22) );
_doubleList.append( new double(3.22) );
_doubleList.append( new double(1.22) );
_doubleList.append( new double(4.22) );


QListIterator<double*> it( _doubleList );
double* d = 0;
cout<<"\n ****** Before SORT ***** " ;
while( it.hasNext() )
{
d = it.next();
cout<<"\n" << *d;
}
cout<<"\n ****** After SORT ***** " ;
qSort( _doubleList.begin(), _doubleList.end() , putDoubleListInAscendingOrder );

QListIterator<double*> it_2 ( _doubleList )
it_2. next() ;
d= it_2. next();
cout<<"\n d :" << *d ; // Here the result is "1.22"

// could you please explain why ...?? or If my understanding is wrong please correct me..

return 0;
}

ChristianEhrlicher
11th October 2007, 12:31
'it' is invalid after qSort()

jpn
11th October 2007, 12:40
Indeed, as QListIterator docs state:

QListIterator<T> allows you to iterate over a QList<T> (or a QQueue<T>). If you want to modify the list as you iterate over it, use QMutableListIterator<T> instead.
Also, may I ask what's the point of allocating doubles on the heap? Notice that QList is an implicitly shared (http://doc.trolltech.com/4.3/shared.html) class.

joseph
11th October 2007, 13:13
Indeed, as QListIterator docs state:

Also, may I ask what's the point of allocating doubles on the heap? Notice that QList is an implicitly shared (http://doc.trolltech.com/4.3/shared.html) class.


Thanks for you information.
yes you are right. There is no need for <double*>.
But it was just an example.:)


I have tried with QMutableListIterator . its working perfectly
thanks

petersvp
18th August 2013, 17:40
Check this & use functors!

http://stackoverflow.com/questions/12689376/how-to-pass-a-method-to-qsort/18301277#18301277

d_stranz
18th August 2013, 18:55
I am sure that 6 years ago, your advice would have been useful. Meanwhile, the OP's original project was canceled, the company went under, and he's had 4 different jobs since then.

Functors are nice, but when all you need is a simple static function that takes two pointers to double as arguments and returns a bool, adding all that overhead is overkill. And will the person who inherits this code take a look and ask, "Why the heck did they use functors when a static function would have worked just as well? Must be reading too many advanced C++ books".

Been there, done that. Functors have their uses and many C++ generic programming template constructs could not be implemented without them. Sorting a list of pointers by the value of the pointed-to instance isn't one of them.