現在的位置: 首頁 > 綜合 > 正文

QT容器中的通用算法

2013年10月08日 ⁄ 綜合 ⁄ 共 2617字 ⁄ 字號 評論關閉
今天開始的部分是關於Qt提供的一些通用算法。這部分內容來自C++ GUI Programming with Qt 4, 2nd Edition。
 
<QtAlgorithms>提供了一系列通用的模板函數,用於實現容器上面的基本算法。這部分算法很多依賴於STL風格的遍歷器(還記得前面曾經說過的Java風格的遍歷器和STL風格的遍歷器嗎?)。實際上,C++ STL也提供了很多通用算法,包含在<algorithm>頭文件內。這部分算法對於Qt容器同樣也是適用的。因此,如果你想使用的算法在Qt的<QtAlgorithms>頭文件中沒有包含,那麼就可以使用STL的算法代替,這並不會產生什麼衝突。這裡我們來說幾個Qt中的通用算法。雖然這些算法都是很簡單的,但是,庫函數往往會比自己編寫的更有效率,因此還是推薦使用系統提供的函數的。
 
首先是qFind()函數。qFind()函數會在容器中查找一個特定的值。它的參數中有一個起始位置和終止位置,如果被查找的元素存在,函數返回第一個匹配項的位置,否則則返回終止位置。注意,我們這裡說的“位置”,實際上是STL風格的遍歷器。我們知道,使用STL風格遍歷器是可以反映一個位置的。例如下面的例子,i的值將是list.begin() + 1,而j會是list.end():
 
QStringList list;
list << "Emma" << "Karl" << "James" << "Mariette";

QStringList::iterator i = qFind(list.begin(), list.end(), "Karl");
QStringList::iterator j = qFind(list.begin(), list.end(), "Petra");
 
qBinaryFind()的行為很像qFind(),所不同的是,qBinaryFind()是二分查找算法,它只適用於查找排序之後的集合,而qFind()則是標準的線性查找。通常,二分查找法使用條件更為苛刻,但是效率也會更高。
 
qFill()會使用給定值對容器進行填充。例如:
 
QLinkedList<int> list(10);
qFill(list.begin(), list.end(), 1009);
 
正如其他基於遍歷器的算法一樣,qFill()也可以針對容器的一部分進行操作,例如下面的代碼將會把vector的前5位設置成1009,而最後5位設置為2013:
 
QVector<int> vect(10);
qFill(vect.begin(), vect.begin() + 5, 1009);
qFill(vect.end() - 5, vect.end(), 2013);
 
qCopy()算法可以實現將一個容器中的元素複製到另一個容器,例如:
 
qCopy()也可以用於同一容器中的元素的複製。qCopy()操作成功的關鍵是源容器和目的容器的範圍不會發生溢出。例如如下代碼,我們將把一個列表的最後兩個元素複製給前兩個元素:
 
qCopy(list.begin(), list.begin() + 2, list.end() - 2);
 
qSort()實現了容器元素的遞增排序,使用起來也很簡單:
 
qSort(list.begin(), list.end());
 
默認情況下,qSort()將使用 < 運算符進行元素的比較。這暗示如果需要的話,你必須定義 < 運算符。如果需要按照遞減排序,需要將qGreater<T>()當作第三個參數傳給qSort()函數。例如:
 
qSort(list.begin(), list.end(), qGreater<int>());
 
注意,這裡的T實際上是容器的泛型類型。實際上,我們可以利用第三個參數對排序進行定義。例如,我們自定義的數據類型中有一個大小寫不敏感的QString的小於比較函數:
 
bool insensitiveLessThan(const QString &str1, const QString &str2)
{
        return str1.toLower() < str2.toLower();
}
 
那麼,我們可以這樣使用qSort()從而可以利用這個函數:
 
QStringList list;
// ...
qSort(list.begin(), list.end(), insensitiveLessThan);
 
qStableSort()函數類似與qSort(),所不同之處在於它是穩定排序。穩定排序是算法設計上的一個名詞,意思是,在排序過程中,如果有兩個元素相等,那麼在排序結果中這兩個元素的先後順序同排序前的原始順序是一致的。舉個例子,對於一個序列:a1, a5, a32, a31, a4,它們的大小順序是a1 < a31 = a32 < a4 < a5,那麼穩定排序之後的結果應該是 a1, a32, a31, a4, a5,也就是相等的元素在排序結果中出現的順序和原始順序是一致的。穩定排序在某些場合是很有用的,比如,現在有一份按照學號排序的學生成績單。你想按照成績高低重新進行排序,對於成績一樣的學生,還是遵循原來的學號順序。這時候就要穩定排序了。
 
qDeleteAll()函數將對容器中存儲的所有指針進行delete操作。這個函數僅在容器元素是指針的情形下才適用。執行過這個函數之後,容器中的指針均被執行了delete運算,但是這些指針依然被存儲在容器中,成為野指針,你需要調用容器的clear()函數來避免這些指針的誤用:
 
qDeleteAll(list);
list.clear();
 
當我們需要動態申請很多空間,但是暫時又不能delete的時候,就可以把他們都放入QList中,然後再在合適的時候delete了
qSwap()函數可以交換兩個元素的位置。例如:
 
int x1 = line.x1();
int x2 = line.x2();
if (x1 > x2)
        qSwap(x1, x2);
 
最後,在<QtGlobal>頭文件中,也定義了幾個有用的函數。這個頭文件被其他所有的頭文件include了,因此你不需要顯式的include這個頭文件了。
在這個頭文件中有這麼幾個函數:qAbs()返回參數的絕對值,qMin()qMax()則返回兩個值的最大值和最小值。

抱歉!評論已關閉.