1. 程式人生 > >使用map以時間對資料夾進行排序

使用map以時間對資料夾進行排序

理論:摘自他人:

map是用來存放<key, value>鍵值對的資料結構,可以很方便快速的根據key查到相應的value。假如儲存學生和其成績(假定不存在重名,當然可以對重名加以區分),我們用map來進行儲存就是個不錯的選擇。 我們這樣定義,map<string, int>,其中學生姓名用string型別,作為Key;該學生的成績用int型別,作為value。這樣一來,我們可以根據學生姓名快速的查詢到他的成績。

        但是,我們除了希望能夠查詢某個學生的成績,或許還想看看整體的情況。我們想把所有同學和他相應的成績都輸出來,並且按照我們想要的順序進行輸出:比如按照學生姓名的順序進行輸出,或者按照學生成績的高低進行輸出。換句話說,我們希望能夠對map進行按Key排序或按Value排序,然後按序輸出其鍵值對的內容。

一、C++ STL中Map的按Key排序

       其實,為了實現快速查詢,map內部本身就是按序儲存的(比如紅黑樹)。在我們插入<key, value>鍵值對時,就會按照key的大小順序進行儲存。這也是作為key的型別必須能夠進行<運算比較的原因。現在我們用string型別作為key,因此,我們的儲存就是按學生姓名的字典排序儲存的。

【參考程式碼】

  1. #include<map>
  2. #include<string>
  3. #include<iostream>
  4. usingnamespace std;  
  5. typedef pair<string, int> PAIR;  
  6. ostream& operator<<(ostream& out, const PAIR& p) {  
  7.   return out << p.first << "\t" << p.second;  
  8. }  
  9. int main() {  
  10.   map<string, int> name_score_map;  
  11.   name_score_map["LiMin"] = 90;   
  12.   name_score_map["ZiLinMi"] = 79;   
  13.   name_score_map["BoB"] = 92;   
  14.   name_score_map.insert(make_pair("Bing"
    ,99));  
  15.   name_score_map.insert(make_pair("Albert",86));  
  16.   for (map<string, int>::iterator iter = name_score_map.begin();  
  17.        iter != name_score_map.end();  
  18.        ++iter) {  
  19.     cout << *iter << endl;  
  20.   }  
  21.   return 0;  
  22.  }  

【執行結果】


大家都知道map是stl裡面的一個模板類,現在我們來看下map的定義:

  1. template < class Key, class T, class Compare = less<Key>,  
  2.            class Allocator = allocator<pair<const Key,T> > > class map;  

它有四個引數,其中我們比較熟悉的有兩個: Key 和 Value。第四個是 Allocator,用來定義儲存分配模型的,此處我們不作介紹。

現在我們重點看下第三個引數: class Compare = less<Key> 

這也是一個class型別的,而且提供了預設值 less<Key>。 less是stl裡面的一個函式物件,那麼什麼是函式物件呢?

所謂的函式物件:即呼叫操作符的類,其物件常稱為函式物件(function object),它們是行為類似函式的物件。表現出一個函式的特徵,就是通過“物件名+(引數列表)”的方式使用一個 類,其實質是對operator()操作符的過載。

現在我們來看一下less的實現:

  1. template <class T> struct less : binary_function <T,T,bool> {  
  2.   bool operator() (const T& x, const T& y) const
  3.     {return x<y;}  
  4. };  

它是一個帶模板的struct,裡面僅僅對()運算子進行了過載,實現很簡單,但用起來很方便,這就是函式物件的優點所在。stl中還為四則運算等常見運算定義了這樣的函式物件,與less相對的還有greater:
  1. template <class T> struct greater : binary_function <T,T,bool> {  
  2.   bool operator() (const T& x, const T& y) const
  3.     {return x>y;}  
  4. };  

map這裡指定less作為其預設比較函式(物件),所以我們通常如果不自己指定Compare,map中鍵值對就會按照Key的less順序進行組織儲存,因此我們就看到了上面程式碼輸出結果是按照學生姓名的字典順序輸出的,即string的less序列。

