(svn r13276) -Codechange: use qsort() for initial sorting of a list for better performance (credits go to skidd13 and peter1138)
This commit is contained in:
		| @@ -9,11 +9,12 @@ | |||||||
| #include "date_type.h" | #include "date_type.h" | ||||||
|  |  | ||||||
| enum SortListFlags { | enum SortListFlags { | ||||||
| 	VL_NONE    = 0,      ///< no sort | 	VL_NONE       = 0,      ///< no sort | ||||||
| 	VL_DESC    = 1 << 0, ///< sort descending or ascending | 	VL_DESC       = 1 << 0, ///< sort descending or ascending | ||||||
| 	VL_RESORT  = 1 << 1, ///< instruct the code to resort the list in the next loop | 	VL_RESORT     = 1 << 1, ///< instruct the code to resort the list in the next loop | ||||||
| 	VL_REBUILD = 1 << 2, ///< create sort-listing to use for qsort and friends | 	VL_REBUILD    = 1 << 2, ///< rebuild the sort list | ||||||
| 	VL_END     = 1 << 3, | 	VL_FIRST_SORT = 1 << 3, ///< sort with qsort first | ||||||
|  | 	VL_END        = 1 << 4, | ||||||
| }; | }; | ||||||
| DECLARE_ENUM_AS_BIT_SET(SortListFlags); | DECLARE_ENUM_AS_BIT_SET(SortListFlags); | ||||||
|  |  | ||||||
| @@ -52,10 +53,25 @@ public: // Temporary: public for conversion only | |||||||
| 		this->resort_timer = DAY_TICKS * 10; | 		this->resort_timer = DAY_TICKS * 10; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Reverse the list | ||||||
|  | 	 */ | ||||||
|  | 	void Reverse() | ||||||
|  | 	{ | ||||||
|  | 		assert(this->IsSortable()); | ||||||
|  |  | ||||||
|  | 		T *a = this->data; | ||||||
|  | 		T *b = a + (this->items - 1); | ||||||
|  |  | ||||||
|  | 		do { | ||||||
|  | 			Swap(*a, *b); | ||||||
|  | 		} while (((a + 1) != b) && (++a != --b)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| public: | public: | ||||||
| 	GUIList() : | 	GUIList() : | ||||||
| 		func_list(NULL), | 		func_list(NULL), | ||||||
| 		flags(VL_NONE), | 		flags(VL_FIRST_SORT), | ||||||
| 		sort_type(0), | 		sort_type(0), | ||||||
| 		resort_timer(1) | 		resort_timer(1) | ||||||
| 	{}; | 	{}; | ||||||
| @@ -78,7 +94,7 @@ public: | |||||||
| 	void SetSortType(uint8 n_type) | 	void SetSortType(uint8 n_type) | ||||||
| 	{ | 	{ | ||||||
| 		if (this->sort_type != n_type) { | 		if (this->sort_type != n_type) { | ||||||
| 			SETBITS(this->flags, VL_RESORT); | 			SETBITS(this->flags, VL_RESORT | VL_FIRST_SORT); | ||||||
| 			this->sort_type = n_type; | 			this->sort_type = n_type; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -110,6 +126,8 @@ public: | |||||||
| 			CLRBITS(this->flags, VL_DESC); | 			CLRBITS(this->flags, VL_DESC); | ||||||
| 		} | 		} | ||||||
| 		this->sort_type = l.criteria; | 		this->sort_type = l.criteria; | ||||||
|  |  | ||||||
|  | 		SETBITS(this->flags, VL_FIRST_SORT); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -158,21 +176,16 @@ public: | |||||||
| 	{ | 	{ | ||||||
| 		this->flags ^= VL_DESC; | 		this->flags ^= VL_DESC; | ||||||
|  |  | ||||||
| 		if (this->IsSortable()) { | 		if (this->IsSortable()) this->Reverse(); | ||||||
| 			T *a = this->data; |  | ||||||
| 			T *b = a + (this->items - 1); |  | ||||||
|  |  | ||||||
| 			do { |  | ||||||
| 				Swap(*a, *b); |  | ||||||
| 			} while (((a + 1) != b) && (++a != --b)); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * GnomeSort algorithm | 	 * GnomeSort algorithm | ||||||
| 	 *  This sorting uses a slightly modifyied Gnome search. | 	 *  This sorting uses a slightly modifyied Gnome search. | ||||||
| 	 *  The basic Gnome search trys to sort already sorted | 	 *  The basic Gnome search trys to sort already sorted | ||||||
| 	 *  list parts. The modification skips these. | 	 *  list parts. The modification skips these. For the first | ||||||
|  | 	 *  sorting we use qsort since it is faster for irregular | ||||||
|  | 	 *  sorted data. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param compare The function to compare two list items | 	 * @param compare The function to compare two list items | ||||||
| 	 * */ | 	 * */ | ||||||
| @@ -188,12 +201,20 @@ public: | |||||||
| 		/* Do not sort when the list is not sortable */ | 		/* Do not sort when the list is not sortable */ | ||||||
| 		if (!this->IsSortable()) return; | 		if (!this->IsSortable()) return; | ||||||
|  |  | ||||||
|  | 		const bool desc = HASBITS(this->flags, VL_DESC); | ||||||
|  |  | ||||||
|  | 		if (HASBITS(this->flags, VL_FIRST_SORT)) { | ||||||
|  | 			qsort(this->data, this->items, sizeof(T), (int (*)(const void *a, const void *b))compare); | ||||||
|  |  | ||||||
|  | 			if (desc) this->Reverse(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		T *a = this->data; | 		T *a = this->data; | ||||||
| 		T *b = a + 1; | 		T *b = a + 1; | ||||||
|  |  | ||||||
| 		uint length = this->items; | 		uint length = this->items; | ||||||
| 		uint offset = 0; // Jump variable | 		uint offset = 0; // Jump variable | ||||||
| 		const bool desc = HASBITS(this->flags, VL_DESC); |  | ||||||
|  |  | ||||||
| 		while (length > 1) { | 		while (length > 1) { | ||||||
| 			const int diff = compare(a, b); | 			const int diff = compare(a, b); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 smatz
					smatz