Reference Book: 《Data Structures and Program Design in C++》
--------------------------------------------------------------------------------------------------------------------------------------------------- 1. Doubly_Linked_List 见文章《Doubly_Linked_List的代码实现》 2. Sortable_list #ifndef SORTABLE_LIST_H #define SORTABLE_LIST_H #include "Doubly_Linked_List.h" #include "Record.h" #define MAX_SIZE 128 template <class Key> class Sortable_list: public Doubly_Linked_List<Key> { public: //直接调用基类Doubly_Linked_List的初始化方法 // 插入排序 void insertion_sort(); // 选择排序 void selection_sort(); int max_key(int low, int high); void swap(int low, int high); // 希尔排序(不适用链式实现) void sort_interval(int start, int increment); void shell_sort(); // 归并排序 void merge_sort(); void recursive_merge_sort(Sortable_list<Key> &the_list); // 不用书中传入head指针的实现方式 Sortable_list<Key> divide_from(Sortable_list<Key> &the_list); void combine(Sortable_list<Key> &the_list, const Sortable_list<Key> &second_list); // 快速排序 void quick_sort(); void recursive_quick_sort(Sortable_list<Key> &the_list); Sortable_list<Key> partition(Sortable_list<Key> &the_list, Key pivot); void unite(Sortable_list<Key> &the_list, Sortable_list<Key> &second_list, Key pivot); // 堆排序 void heap_sort(); void build_heap(); void insert_heap(const Key &now, int low, int high); void insert_array(int position, const Key &data); void traverse_array(void (*visit)(Key &)); protected: private: Key entry[MAX_SIZE]; }; /************************************* * Insertion Sort * *************************************/ template <class Key> void Sortable_list<Key>::insertion_sort() /*Pre: Post: 从前向后遍历表, 将尚未排序的第一个键在已排序队列中找到合适的位置进行插入. */ { Node<Key> *first_unsorted, *last_sorted, *now, *trailing; if(Doubly_Linked_List<Key>::head != nullptr) // head是双链表类中的元素, 需要作用域符号 { last_sorted = Doubly_Linked_List<Key>::head; while(last_sorted->next != nullptr) { first_unsorted = last_sorted->next; // 插入到pos==0的位置 if(first_unsorted->entry <= Doubly_Linked_List<Key>::head->entry) { last_sorted->next = first_unsorted->next; if(first_unsorted->next != nullptr) // 当unsorted中至少有1个结点时 first_unsorted->next->back = last_sorted; Doubly_Linked_List<Key>::head->back = first_unsorted; first_unsorted->next = Doubly_Linked_List<Key>::head; first_unsorted->back = nullptr; Doubly_Linked_List<Key>::head = first_unsorted; } // 搜索正确的pos插入 else { trailing = Doubly_Linked_List<Key>::head; now = trailing->next; while(first_unsorted->entry > now->entry) { trailing = now; now = trailing->next; } if(first_unsorted==now) // 已经在正确的位置 last_sorted = first_unsorted; else { last_sorted->next = first_unsorted->next; first_unsorted->next->back = last_sorted; first_unsorted->next = now; now->back = first_unsorted; trailing->next = first_unsorted; first_unsorted->back = trailing; } } } } } /************************************* * Selection Sort * *************************************/ template <class Key> void Sortable_list<Key>::selection_sort() /*Pre: Post: */ { // pos从最后到1, 不用到0因为pos==1时已经比较过第一个键 for(int pos = Doubly_Linked_List<Key>::count-1; pos > 0; pos--) { int max = max_key(0, pos); swap(max, pos); } } template <class Key> int Sortable_list<Key>::max_key(int low, int high) /*Pre: Post: 遍历pos从low到high之间的所有键, 返回最大键的位置. */ { Key data, now_entry; Doubly_Linked_List<Key>::set_position(low); data = Doubly_Linked_List<Key>::current->entry; int now, pos = low; // 找到pos为low至high之间最大键的位置 for(now = low + 1; now <= high; now++) { Doubly_Linked_List<Key>::set_position(now); now_entry = Doubly_Linked_List<Key>::current->entry; if(data < now_entry) { data = now_entry; pos = now; } } return pos; } template <class Key> void Sortable_list<Key>::swap(int low, int high) /*Pre: Post: 若需要交换的pos相同者不进行操作; 否则通过insert和remove操作先将最大键插入到 pos==high的位置, 再删除对应结点, 再将要交换的键插入到pos==low的位置, 最后 remove该键注意该键在high+1的位置. */ { if(low==high)return; // 当前pos的键为最大键则不发生交换 Key data; Node<Key> *max, *pos; Doubly_Linked_List<Key>::set_position(low); max = Doubly_Linked_List<Key>::current; Doubly_Linked_List<Key>::set_position(high); pos = Doubly_Linked_List<Key>::current; // 利用insert和remove操作完成结点的交换 (*this).insert(high, max->entry); (*this).remove(low, data); (*this).insert(low, pos->entry); (*this).remove(high+1, data); } /********************************* * Shell Sort * *********************************/ template <class Key> void Sortable_list<Key>::sort_interval(int start, int increment) /*Pre: Post: */ { int first_unsorted; // position of first unsorted entry int position; // searches sorted part of list Key current; // holds the entry temporarily removed from list for (first_unsorted = start + increment; first_unsorted < Doubly_Linked_List<Key>::count; first_unsorted += increment ) if (entry[first_unsorted] < entry[first_unsorted - increment]) { position = first_unsorted; current = entry[first_unsorted]; // Pull unsorted entry out of the list. do { // Shift all entries until the proper position is found. entry[position] = entry[position - increment]; position -= increment; // position is empty. } while (position > start && entry[position - increment] > current); entry[position] = current; } } template <class Key> void Sortable_list<Key>::shell_sort() /*Pre: Post: */ { int increment, start; increment = Doubly_Linked_List<Key>::count; do { increment = increment/3+1; for(start = 0; start<increment; start++) sort_interval(start, increment); }while(increment > 1); } /********************************** * Merge Sort * **********************************/ template <class Key> void Sortable_list<Key>::merge_sort() /*Post: 对表中元素分组重新排列,最终得到一个升序序列. Uses: Doubly_Linked_List和recursive_merge_sort(). */ { recursive_merge_sort(*this); } template <class Key> void Sortable_list<Key>::recursive_merge_sort(Sortable_list<Key> &the_list) /*Post: 通过将the_list分为两个子表再递归调用recursive_merge_sort()并将其合并, 通过 修改the_list返回排序后的新表. Uses: */ { Sortable_list<Key> second_list; if(the_list.size() > 1) // 表中至少有两个键时进行归并排序 { second_list = divide_from(the_list); recursive_merge_sort(the_list); recursive_merge_sort(second_list); combine(the_list, second_list); } } template <class Key> Sortable_list<Key> Sortable_list<Key>::divide_from(Sortable_list<Key> &the_list) /*Post: 将the_list分割成两个list其中第一个list较长保存再the_list中, 另一个 返回为second_list. Uses: */ { int mid = (the_list.size()-1) / 2; // 中间元素(若偶数个元素则为左中)的pos值 int second_size = the_list.size() - (mid+1); Sortable_list<Key> second_list; for(int i = 0; i < second_size; i++) { Key data; the_list.remove(mid+1, data); // 始终删除的是pos为mid+1的键 second_list.insert(i, data); } return second_list; } template <class Key> void Sortable_list<Key>::combine(Sortable_list<Key> &the_list, const Sortable_list<Key> &second_list) /*Post: 将the_list和second_list中的键排序之后合并成新的list并返回. Uses: */ { Key data_the_list, data_second_list; Sortable_list<Key> temp_list; int pos_the_list = 0, pos_second_list = 0, pos_temp_list = 0; // the_list和second_list均非空时比较两者元素, 并按升序插入至temp_list while(pos_the_list < the_list.size() && pos_second_list < second_list.size()) { the_list.retrieve(pos_the_list, data_the_list); second_list.retrieve(pos_second_list, data_second_list); if(data_the_list <= data_second_list) { temp_list.insert(pos_temp_list, data_the_list); pos_the_list++; } else { temp_list.insert(pos_temp_list, data_second_list); pos_second_list++; } pos_temp_list++; } // 将仍有元素的表的剩余键按序插入temp_list while(pos_the_list < the_list.size()) { the_list.retrieve(pos_the_list, data_the_list); temp_list.insert(pos_temp_list, data_the_list); pos_the_list++; pos_temp_list++; } while(pos_second_list < second_list.size()) { second_list.retrieve(pos_second_list, data_second_list); temp_list.insert(pos_temp_list, data_second_list); pos_second_list++; pos_temp_list++; } the_list = temp_list; // 操作符=重载将temp_list赋值给the_list返回 } /********************************** * Quick Sort * **********************************/ template <class Key> void Sortable_list<Key>::quick_sort() /*Post: Uses: */ { recursive_quick_sort(*this); } template <class Key> void Sortable_list<Key>::recursive_quick_sort(Sortable_list<Key> &the_list) /*Post: 将the_list中的中间键作为pivot, 当the_list中的键的数目大于1时将其 按与键pivot的相对大小分为the_list和second_list两个子表. 然后分别执行 递归调用, 返回后将the_list, pivot, second_list进行合并. Uses: */ { // 中间元素(若偶数个元素则为左中)的pos值 int pivot_position = (the_list.size()-1) / 2; Key pivot; the_list.remove(pivot_position, pivot); Sortable_list<Key> second_list; if(the_list.size() > 1) { second_list = partition(the_list, pivot); recursive_quick_sort(the_list); recursive_quick_sort(second_list); unite(the_list, second_list, pivot); } else if(the_list.size()==1) { Key data; the_list.retrieve(0, data); if(data<pivot) the_list.insert(1, pivot); else the_list.insert(0, pivot); } else the_list.insert(0, pivot); } template <class Key> Sortable_list<Key> Sortable_list<Key>::partition(Sortable_list<Key> &the_list, Key pivot) /*Post: 将the_list中的键按与pivot的相对大小, 严格小于pivot的重新存入the_list, 其他键存入second_list并返回, 且保持原来键的相对位置不变. Uses: */ { Sortable_list<Key> second_list, temp_list; int i, pos_temp_list = 0, pos_second_list = 0; Key data; for(i = 0; i < the_list.size(); i++) { the_list.retrieve(i, data); if(data < pivot)temp_list.insert(pos_temp_list++, data); else second_list.insert(pos_second_list++, data); } the_list = temp_list; return second_list; } template <class Key> void Sortable_list<Key>::unite(Sortable_list<Key> &the_list, Sortable_list<Key> &second_list, Key pivot) /*Post: 将pivot和second_list中的键依序插入至the_list的最末端. Uses: */ { int i; int pos_the_list = the_list.size(); Key data; the_list.insert(pos_the_list++, pivot); // 插入pivot至the_list末 for(i = 0; i < second_list.size(); i++) { second_list.retrieve(i, data); the_list.insert(pos_the_list++, data); } } /******************************** * Heap Sort * ********************************/ template <class Key> void Sortable_list<Key>::heap_sort() /*Post: 先将顺序表构建成一个初始的大根堆, 再通过for循环, 每次将根元素移至未排序 部分的尾部, 并重新将未排序部分重新排列为一个大根堆. Uses: */ { Key now; int last_unsorted; build_heap(); // 构建初始堆 for(last_unsorted = Doubly_Linked_List<Key>::count-1; last_unsorted > 0; last_unsorted--) { now = entry[last_unsorted]; // 将堆的根上的键移至最后, 即进行键排序 entry[last_unsorted] = entry[0]; insert_heap(now, 0, last_unsorted - 1); // 重新排列堆 } } template <class Key> void Sortable_list<Key>::build_heap() /*Post: 将顺序表建成一个初始堆. Uses: */ { int low; // count/2-1即最后一个结点的父亲结点索引, 自下而上, 自右向左构建大根堆 for(low = Doubly_Linked_List<Key>::count/2-1; low >= 0; low--) { Key now = entry[low]; // insert丢弃low位置元素, 将low位置now用作插入 insert_heap(now, low, Doubly_Linked_List<Key>::count-1); } } template <class Key> void Sortable_list<Key>::insert_heap(const Key &now, int low, int high) /*Pre: 在索引low到high之间的键构成一个大根堆. 在索引low位置的键将被丢弃. Post: 键now将被插入至索引low到high之间, 并最终构成一个大根堆. Uses: */ { int large; large = 2*low+1; // low的左孩子结点 while(large <= high) { // 左孩子结点不是最后一个结点, 且左孩子结点小于右孩子结点 if(large<high && entry[large]< entry[large+1]) large++; // 已经是大根堆就跳出while循环 if(now >= entry[large]) break; else { entry[low] = entry[large]; low = large; large = 2*low+1; } } entry[low] = now; } template <class Key> void Sortable_list<Key>::insert_array(int position, const Key &data) /*Post: 用作顺序实现堆排序. Uses: */ { Doubly_Linked_List<Key>::count++; Doubly_Linked_List<Key>::current_position = position; Doubly_Linked_List<Key>::set_position(position); entry[position] = data; } template <class Key> void Sortable_list<Key>::traverse_array(void (*visit)(Key &)) /*Post: 对顺序表entry进行遍历, 并对其中的键执行visit的 Uses: */ { int position; for(position = 0; position < Doubly_Linked_List<Key>::count; position++) // 遍历列表的数组中所有元素并执行visit函数 (*visit)(entry[position]); } #endif // SORTABLE_LIST_H 3. main.cpp #include <iostream> #include "Sortable_list.h" using namespace std; void print(Key &x) { cout << x; } void test_insertion_sort() /*Post: 进行插入排序的测试. */ { Sortable_list<Key> the_list; for(int i = 0; i < 10; i++)the_list.insert(i, Key(10-i)); cout << "The list is:" << endl; the_list.traverse(print); cout << endl << "Use insertion_sort Method:" << endl; the_list.insertion_sort(); the_list.traverse(print); } void test_selection_sort() /*Post: 进行选择排序的测试. */ { Sortable_list<Key> the_list; for(int i = 0; i < 10; i++)the_list.insert(i, Key(10-i)); cout << "The list is:" << endl; the_list.traverse(print); cout << endl << "Use selection_sort Method:" << endl; the_list.selection_sort(); the_list.traverse(print); } void test_shell_sort() /*Post: 进行希尔排序的测试. */ { Sortable_list<Key> the_list; for(int i = 0; i < 10; i++)the_list.insert_array(i, Key(10-i)); cout << "The list is:" << endl; the_list.traverse_array(print); cout << endl << "Use shell_sort Method:" << endl; the_list.shell_sort(); the_list.traverse_array(print); } void test_merge_sort() /*Post: 进行归并排序的测试. */ { Sortable_list<Key> the_list; for(int i = 0; i < 10; i++)the_list.insert(i, Key(10-i)); cout << "The list is:" << endl; the_list.traverse(print); cout << endl << "Use merge_sort Method:" << endl; the_list.merge_sort(); the_list.traverse(print); } void test_quick_sort() /*Post: 进行快速排序的测试. */ { Sortable_list<Key> the_list; for(int i = 0; i < 10; i++)the_list.insert(i, Key(10-i)); cout << "The list is:" << endl; the_list.traverse(print); cout << endl << "Use quick_sort Method:" << endl; the_list.quick_sort(); the_list.traverse(print); } void test_heap_sort() /*Post: 进行堆排序的测试. */ { Sortable_list<Key> the_list; for(int i = 0; i < 10; i++)the_list.insert_array(i, Key(10-i)); cout << "The list is:" << endl; the_list.traverse_array(print); cout << endl << "Use heap_sort Method:" << endl; the_list.heap_sort(); the_list.traverse_array(print); } int main() { //test_insertion_sort(); //test_selection_sort(); //test_shell_sort(); //test_merge_sort(); //test_quick_sort(); //test_heap_sort(); return 0; }