我們可以在定義map的時候,指定它的第三個引數Compare,比如我們把預設的less指定為greater:

【參考程式碼】

  1. #include<map>
  2. #include<string>
  3. #include<iostream>
  4. usingnamespace std;  
  5. typedef pair<string, int> PAIR;  
  6. ostream& operator<<(ostream& out, const PAIR& p) {  
  7.   return out << p.first << "\t" << p.second;  
  8. }  
  9. int main() {  
  10.   map<string, int, greater<string> > name_score_map;  
  11.   name_score_map["LiMin"] = 90;   
  12.   name_score_map["ZiLinMi"] = 79;   
  13.   name_score_map["BoB"] = 92;   
  14.   name_score_map.insert(make_pair("Bing",99));  
  15.   name_score_map.insert(make_pair("Albert",86));  
  16.   for (map<string, int>::iterator iter = name_score_map.begin();  
  17.        iter != name_score_map.end();  
  18.        ++iter) {  
  19.     cout << *iter << endl;  
  20.   }  
  21.   return 0;  
  22. }  

【執行結果】


現在知道如何為map指定Compare類了,如果我們想自己寫一個compare的類,讓map按照我們想要的順序來儲存,比如,按照學生姓名的長短排序進行儲存,那該怎麼做呢?

其實很簡單,只要我們自己寫一個函式物件,實現想要的邏輯,定義map的時候把Compare指定為我們自己編寫的這個就ok啦。

  1. struct CmpByKeyLength {  
  2.   bool operator()(const string& k1, const string& k2) {  
  3.     return k1.length() < k2.length();  
  4.   }  
  5. };  

是不是很簡單!這裡我們不用把它定義為模板,直接指定它的引數為string型別就可以了。

【參考程式碼】

  1. int main() {  
  2.   map<string, int, CmpByKeyLength> name_score_map;  
  3.   name_score_map["LiMin"] = 90;   
  4.   name_score_map["ZiLinMi"] = 79;   
  5.   name_score_map["BoB"] = 92;   
  6.   name_score_map.insert(make_pair("Bing",99));  
  7.   name_score_map.insert(make_pair("Albert",86));  
  8.   for (map<string, int>::iterator iter = name_score_map.begin();  
  9.        iter != name_score_map.end();  
  10.        ++iter) {  
  11.     cout << *iter << endl;  
  12.   }  
  13.   return 0;  
  14. }  

【執行結果】


測試:

// mapSort.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include <afxwin.h>
#include <iostream>  
#include <map>  
#include <string>
using namespace std;


int _tmain(int argc, _TCHAR* argv[])
{
	SYSTEMTIME localTime;
	SYSTEMTIME sysTime;
	GetLocalTime(&localTime);
	GetSystemTime(&sysTime);

	WIN32_FIND_DATA FindFileData;
	HANDLE hFind = INVALID_HANDLE_VALUE;

	CString strDirPath = "C:\\data\\*.*";
	map<LONGLONG,CString,greater<LONG32>> vFileInfo;
	hFind = FindFirstFile(strDirPath,&FindFileData);

	while (TRUE)
	{
		if(FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY
			&& _tcscmp(FindFileData.cFileName, _T(".")) != 0
			&& _tcscmp(FindFileData.cFileName, _T("..")) != 0)
		{ 			
			CFileTime fileTime(FindFileData.ftLastAccessTime);
			LONGLONG  nTime = fileTime.GetTime();

			CString strFileName = FindFileData.cFileName;//檔名
			vFileInfo[nTime] = strFileName;             //檔案時間:64位整形數用來比較大小
		}

		if (FindNextFile(hFind, &FindFileData) == 0)
		{
			break;
		}
	}
	FindClose(hFind);
	hFind = INVALID_HANDLE_VALUE;

	map<LONGLONG,CString,greater<LONG32>>::iterator iter;
	for (iter = vFileInfo.begin();iter != vFileInfo.end();++iter)
	{
		cout<<iter->first<<"\t"<<iter->second<<endl;
	}

	return 0;  
}