├── Binary-search ├── Makefile ├── binarySearch.h ├── generateTestData.cpp └── test.cpp ├── README.md ├── hash_table ├── chain_hash_table │ ├── Makefile │ ├── chain_hash_table.h │ ├── chain_hash_table_test.cpp │ └── hash.h ├── open_addressing_hash_table │ ├── Makefile │ ├── hash.h │ ├── open_addressing_hash_table.h │ └── open_addressing_hash_table_test.cpp └── perfect_hashing │ ├── Makefile │ ├── hash.h │ ├── perfect_hashing.h │ └── perfect_hashing_test.cpp ├── interesting_algorithm ├── gcd_algorithm │ ├── Makefile │ ├── gcd.h │ └── gcd_test.cpp └── pow_algorithm │ ├── Makefile │ ├── recursionPow.h │ └── recursionPow_test.cpp ├── list_algorithm ├── circular_list │ ├── Makefile │ ├── circularList.h │ └── circularList_test.cpp ├── doublyLinkedListNode │ ├── Makefile │ ├── doublyLinkedListNode.h │ └── doublyLinkedListNode_test.cpp ├── doubly_linked_list │ ├── Makefile │ ├── doublyLinkedList.h │ └── doublyLinkedList_test.cpp ├── list │ ├── Makefile │ ├── list.h │ └── list_test.cpp └── listNode │ ├── ListNode.h │ ├── ListNode_test.cpp │ └── Makefile ├── queue_algorithm ├── min_queue │ ├── Makefile │ ├── minqueue.h │ └── minqueue_test.cpp └── queue │ ├── Makefile │ ├── queue.h │ └── queue_test.cpp ├── select_algorithm ├── good_select │ ├── Makefile │ ├── goodSelect.h │ └── goodSelect_test.cpp ├── minimum │ ├── Makefile │ ├── minimum.h │ └── minimum_test.cpp └── randomized_select │ ├── Makefile │ ├── randomizedSelect.h │ └── randomizedSelect_test.cpp ├── sort_algorithm ├── bucket_sort │ ├── Makefile │ ├── bucketSort.h │ └── bucketSort_test.cpp ├── counting_sort │ ├── Makefile │ ├── countingSort.h │ └── countingSort_test.cpp ├── heap_sort │ ├── Makefile │ ├── heapSort.h │ └── heapSort_test.cpp ├── insert_sort │ ├── Makefile │ ├── insertSort.h │ └── insertSortTest.cpp ├── merge_sort │ ├── Makefile │ ├── mergeSort.h │ └── mergeSort_test.cpp ├── quick_sort │ ├── Makefile │ ├── quickSort.h │ └── quickSort_test.cpp └── radix_sort │ ├── Makefile │ ├── radixSort.h │ └── radixSort_test.cpp ├── stack_algorithm ├── Makefile ├── stack.h └── stack_test.cpp ├── subset_algorithm ├── merge_subset_sum │ ├── Makefile │ ├── mergeSubsetSum.h │ └── mergeSubsetSum_test.cpp ├── online_subset_sum │ ├── Makefile │ ├── onlineSubsetSum.h │ └── onlineSubsetSum_test.cpp └── original_subset_sum │ ├── Makefile │ ├── originalSubsetSum.h │ └── originalSubsetSum_Test.cpp └── tree_algorithm ├── RedBlackTree ├── Makefile ├── RedBlackTree.h └── RedBlackTree_test.cpp ├── RedBlackTreeNode ├── Makefile ├── RedBlackTreeNode.h └── RedBlackTreeNode_test.cpp ├── binary_search_tree ├── Makefile ├── binary_search_tree.h └── binary_search_tree_test.cpp ├── binarytree ├── Makefile ├── binarytree.h └── binarytree_test.cpp └── binarytreeNode ├── Makefile ├── binarytreeNode.h └── binarytreeNode_test.cpp /Binary-search/Makefile: -------------------------------------------------------------------------------- 1 | cc = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: generateTestData test 6 | 7 | generateTestData: generateTestData.cpp 8 | $(cc) $(VERSION) -o generateTestData generateTestData.cpp 9 | 10 | test: test.cpp binarySearch.h 11 | $(cc) $(VERSION) -o test test.cpp 12 | 13 | clean: 14 | rm binarySearch.o 15 | -------------------------------------------------------------------------------- /Binary-search/binarySearch.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: binarySearch.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年10月18日 星期四 13时07分43秒 6 | ************************************************************************/ 7 | 8 | #ifndef BINARYSEARCH_H 9 | #define BINARYSEARCH_H 10 | // 在给定的从小到大排序好的数列中查找一个给定的数 11 | // ,如果存在返回下标如果不存在返回-1 12 | #include 13 | 14 | template 15 | int binarySearch(const std::vector &a, const Comparable x) 16 | { 17 | decltype(a.size()) low = 0, high = a.size() - 1; 18 | 19 | while (low <= high){ 20 | auto mid = (high + low) / 2; 21 | if (a[mid] < x) 22 | low = mid + 1; 23 | else if (a[mid] > x) 24 | high = mid - 1; 25 | else 26 | return mid; 27 | } 28 | 29 | return -1; 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /Binary-search/generateTestData.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: generateTestData.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年10月18日 星期四 13时25分43秒 6 | ************************************************************************/ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | void generateData(const std::string filename, size_t num) 13 | { 14 | std::ofstream out(filename); 15 | std::uniform_int_distribution u(-100,100); 16 | std::default_random_engine e; 17 | 18 | for (size_t i = 0; i != num; i++) 19 | out << u(e) << "\t" << u(e) << "\n"; 20 | out.close(); 21 | } 22 | 23 | int main(void) 24 | { 25 | generateData("testData", 100); 26 | 27 | return 0; 28 | } 29 | 30 | 31 | -------------------------------------------------------------------------------- /Binary-search/test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年10月18日 星期四 13时34分26秒 6 | ************************************************************************/ 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "binarySearch.h" 13 | 14 | template 15 | void readData(const std::string filename, std::vector &vec) 16 | { 17 | std::ifstream in(filename); 18 | T value; 19 | while (in >> value) 20 | vec.push_back(value); 21 | } 22 | 23 | int main(void) 24 | { 25 | std::vector data; 26 | readData("testData", data); 27 | sort(data.begin(), data.end()); 28 | int value = 57; 29 | int sign = binarySearch(data, value); 30 | std::cout << "****************************************************" << std::endl; 31 | for (decltype(data.size()) i = 0; i != data.size(); i++) 32 | std::cout << i << "\t" << data[i] << "\n"; 33 | std::cout << "****************************************************" << std::endl; 34 | std::cout << value << "在顺序数组的第" << sign << std::endl; 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction-to-Algorithms-for-Cplusepluse 2 | 算法导论(第三版)----C++实现. 3 | 4 | 基于C++11标准(全部实现为模板故都放在.h文件中),并给出Makefile文件(基于ubuntu(linux)). 5 | 6 | 代码实现中所有的指针均优先采用C++11新标准建议的智能指针. 7 | ### Binary-search 二分搜索算法 8 | --Binary_search/binarySearch.h: 二分搜索算法 9 | ### hash_table 散列表 10 | --chain_hash_table/chain_hash_table.h: 链接法实现散列表 11 | --open_addressing_hash_table/open_addressing_hash_table.h: 开放寻址法实现散列表 12 | --perfect_hashing/perfect_hashing.h: 完全散列表 13 | ### interesting_algorithm 感兴趣的算法 14 | --gcd_algorithm/gcd.h: 欧几里得算法求解最大公因数 15 | --pow_algorithm/recursionPow.h: 递归求幂运算 16 | ### list_algorithm 链表算法 17 | --circular_list/circularList.h: 带有哨兵的双向循环链表 18 | --doubly_linked_list/doublyLinkedList.h: 双向链表 19 | --doublyLinkedListNode/doublyLinkedListNode.h: 双向链表/循环链表的节点数据类型 20 | --list/list.h: 单向链表 21 | --listNode/ListNode.h: 单向链表的节点数据类型 22 | ### queue_algorithm 队列算法 23 | --min_queue/min_queue.h: 最小优先队列 24 | --queue/queue.h: 单端队列 25 | ### select_algorithm 选择算法 26 | --good_select/goodSelect.h: 最坏情况下为线性时间的选择算法 27 | --minimum/minimum.h: 从一个集合中选择最小(最大)元素 28 | --randomized_select/randomizedSelect.h: 随机选择算法(期望为线性时间的选择算法) 29 | ### sort_algorithm 排序算法 30 | --bucket_sort/bucketSort.h: 桶排序 31 | --counting_sort/countingSort.h: 计数排序 32 | --heap_sort/heapSort.h: 堆排序 33 | --insert_sort/insertSort.h: 插入排序 34 | --merge_sort/mergeSort.h: 归并排序 35 | --quick_sort/quickSort.h: 快速排序 36 | --radix_sort/radixSort.h: 基数排序 37 | ### stack_algorithm 栈算法 38 | --stack_algorithm/stack.h: 栈 39 | ### subset_algorithm 子序列算法 40 | --merge_subset_sum/mergeSubsetSum.h: 寻找最大相连子序列和的递归算法 41 | --online_subset_sum/onlineSubsetSum.h: 寻找最大相连子序列和的在线算法 42 | --original_subset_sum/originalSubsetSum.h: 寻找最大相连子序列和的暴力算法 43 | ### tree_algorithm 树算法 44 | --Binary_search_tree/binary_search_tree.h: 二叉搜索树 45 | --binarytree/binarytree.h: 二叉树 46 | --binarytreeNode/binarytreeNode.h: 二叉树的节点数据类型 47 | --RedBlackTree/RedBlackTree.h: 红黑树 48 | --RedBlackTreeNode/RedBlackTreeNode.h: 红黑树的节点数据类型 49 | -------------------------------------------------------------------------------- /hash_table/chain_hash_table/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: hash.h chain_hash_table.h chain_hash_table_test.cpp 8 | $(c++) $(VERSION) -o Test chain_hash_table_test.cpp 9 | -------------------------------------------------------------------------------- /hash_table/chain_hash_table/chain_hash_table.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: chain_hash_table.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月18日 星期日 20时54分22秒 6 | ************************************************************************/ 7 | 8 | #ifndef _CHAIN_HASH_TABLE_H 9 | #define _CHAIN_HASH_TABLE_H 10 | #include 11 | #include 12 | #include 13 | #include 14 | // HashTable: 分离链接法(双向链表结构)处理冲突情况的散列表. 算法导论11.2 11.3 15 | /* 16 | * 简而言之,散列就是一种用以常数平均时间执行插入,删除的技术.但是元素间排序将不会 17 | * 得到支持.可以把散列理解为介于链表与二叉树之间的数据结构. 18 | * 19 | * 散列最主要的问题就是确定散列函数,以解决冲突问题.(当两个关键字散列到一个值的时候产生冲突). 20 | * 21 | * 解决冲突的方法最简单的有两种: 分离链接法和开放定址法. 22 | */ 23 | template 24 | class HashTable 25 | { 26 | public: 27 | //typedef typename HashedObj::ValueType valueType; 28 | //***************************构造函数********************************* 29 | explicit HashTable(std::size_t size = 101): currentSize(0) {theLists.resize(size);} 30 | ~HashTable()=default; 31 | //***************************成员函数********************************* 32 | bool contains(const HashedObj &x) const; // 向散列表中查询一个元素 33 | void makeEmpty(); // 清空散列表 34 | bool insert(const HashedObj &x); // 向散列表中插入一个元素 35 | bool remove(const HashedObj &x); // 向散列表中删除一个元素 36 | private: 37 | //***************************数据结构********************************* 38 | std::vector> theLists; // 链表的数组 39 | std::size_t currentSize; // 哈希数组大小 40 | //***************************私有成员函数***************************** 41 | void rehash(); 42 | std::size_t myhash(const HashedObj &x) const; 43 | }; 44 | //***************************私有成员函数********************************* 45 | // rehash: 重新建立hash表. 46 | template 47 | void HashTable::rehash() 48 | { 49 | theLists.resize(0); 50 | currentSize = 0; 51 | } 52 | // myhash: 将HashedObj的值转换为数组的下标 53 | /* 54 | * \parameter x: 待转换的元素; 55 | * \return 数组下标. 56 | */ 57 | template 58 | std::size_t HashTable::myhash(const HashedObj &x) const 59 | { 60 | std::size_t hashIndex = x.getIndex(); 61 | // 除法散列法 62 | /* 63 | * 关于除法散列函数: 选取m(theLists.size())的值特别重要,一个不太接近2的整数幂的素数,常常是 64 | * m的一个较好的选择. 65 | */ 66 | 67 | //hashIndex = hashIndex % theLists.size(); 68 | 69 | // 乘法散列法 70 | /* 71 | * 关于乘法散列函数: 包含两个步骤: 72 | * --第一步,用关键字k乘上常数A(0(indexValue); 78 | hashIndex = std::floor(101 * indexValue); 79 | 80 | // 全域散列法 81 | /* 82 | * 任何一个特定的散列函数都会出现将n个关键字全部散列到同一个槽中,使得品均的检索时间为O(N),这个就是令人恐怖的最坏的情况. 83 | * 唯一有效的改进方法就是随机地选择散列函数,使之独立于要存储的关键字,这种方法称为全域散列.不管选择了怎样的关键字,其品均 84 | * 性能都比较好. 85 | * 86 | * 全域散列法在执行的开始,就从一组精心设计的函数中,随机选择一个作为散列函数.就像在快速排序中一样,随机化保证了没有哪一种 87 | * 输入会始终导致最坏的情况性能. 88 | */ 89 | return hashIndex; 90 | } 91 | //***************************成员函数************************************* 92 | // contains: 检查成员是否被包含在hash table中. 93 | /* 94 | * \parameter x: 待检查的元素; 95 | * \return 返回这个元素是否存在于hash table中. 96 | */ 97 | template 98 | bool HashTable::contains(const HashedObj &x) const 99 | { 100 | auto &whichList = theLists[myhash(x)]; 101 | return std::find(whichList.begin(), whichList.end(), x) != whichList.end(); 102 | } 103 | // makeEmpty: 把hash table置空. 104 | /* 105 | * \return void. 106 | * 将hash table置空以后. 107 | */ 108 | template 109 | void HashTable::makeEmpty() 110 | { 111 | for (auto &thisList : theLists) 112 | thisList.clear(); 113 | } 114 | // insert: 将一个元素插入到hash table 中 115 | /* 116 | * \parameter x: 一个待插入的元素; 117 | * \return 插入是否成功的标志. 118 | * 当元素在hash table中插入不成功,返回false; 119 | * 当元素不在hash table中,插入到链表的最尾端,返回true. 120 | */ 121 | template 122 | bool HashTable::insert(const HashedObj &x) 123 | { 124 | auto &whichList = theLists[myhash(x)]; 125 | if (std::find(whichList.begin(), whichList.end(), x) != whichList.end() && 126 | whichList.begin() != whichList.end()) 127 | return false; 128 | whichList.push_back(x); 129 | ++currentSize; 130 | return true; 131 | } 132 | // remove: 将一个元素从hash table中删除. 133 | /* 134 | * \parameter x: 一个待删除的元素; 135 | * \return 返回是否删除成功的标志. 136 | * 当元素在hash table中删除成功,返回true; 137 | * 当元素不在hash table中,删除不成功,返回false. 138 | */ 139 | template 140 | bool HashTable::remove(const HashedObj &x) 141 | { 142 | auto &whichList = theLists[myhash(x)]; 143 | auto iter = std::find(whichList.begin(), whichList.end(), x); 144 | if (iter == whichList.end()) 145 | return false; 146 | whichList.erase(iter); 147 | --currentSize; 148 | return true; 149 | } 150 | #endif 151 | -------------------------------------------------------------------------------- /hash_table/chain_hash_table/chain_hash_table_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: chain_hash_table_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月21日 星期三 17时13分53秒 6 | ************************************************************************/ 7 | #include 8 | #include 9 | #include "hash.h" 10 | #include "chain_hash_table.h" 11 | typedef Hash IHash; 12 | typedef HashTable> Hashtable; 13 | 14 | void inserts_test() 15 | { 16 | Hashtable hashTable; 17 | bool sign = hashTable.insert({"cat",1234}); 18 | std::cout << "'cat, 1234'是否插入成功: " << sign << std::endl; 19 | sign = hashTable.insert({"cat",1234}); 20 | std::cout << "再次插入'cat, 1234'是否插入成功: " << sign << std::endl; 21 | sign = hashTable.insert({"Cat",111}); 22 | std::cout << "'Cat,111'是否插入成功: " << sign << std::endl; 23 | hashTable.insert({"cat",123}); 24 | std::cout <<"'zhi,123'是否插入成功: " << sign << std::endl; 25 | } 26 | 27 | void contains_test() 28 | { 29 | Hashtable hashTable; 30 | hashTable.insert({"cat",1234}); 31 | hashTable.insert({"Cat",111}); 32 | hashTable.insert({"cat",123}); 33 | hashTable.insert({"ss",987}); 34 | 35 | bool sign = hashTable.contains({"cat",1234}); 36 | std::cout << "'cat, 1234'是否存在hash table中: " << sign << std::endl; 37 | 38 | sign = hashTable.contains({"Cat", 111}); 39 | std::cout << "'Cat,111'是否在hash table中: " << sign << std::endl; 40 | 41 | sign = hashTable.contains({"cat", 123}); 42 | std::cout << "'cat,123'是否在hash table中: " << sign << std::endl; 43 | 44 | sign = hashTable.contains({"ss",987}); 45 | std::cout << "'ss,987'是否在hash table中: " << sign << std::endl; 46 | 47 | sign = hashTable.contains({"ZHH",110}); 48 | std::cout << "'ZHH',110是否在hash table中: " << sign << std::endl; 49 | } 50 | 51 | void remove_test() 52 | { 53 | Hashtable hashTable; 54 | hashTable.insert({"cat",1234}); 55 | hashTable.insert({"Cat",111}); 56 | hashTable.insert({"cat",123}); 57 | hashTable.insert({"ss",987}); 58 | 59 | //hashTable.makeEmpty(); 60 | bool sign = hashTable.remove({"cat", 1234}); 61 | std::cout << "'cat, 1234'是否删除成功: " << sign << std::endl; 62 | std::cout << "'cat, 1234'是否还在hash table中: " 63 | << hashTable.contains({"cat",1234}) << std::endl; 64 | 65 | sign = hashTable.remove({"Cat", 111}); 66 | std::cout << "'Cat, 111'是否删除成功: " << sign << std::endl; 67 | std::cout << "'Cat, 111'是否还在hash table中: " 68 | << hashTable.contains({"Cat",111}) << std::endl; 69 | 70 | sign = hashTable.remove({"cat", 123}); 71 | std::cout << "'cat, 123'是否删除成功: " << sign << std::endl; 72 | std::cout << "'cat, 123'是否还在hash table中: " 73 | << hashTable.contains({"cat",123}) << std::endl; 74 | 75 | sign = hashTable.remove({"ss", 987}); 76 | std::cout << "'ss, 987'是否删除成功: " << sign << std::endl; 77 | std::cout << "'ss, 987'是否还在hash table中: " 78 | << hashTable.contains({"ss",987}) << std::endl; 79 | } 80 | int main() 81 | { 82 | std::cout << "********hash table的insert测试********\n"; 83 | inserts_test(); 84 | std::cout << "********hash table的contains测试*******\n"; 85 | contains_test(); 86 | std::cout << "********hash table的remove测试********\n"; 87 | remove_test(); 88 | 89 | return 0; 90 | } 91 | 92 | 93 | -------------------------------------------------------------------------------- /hash_table/chain_hash_table/hash.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: hash.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月21日 星期三 16时32分18秒 6 | ************************************************************************/ 7 | 8 | #ifndef _HASH_H 9 | #define _HASH_H 10 | #include 11 | // 散列表中存储的数据类型 12 | template 13 | class Hash 14 | { 15 | public: 16 | typedef value_type ValueType; 17 | //*************************构造函数*********************************** 18 | Hash() = default; // 默认构造函数 19 | Hash(key_type v0, value_type v1): key(v0), value(v1) { } 20 | friend bool operator==(const Hash& hash1, const Hash& hash2) 21 | { 22 | if (hash1.key == hash2.key && hash1.value == hash2.value) 23 | return true; 24 | else 25 | return false; 26 | } 27 | //***********************公有成员函数********************************* 28 | std::size_t getIndex() const 29 | { 30 | std::size_t hashIndx = 0; 31 | for (auto ch : key) 32 | hashIndx += ch * 128; 33 | return hashIndx; 34 | } 35 | //*************************数据成员*********************************** 36 | key_type key; // hash table的键 37 | value_type value; // hash table的值 38 | }; 39 | #endif 40 | -------------------------------------------------------------------------------- /hash_table/open_addressing_hash_table/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: open_addressing_hash_table_test.cpp open_addressing_hash_table.h hash.h 8 | $(c++) $(VERSION) -o Test open_addressing_hash_table_test.cpp 9 | -------------------------------------------------------------------------------- /hash_table/open_addressing_hash_table/hash.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: hash.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月22日 星期四 09时43分29秒 6 | ************************************************************************/ 7 | 8 | #ifndef _HASH_H 9 | #define _HASH_H 10 | #include 11 | // 散列表中存储的数据 12 | template 13 | class Hash 14 | { 15 | public: 16 | typedef value_type ValueType; // 指向的数据类型 17 | //**************************构造函数*********************************** 18 | Hash() = default; // 默认构造函数 19 | Hash(key_type v0, value_type v1): key(v0), value(v1) { } 20 | ~Hash() = default; 21 | friend bool operator==(const Hash &hash1, const Hash &hash2) 22 | { 23 | if (hash1.key == hash2.key && hash1.value == hash2.value) 24 | return true; 25 | else 26 | return false; 27 | } 28 | //**************************公有成员函数******************************* 29 | std::size_t getIndex() const 30 | { 31 | std::size_t hashIndex = 0; 32 | for (auto x : key) 33 | hashIndex += x * 128; 34 | return hashIndex; 35 | } 36 | //**************************数据成员*********************************** 37 | key_type key; // hash table 键 38 | value_type value; // hash table值 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /hash_table/open_addressing_hash_table/open_addressing_hash_table.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: open_addressing_hash_table.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月22日 星期四 08时40分05秒 6 | ************************************************************************/ 7 | 8 | #ifndef _OPEN_ADDRESSING_HASH_TABLE_H 9 | #define _OPEN_ADDRESSING_HASH_TABLE_H 10 | #include 11 | // HashTable: 开放寻址法实现散列 算法导论11.4 12 | /* 13 | * 开放寻址法的好处就在于它不用指针,而是计算出要存取的槽序列.于是,不用存储 14 | * 指针而节省的空间,使得可以用同样的空间来提供更多的槽,潜在的减少了冲突,提高了 15 | * 检索速度. 16 | */ 17 | template 18 | class HashTable 19 | { 20 | public: 21 | //***************************枚举类型********************************* 22 | enum ELE_STATUS{ 23 | EMPTY = 0, // 空的 24 | DELETE = 1, // 被删除的 25 | FULL = 2, // 有元素的 26 | }; 27 | //***************************构造函数********************************* 28 | // 构造函数 29 | HashTable(std::size_t num = 101): size(0){hashData.resize(num); status.resize(num);} 30 | ~HashTable() = default; // 析构函数 31 | //***************************成员函数********************************* 32 | bool insert(const HashedObj &); // 向散列表中插入一个元素 33 | bool search(const HashedObj &); // 向散列表中查找一个元素 34 | bool hash_delete(const HashedObj &); // 向散列表中删除一个元素 35 | void hash_clear(); // 清空散列表 36 | private: 37 | //***************************数据成员********************************* 38 | std::vector hashData; // 散列表的数组 39 | std::size_t size; // 散列表中存储数据的数量 40 | std::vector status; // 用于存放各个位置的状态信息 41 | //*************************私有成员函数******************************* 42 | std::size_t hash(const HashedObj &); // 辅助散列函数(除法散列函数) 43 | std::size_t hash2(const HashedObj &); // 双重散列函数的辅助函数 44 | std::size_t linear_probing(const HashedObj &, std::size_t); // 线性探查 45 | std::size_t quadratic_probing(const HashedObj &, std::size_t); // 二次探查 46 | std::size_t double_hashing(const HashedObj &, std::size_t); // 双重散列 47 | }; 48 | // hash: 辅助散列函数(除法散列函数) 49 | template 50 | std::size_t HashTable::hash(const HashedObj &hashed) 51 | { 52 | std::size_t index = hashed.getIndex(); 53 | index = index % hashData.size(); 54 | return index; 55 | } 56 | // hash2: 双重散列函数的辅助函数 57 | template 58 | std::size_t HashTable::hash2(const HashedObj &hashed) 59 | { 60 | std::size_t index = hashed.getIndex(); 61 | index = index % (hashData.size() - 1) + 1; 62 | return index; 63 | } 64 | // linear_probing: 线性探查 65 | /* 66 | * \parameter hashed: hash table存储的数据类型; 67 | * \parameter offset: 线性探查公式中的i; 68 | * \return 返回线性探查结果的下标. 69 | * 算法思想: h(k,i) = (h(k) + i) mod m, i = 0,1,2,...,m-1 70 | * 线性探查方法比较容易实现,但它存在着一个问题,称为一次聚集. 随着连续被占用的槽不断增加,平均 71 | * 查找时间也随之不断增加.群集现象很容易出现,这是因为当一个空槽前有i个满的槽时,该空槽为下一个被 72 | * 占用的概率为(i+1)/m.连续被占用的槽就会变得越来越长,因而平均查找时间也会越来越大. 73 | */ 74 | template 75 | std::size_t HashTable::linear_probing(const HashedObj &hashed, std::size_t offset) 76 | { 77 | return (hash(hashed) + offset) % hashData.size(); 78 | } 79 | // quadratic_probing: 二次探查 80 | /* 81 | * \parameter hashed: hash table存储的数据类型; 82 | * \parameter offset: 二次查探函数中的i; 83 | * \return 返回二次查探结果的下标. 84 | * 算法思想: h(k,i) = (h(k) + c1*i + c2*i*i) mod m, i = 0,1,2,...,m-1 85 | * 二次查探的性质比线性查探的性质好很多,但是h(k1,0) = h(k2,0)蕴含着h(k1,i) = h(k2,i). 86 | * 这一性质可导致一种轻度的群集,称为二次群集. 87 | */ 88 | template 89 | std::size_t HashTable::quadratic_probing(const HashedObj &hashed, std::size_t offset) 90 | { 91 | return (hash(hashed) + offset + offset * offset) % hashData.size(); 92 | } 93 | // double_hashing: 双重散列 94 | /* 95 | * \parameter hashed: hash table存储的数据类型; 96 | * \parameter offset: 双重查探函数中的i; 97 | * \return 返回双重查探结果的下标. 98 | * 算法思想: h(k,i) = (h1(k) + i*h2(k)) mod m; i = 0,1,2,3,...,m-1. 99 | * 双重散列是用于开放寻址的最好方法之一,因为它所产生的排列具有随机选择排序的许多特征. 100 | * 101 | * 为了能查找整个散列表,值h2(k)必须要与表的大小m互素.有一种简便的方法确保这个条件成立,就是 102 | * 取m为2的幂,并设计一个总产生奇数的h2. 103 | * 另一种方法是取m为素数,并设计一个总返回较m小的正整数的函数h2. 104 | * --例如,我们可以取m为素数,并取h1(k) = k mod m, h2(k) = 1 + (k mod m') 105 | * 其中m'略小于m(比如,m-1). 106 | */ 107 | template 108 | std::size_t HashTable::double_hashing(const HashedObj &hashed, std::size_t offset) 109 | { 110 | std::size_t index0 = hash(hashed); 111 | std::size_t index1 = hash2(hashed); 112 | return (index0 + offset * index1) % hashData.size(); 113 | } 114 | 115 | //*******************************函数接口********************************* 116 | // insert: 插入操作 117 | /* 118 | * \parameter hash: 待插入的元素; 119 | * \return 返回插入是否成功的标志. 120 | */ 121 | template 122 | bool HashTable::insert(const HashedObj &hash) 123 | { 124 | if (size >= hashData.size()){ 125 | std::cerr << "hash table overflow!" << std::endl;; 126 | return false; 127 | } 128 | std::size_t i = 0; 129 | while (i != hashData.size()){ 130 | //std::size_t index = linear_probing(hash, i); 131 | //std::size_t index = quadratic_probing(hash, i); 132 | std::size_t index = double_hashing(hash, i); 133 | if (status[index] != FULL){ 134 | hashData[index] = hash; 135 | status[index] = FULL; 136 | ++size; 137 | return true; 138 | } 139 | ++i; 140 | } 141 | std::cerr << "hash table overflow!" << std::endl; 142 | return false; 143 | } 144 | // search: 查询操作 145 | /* 146 | * \parameter hashed: 待查找的元素; 147 | * \return 返回查找是否成功的标志. 148 | */ 149 | template 150 | bool HashTable::search(const HashedObj &hashed) 151 | { 152 | std::size_t i = 0; 153 | while (i != hashData.size()){ 154 | //std::size_t index = linear_probing(hashed, i); 155 | //std::size_t index = quadratic_probing(hashed, i); 156 | std::size_t index = double_hashing(hashed, i); 157 | if (status[index] == EMPTY) 158 | return false; 159 | else if (status[index] == FULL){ 160 | if (hashData[index] == hashed) 161 | return true; 162 | } 163 | ++i; 164 | } 165 | return false; 166 | } 167 | // hash_delete: 删除操作 168 | /* 169 | * \parameter hashed: 待删除的元素; 170 | * \return 删除是否成功的标志. 171 | */ 172 | template 173 | bool HashTable::hash_delete(const HashedObj &hashed) 174 | { 175 | std::size_t i = 0; 176 | while (i != hashData.size()){ 177 | //std::size_t index = linear_probing(hashed, i); 178 | //std::size_t index = quadratic_probing(hashed, i); 179 | std:;size_t index = double_hashing(hashed, i); 180 | if (status[index] == EMPTY) 181 | return false; 182 | else if (status[index] == FULL){ 183 | if (hashData[index] == hashed){ 184 | status[index] = DELETE; 185 | return true; 186 | --size; 187 | } 188 | } 189 | ++i; 190 | } 191 | return false; 192 | } 193 | // hash_clear: 清空散列表 194 | /* 195 | * 只需对状态数组修改就行. 196 | */ 197 | template 198 | void HashTable::hash_clear() 199 | { 200 | size = 0; 201 | for (auto &i : status) 202 | i = EMPTY; 203 | } 204 | #endif 205 | -------------------------------------------------------------------------------- /hash_table/open_addressing_hash_table/open_addressing_hash_table_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: open_addressing_hash_table_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月22日 星期四 10时15分33秒 6 | ************************************************************************/ 7 | #include 8 | #include 9 | #include "hash.h" 10 | #include "open_addressing_hash_table.h" 11 | typedef Hash IHash; 12 | typedef HashTable> Hashtable; 13 | 14 | void inserts_test() 15 | { 16 | Hashtable hashTable; 17 | bool sign = hashTable.insert({"cat",1234}); 18 | std::cout << "'cat, 1234'是否插入成功: " << sign << std::endl; 19 | sign = hashTable.insert({"cat",1234}); 20 | std::cout << "再次插入'cat, 1234'是否插入成功: " << sign << std::endl; 21 | sign = hashTable.insert({"Cat",111}); 22 | std::cout << "'Cat,111'是否插入成功: " << sign << std::endl; 23 | sign = hashTable.insert({"cat",123}); 24 | std::cout <<"'zhi,123'是否插入成功: " << sign << std::endl; 25 | } 26 | 27 | void search_test() 28 | { 29 | Hashtable hashTable; 30 | hashTable.insert({"cat",1234}); 31 | hashTable.insert({"Cat",111}); 32 | hashTable.insert({"cat",123}); 33 | hashTable.insert({"ss",987}); 34 | 35 | bool sign = hashTable.search({"cat",1234}); 36 | std::cout << "'cat, 1234'是否存在hash table中: " << sign << std::endl; 37 | 38 | sign = hashTable.search({"Cat", 111}); 39 | std::cout << "'Cat,111'是否在hash table中: " << sign << std::endl; 40 | 41 | sign = hashTable.search({"cat", 123}); 42 | std::cout << "'cat,123'是否在hash table中: " << sign << std::endl; 43 | 44 | sign = hashTable.search({"ss",987}); 45 | std::cout << "'ss,987'是否在hash table中: " << sign << std::endl; 46 | 47 | sign = hashTable.search({"ZHH",110}); 48 | std::cout << "'ZHH',110是否在hash table中: " << sign << std::endl; 49 | } 50 | 51 | void hash_delete_test() 52 | { 53 | Hashtable hashTable; 54 | hashTable.insert({"cat",1234}); 55 | hashTable.insert({"Cat",111}); 56 | hashTable.insert({"cat",123}); 57 | hashTable.insert({"ss",987}); 58 | 59 | //hashTable.hash_clear(); 60 | bool sign = hashTable.hash_delete({"cat", 1234}); 61 | std::cout << "'cat, 1234'是否删除成功: " << sign << std::endl; 62 | std::cout << "'cat, 1234'是否还在hash table中: " 63 | << hashTable.search({"cat",1234}) << std::endl; 64 | 65 | sign = hashTable.hash_delete({"Cat", 111}); 66 | std::cout << "'Cat, 111'是否删除成功: " << sign << std::endl; 67 | std::cout << "'Cat, 111'是否还在hash table中: " 68 | << hashTable.search({"Cat",111}) << std::endl; 69 | 70 | sign = hashTable.hash_delete({"cat", 123}); 71 | std::cout << "'cat, 123'是否删除成功: " << sign << std::endl; 72 | std::cout << "'cat, 123'是否还在hash table中: " 73 | << hashTable.search({"cat",123}) << std::endl; 74 | 75 | sign = hashTable.hash_delete({"ss", 987}); 76 | std::cout << "'ss, 987'是否删除成功: " << sign << std::endl; 77 | std::cout << "'ss, 987'是否还在hash table中: " 78 | << hashTable.search({"ss",987}) << std::endl; 79 | } 80 | 81 | int main() 82 | { 83 | std::cout << "********hash table的insert测试********\n"; 84 | inserts_test(); 85 | std::cout << "********hash table的search测试*******\n"; 86 | search_test(); 87 | std::cout << "********hash table的hash_delete测试********\n"; 88 | hash_delete_test(); 89 | 90 | return 0; 91 | } 92 | 93 | -------------------------------------------------------------------------------- /hash_table/perfect_hashing/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: perfect_hashing_test.cpp perfect_hashing.h hash.h 8 | $(c++) $(VERSION) -o Test perfect_hashing_test.cpp 9 | -------------------------------------------------------------------------------- /hash_table/perfect_hashing/hash.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: hash.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月22日 星期四 17时29分58秒 6 | ************************************************************************/ 7 | 8 | #ifndef _HASH_H 9 | #define _HASH_H 10 | #include 11 | // 散列表中存储的数据 12 | template 13 | class Hash 14 | { 15 | public: 16 | typedef value_type ValueType; // 指向的数据类型 17 | //**************************构造函数*********************************** 18 | Hash(): value(0){ }; // 默认构造函数 19 | Hash(key_type v0, value_type v1): key(v0), value(v1) { } 20 | ~Hash() = default; 21 | friend bool operator==(const Hash &hash1, const Hash &hash2) 22 | { 23 | if (hash1.key == hash2.key && hash1.value == hash2.value) 24 | return true; 25 | else 26 | return false; 27 | } 28 | //**************************公有成员函数******************************* 29 | std::size_t getIndex() const 30 | { 31 | std::size_t hashIndex = 0; 32 | for (auto x : key) 33 | hashIndex += x * 128; 34 | return hashIndex; 35 | } 36 | //**************************数据成员*********************************** 37 | key_type key; // hash table 键 38 | value_type value; // hash table值 39 | }; 40 | #endif 41 | -------------------------------------------------------------------------------- /hash_table/perfect_hashing/perfect_hashing.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: perfect_hashing.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月22日 星期四 16时20分45秒 6 | ************************************************************************/ 7 | #ifndef _PERFECT_HASHING_H 8 | #define _PERFECT_HASHING_H 9 | #include 10 | #include 11 | // Function: 散列函数的系数 12 | struct Function 13 | { 14 | std::size_t a; // 二级散列函数((a*k+b) mod p) mod m 15 | std::size_t b; 16 | std::size_t p; 17 | std::size_t m; 18 | }; 19 | // 待使用的随机产生的散列函数的系数 20 | std::default_random_engine e; 21 | // HashTable: 完全散列 算法导论11.5 22 | /* 23 | * 如果从全域散列函数类中随机选出散列函数h,将n个关键字存储在一个大小为m=n^2的散列表中 24 | * 那么表中出现冲突的概率小于1/2. 25 | * 26 | * 使用散列技术通常是个很好的选择,不仅是因为它有优异的平均情况性能,而且当关键字集合是静态的 27 | * 时候,散列技术也能提供出色的最坏情况性能.所谓静态,就是指一旦各关键字存入表中,关键字集合就不再 28 | * 改变. 29 | * 30 | * 完全散列方法,如果对该方法进行查找的时候,能在最坏情况下用O(1)次访存完成. 31 | */ 32 | template 33 | class HashTable 34 | { 35 | public: 36 | //**************************结构函数********************************** 37 | HashTable(std::size_t num = 2): size(0){hashData.resize(num); function.resize(num);} 38 | ~HashTable() = default; // 析构函数 39 | //**************************成员函数********************************** 40 | bool initialization(const std::vector &); // hash table 初始化 41 | bool search(const HashedObj &); // hash table 查询操作 42 | bool insert(const HashedObj &); // hash table 插入操作 43 | bool hash_delete(const HashedObj &); // hash table 删除操作 44 | private: 45 | //**************************数据成员********************************** 46 | std::vector> hashData; // 散列表的数组 47 | std::size_t size; // 散列表中存储数据的数量 48 | std::vector function; // 散列函数的系数 49 | //***********************私有成员函数********************************* 50 | std::size_t hash(const HashedObj &); // 一级hash table的散列函数 51 | void random_hash(const std::vector &); // 二级hash table随机散列函数 52 | void random_hash(const std::size_t); // 重载二级hash table随机散列函数 53 | std::size_t hash2(const HashedObj &); // 二级hash table散列函数 54 | }; 55 | // hash: 一级散列函数 56 | template 57 | std::size_t HashTable::hash(const HashedObj &hashed) 58 | { 59 | std::size_t hashIndex = hashed.getIndex(); 60 | hashIndex = ((3 * hashIndex + 42) % 101) % hashData.size(); 61 | return hashIndex; 62 | } 63 | // random_hash: 二级随机散列函数 64 | template 65 | void HashTable::random_hash(const std::vector &numbers) 66 | { 67 | 68 | for (decltype(numbers.size()) i = 0; i != numbers.size(); ++i){ 69 | if (numbers[i] == 1){ 70 | function[i].a = 0; 71 | function[i].b = 0; 72 | function[i].p = e(); 73 | function[i].m = numbers[i]; 74 | } 75 | else{ 76 | function[i].a = e(); 77 | function[i].b = e(); 78 | function[i].p = e(); 79 | function[i].m = numbers[i]; 80 | } 81 | } 82 | } 83 | // random_hash: 重载二级随机散列函数 84 | template 85 | void HashTable::random_hash(const std::size_t levelIndex) 86 | { 87 | if (function[levelIndex].m == 1){ 88 | function[levelIndex].a = 0; 89 | function[levelIndex].b = 0; 90 | function[levelIndex].p = e(); 91 | } 92 | else{ 93 | function[levelIndex].a = e(); 94 | function[levelIndex].b = e(); 95 | function[levelIndex].p = e(); 96 | } 97 | } 98 | // hash2: 二级散列函数 99 | template 100 | std::size_t HashTable::hash2(const HashedObj &hashed) 101 | { 102 | std::size_t levelIndex = hash(hashed); 103 | std::size_t index = ((function[levelIndex].a * hashed.getIndex() + function[levelIndex].b) 104 | % function[levelIndex].p) % (function[levelIndex].m * function[levelIndex].m); 105 | return index; 106 | } 107 | // initialization: hash table初始化 108 | /* 109 | * \parameter vec: 待初始化的数据向量; 110 | * \return bool(返回是否初始化成功的标志). 111 | */ 112 | template 113 | bool HashTable::initialization(const std::vector &vec) 114 | { 115 | size = vec.size(); 116 | std::vector numbers; // 统计散列到同一个槽的数量 117 | numbers.resize(hashData.size()); 118 | for (auto &i : vec) 119 | numbers[hash(i)] += 1; 120 | for (decltype(hashData.size()) i = 0; i != hashData.size(); ++i) 121 | hashData[i].resize(numbers[i] * numbers[i]); 122 | bool sign = false; // 标志是否发生冲突 123 | random_hash(numbers); // 随机产生初始散列函数 124 | do{ 125 | sign = false; 126 | for (decltype(vec.size()) i = 0; i < vec.size(); ++i){ 127 | std::size_t levelIndex = hash(vec[i]); 128 | std::size_t index = hash2(vec[i]); 129 | HashedObj hashObj; 130 | if (hashData[levelIndex][index] == hashObj){ 131 | hashData[levelIndex][index] = vec[i]; 132 | sign = false; 133 | } 134 | else{ 135 | sign = true; 136 | for (int row = 0; row != hashData.size(); ++row) 137 | for (int col = 0; col != hashData[row].size(); ++col) 138 | hashData[row][col] = hashObj; 139 | random_hash(levelIndex); // 随机产生这一列的二级散列新的随机函数 140 | break; 141 | } 142 | } 143 | }while(sign); 144 | return true; 145 | } 146 | // search: 完全散列的查询操作 147 | /* 148 | * \parameter hashed: 待查询的元素; 149 | * \return bool(查询是否成功的标志). 150 | * 算法性能(O(1)). 151 | */ 152 | template 153 | bool HashTable::search(const HashedObj &hashed) 154 | { 155 | bool sign = false; 156 | std::size_t levelIndex = hash(hashed); 157 | std::size_t index = hash2(hashed); 158 | if (hashData[levelIndex][index] == hashed) 159 | sign = true; 160 | return sign; 161 | } 162 | // insert: 完全散列的插入操作 163 | /* 164 | * \parameter hashed: 待插入的元素; 165 | * \return bool(返回是否插入成功). 166 | * 算法性能(O(1)). 167 | * 算法基本思想: 完全散列插入最大的问题就在于冲突的处理,由于插入元素造成冲突处理的成本比较高, 168 | * 这里我们假定当插入元素与其它元素发生碰撞以后就禁止插入此元素. 169 | */ 170 | template 171 | bool HashTable::insert(const HashedObj &hashed) 172 | { 173 | bool sign = false; 174 | std::size_t levelIndex = hash(hashed); 175 | if (function[levelIndex].m == 0){ 176 | std::cerr << "发生碰撞!禁止插入!" << std::endl; 177 | sign = false; 178 | return sign; 179 | } 180 | std::size_t index = hash2(hashed); 181 | HashedObj hashObj; 182 | if (hashData[levelIndex][index] == hashObj){ 183 | hashData[levelIndex][index] = hashed; 184 | sign = true; 185 | ++size; 186 | } 187 | else{ 188 | std::cerr << "发生冲突!禁止插入!" << std::endl; 189 | sign = false; 190 | } 191 | return sign; 192 | } 193 | // hash_delete: 完全散列的删除操作 194 | /* 195 | * \parameter hashed: 待删除的元素; 196 | * \return bool(删除此单元成功的标志). 197 | * 算法性能: O(1). 198 | */ 199 | template 200 | bool HashTable::hash_delete(const HashedObj &hashed) 201 | { 202 | bool sign = false; 203 | std::size_t levelIndex = hash(hashed); 204 | if (function[levelIndex].m == 0){ 205 | std::cerr << "未找到要删除的元素!" << std::endl; 206 | return false; 207 | } 208 | std::size_t index = hash2(hashed); 209 | HashedObj hashObj; 210 | if (hashData[levelIndex][index] == hashed){ 211 | hashData[levelIndex][index] = hashObj; 212 | sign = true; 213 | --size; 214 | } 215 | else{ 216 | std::cerr << "未找到要删除的元素!" << std::endl; 217 | sign = false; 218 | } 219 | return sign; 220 | } 221 | #endif 222 | -------------------------------------------------------------------------------- /hash_table/perfect_hashing/perfect_hashing_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: perfect_hashing_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月22日 星期四 21时45分14秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include 11 | using std::string; 12 | #include 13 | using std::vector; 14 | #include "perfect_hashing.h" 15 | #include "hash.h" 16 | typedef Hash HashData; 17 | typedef HashTable> PerHash; 18 | 19 | HashData h1("zhi",123); 20 | HashData h2("lu",123); 21 | HashData h3("llli",123); 22 | HashData h4("whhhi",123); 23 | HashData h5("ki",123); 24 | HashData h6("zi",123); 25 | void initial(PerHash &hash) 26 | { 27 | vector vec; 28 | vec.push_back(h1); 29 | vec.push_back(h2); 30 | vec.push_back(h3); 31 | vec.push_back(h4); 32 | vec.push_back(h5); 33 | vec.push_back(h6); 34 | cout << "完全散列是否初始化成功: " << hash.initialization(vec) << endl; 35 | } 36 | 37 | int main() 38 | { 39 | 40 | PerHash hash; 41 | initial(hash); 42 | cout << "*************************************************\n"; 43 | bool sign = hash.search({"zhi",123}); 44 | cout << "元素'zhi,123'是否在完全散列中: " << sign << endl; 45 | sign = hash.hash_delete(h1); 46 | cout << "元素'zhi,123'是否删除成功: " << sign << endl; 47 | sign = hash.search(h1); 48 | cout << "元素'zhi,123'是否在完全散列中: " << sign << endl; 49 | 50 | cout << "*************************************************\n"; 51 | sign = hash.search(h2); 52 | cout << "元素'liu,123'是否在完全散列中: " << sign << endl; 53 | sign = hash.hash_delete(h2); 54 | cout << "元素'liu,123'是否删除成功: " << sign << endl; 55 | sign = hash.search(h2); 56 | cout << "元素'liu, 123'是否在完全散列中: " << sign << endl; 57 | 58 | cout << "*************************************************\n"; 59 | sign = hash.search(h3); 60 | cout << "元素'li,123'是否在完全散列中: " << sign << endl; 61 | sign = hash.hash_delete(h3); 62 | cout << "元素'li,123'是否删除成功: " << sign << endl; 63 | sign = hash.search(h3); 64 | cout << "元素'li, 123'是否在完全散列中: " << sign << endl; 65 | 66 | cout << "*************************************************\n"; 67 | sign = hash.search(h4); 68 | cout << "元素'whai,123'是否在完全散列中: " << sign << endl; 69 | sign = hash.hash_delete(h4); 70 | cout << "元素'whai,123'是否删除成功: " << sign << endl; 71 | sign = hash.search(h4); 72 | cout << "元素'whai, 123'是否在完全散列中: " << sign << endl; 73 | 74 | cout << "*************************************************\n"; 75 | sign = hash.search(h5); 76 | cout << "元素'ki,123'是否在完全散列中: " << sign << endl; 77 | sign = hash.hash_delete(h5); 78 | cout << "元素'ki,123'是否删除成功: " << sign << endl; 79 | sign = hash.search(h5); 80 | cout << "元素'ki, 123'是否在完全散列中: " << sign << endl; 81 | 82 | cout << "*************************************************\n"; 83 | sign = hash.search(h6); 84 | cout << "元素'zi,123'是否在完全散列中: " << sign << endl; 85 | sign = hash.hash_delete(h6); 86 | cout << "元素'zi,123'是否删除成功: " << sign << endl; 87 | sign = hash.search(h6); 88 | cout << "元素'zi, 123'是否在完全散列中: " << sign << endl; 89 | 90 | cout << "**********************插入测试*******************\n"; 91 | sign = hash.insert({"hello",12345}); 92 | cout << "插入'hello,12345'是否成功: " << sign << endl; 93 | return 0; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /interesting_algorithm/gcd_algorithm/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: gcd_test.cpp gcd.h 8 | $(c++) $(VERSION) -o Test gcd_test.cpp 9 | -------------------------------------------------------------------------------- /interesting_algorithm/gcd_algorithm/gcd.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: gcd.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月06日 星期二 22时06分38秒 6 | ************************************************************************/ 7 | 8 | #ifndef _GCD_H 9 | #define _GCD_H 10 | // 欧几里得算法求解最大公因数 数据结构与算法分析--C++语言描述 2.4.4 11 | /* 12 | * \parameter num1: 求解最大公因数的参数1; 13 | * \parameter num2: 求解最大公因数的参数2; 14 | * \return T; 15 | * 16 | * 算法性能 O(logN); 17 | * 算法具体思想: 辗转相除法. 18 | */ 19 | template 20 | T gcd(T num1, T num2) 21 | { 22 | if (num1 < num2){ 23 | T temp = num1; 24 | num1 = num2; 25 | num2 = temp; 26 | } 27 | // 辗转相除策略 28 | while (num2 > 0){ 29 | T rem = num1 % num2; 30 | num1 = num2; 31 | num2 = rem; 32 | } 33 | 34 | return num1; 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /interesting_algorithm/gcd_algorithm/gcd_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: gcd_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月06日 星期二 22时19分48秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include "gcd.h" 11 | 12 | int main() 13 | { 14 | int value = gcd(10,2); 15 | cout << "10和2的最大公因数为: " << value << endl; 16 | 17 | unsigned value1 = gcd(1000,89); 18 | cout << "1000和89的最大公因数为: " << value1 << endl; 19 | 20 | return 0; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /interesting_algorithm/pow_algorithm/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: recursionPow.h recursionPow_test.cpp 8 | $(c++) $(VERSION) -o Test recursionPow_test.cpp 9 | -------------------------------------------------------------------------------- /interesting_algorithm/pow_algorithm/recursionPow.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: recursionPow.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月06日 星期二 22时28分18秒 6 | ************************************************************************/ 7 | 8 | #ifndef _RECURSIONPOW_H 9 | #define _RECURSIONPOW_H 10 | // 递归求幂运算 数据结构与算法分析--C++语言描述 2.4.4 11 | /* 12 | *\parameter num1: num1^num2; 13 | *\parameter num2: num1^num2; 14 | *\return T 15 | * 16 | * 算法性能: O(logN) 17 | * 算法基本思想: 当N是偶数的时候我们有 x^N = x^{N/2} * x^{N/2}; 18 | * 当N是奇数的时候我们有 x^N = x^{(N-1)/2} * x^{(N-1)/2} * x; 19 | * 根据递归的思想解决. 20 | */ 21 | template 22 | T pow(T num1, unsigned long long num2) 23 | { 24 | // 基准情形 25 | if (num2 == 1) 26 | return num1; 27 | if (num2 == 0) 28 | return 1; 29 | // 递归求幂运算 30 | if (num2 % 2 == 0) 31 | return pow(num1 * num1, num2 / 2); 32 | else 33 | return pow(num1 * num1, num2 / 2) * num1; 34 | } 35 | #endif 36 | -------------------------------------------------------------------------------- /interesting_algorithm/pow_algorithm/recursionPow_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: recursionPow_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月06日 星期二 22时43分19秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include 11 | #include "recursionPow.h" 12 | 13 | int main() 14 | { 15 | double value1 = pow(2.2,2); 16 | double value3 = pow(2.2222222, 5); 17 | double value2 = std::pow(2.2,2); 18 | double value4 = std::pow(2.2222222, 5); 19 | cout << "递归求幂运算\t数学库求幂\n"; 20 | cout << value1 << "\t" << value2 << endl; 21 | cout << value3 << "\t" << value4 << endl; 22 | 23 | return 0; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /list_algorithm/circular_list/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: circularList_test.cpp circularList.h 8 | $(c++) $(VERSION) -o Test circularList_test.cpp 9 | -------------------------------------------------------------------------------- /list_algorithm/circular_list/circularList.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: circularList.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月16日 星期五 10时00分26秒 6 | ************************************************************************/ 7 | 8 | #ifndef _CIRCULARLIST_H 9 | #define _CIRCULARLIST_H 10 | #include 11 | #include 12 | #include "../doublyLinkedListNode/doublyLinkedListNode.h" 13 | // CircularList: 带有哨兵的循环链表 14 | /* 15 | * nil: 哨兵双向循环链表. 16 | * 待有哨兵双向循环链表的优势就在于边界条件的处理. 17 | */ 18 | template 19 | class CircularList 20 | { 21 | public: 22 | typedef NodeT NodeType; // 链表的节点类型 23 | typedef typename NodeT::KeyType KeyType; // 链表节点存储的数据类型 24 | //*******************************构造函数***************************** 25 | CircularList() 26 | { 27 | auto data = std::make_shared(0); 28 | nil = data; 29 | nil->next = data; 30 | nil->prev = data; 31 | } 32 | //*******************************成员函数***************************** 33 | // insertBack: 不断的在nil->next插入元素 34 | /* 35 | * \parameter key: 待插入的元素; 36 | * \return sign(标志插入是否成功). 37 | */ 38 | bool insertBack(const KeyType &key) 39 | { 40 | bool sign = false; 41 | auto data = std::make_shared(key); 42 | data->next = nil->next; 43 | data->prev = nil; 44 | nil->next->prev = data; 45 | nil->next = data; 46 | sign = true; 47 | 48 | return sign; 49 | } 50 | // insert: 在循环链表给定的位置后面插入元素 51 | /* 52 | * \parameter ptr: 给定循环链表中的位置; 53 | * \parameter key: 在给定位置ptr后面插入key; 54 | * \return sign(指示是否插入成功). 55 | * 算法复杂度: O(1). 56 | */ 57 | bool insert(std::shared_ptr &ptr ,const KeyType &key) 58 | { 59 | bool sign = false; 60 | if (ptr == NULL) 61 | return sign; 62 | auto data = std::make_shared(key); 63 | data->next = ptr->next; 64 | data->prev = ptr; 65 | ptr->next->prev = data; 66 | ptr->next = data; 67 | sign = true; 68 | 69 | return sign; 70 | } 71 | // search: 在循环链表中查找给定的元素 72 | /* 73 | * \parameter key: 在链表中查找'key'; 74 | * \return 返回'key'所在的位置. 75 | * 算法复杂度: O(N). 76 | */ 77 | std::shared_ptr search(const KeyType &key) 78 | { 79 | auto current = nil->next; 80 | while(current != nil && current->key != key) 81 | current = current->next; 82 | if (current == nil) 83 | return std::make_shared(); 84 | else 85 | return current; 86 | } 87 | // deleteList: 删除指定位置的元素 88 | /* 89 | * \parameter ptr: 删除ptr指向的元素; 90 | * \return sign(标志是否删除成功). 91 | * 算法复杂度: O(1). 92 | */ 93 | bool deleteList(std::shared_ptr &ptr) 94 | { 95 | bool sign = false; 96 | ptr->next->prev = ptr->prev; 97 | ptr->prev->next = ptr->next; 98 | ptr.reset(); 99 | sign = true; 100 | return sign; 101 | } 102 | // order_print: 顺序遍历链表(从哨兵的next开始) 103 | /* 104 | * 当nil->next==nil的时候循环链表为空链表. 105 | */ 106 | void order_print() 107 | { 108 | if (nil == nil->next){ 109 | std::cout << "The list is empty!\n"; 110 | return; 111 | } 112 | for (auto current = nil->next; current != nil; current = current->next) 113 | std::cout << current->key << " "; 114 | std::cout << std::endl; 115 | } 116 | // reverse_order_print: 逆序遍历链表(从哨兵的prev开始) 117 | /* 118 | * 当nil->prev=nil的时候循环链表为空链表. 119 | */ 120 | void reverse_order_print() 121 | { 122 | if (nil == nil->prev){ 123 | std::cout << "The list is empty!\n"; 124 | return; 125 | } 126 | for (auto current = nil->prev; current != nil; current = current->prev) 127 | std::cout << current->key << " "; 128 | std::cout << std::endl; 129 | } 130 | private: 131 | //*******************************数据结构***************************** 132 | std::shared_ptr nil; // 哨兵 133 | }; 134 | #endif 135 | -------------------------------------------------------------------------------- /list_algorithm/circular_list/circularList_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: circularList_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月16日 星期五 10时57分40秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include "circularList.h" 11 | #include "../doublyLinkedListNode/doublyLinkedListNode.h" 12 | typedef CircularList> IntList; 13 | 14 | void initList_test() 15 | { 16 | IntList intlist; 17 | intlist.order_print(); 18 | intlist.reverse_order_print(); 19 | } 20 | 21 | void insertBack_test() 22 | { 23 | IntList intlist; 24 | cout << "依次向循环链表哨兵后面插入: \n"; 25 | for (int i = 1; i <= 20; ++i){ 26 | cout << i << " "; 27 | intlist.insertBack(i); 28 | } 29 | cout << "\n正序输出: \n"; 30 | intlist.order_print(); 31 | cout << "逆序输出: \n"; 32 | intlist.reverse_order_print(); 33 | } 34 | 35 | void search_test() 36 | { 37 | IntList intlist; 38 | cout << "依次向循环链表哨兵后面插入: \n"; 39 | for (int i = 1; i <= 20; ++i){ 40 | cout << i << " "; 41 | intlist.insertBack(i); 42 | } 43 | auto value_ptr = intlist.search(10); 44 | cout << "\n在序列中是否找到10: " << value_ptr->key << endl; 45 | } 46 | 47 | void insert_test() 48 | { 49 | IntList intlist; 50 | cout << "依次向循环链表哨兵后面插入: \n"; 51 | for (int i = 1; i <= 20; ++i){ 52 | cout << i << " "; 53 | intlist.insertBack(i); 54 | } 55 | auto value_ptr = intlist.search(10); 56 | intlist.insert(value_ptr, 100); 57 | cout << "\n正序输出: \n"; 58 | intlist.order_print(); 59 | cout << "逆序输出:\n"; 60 | intlist.reverse_order_print(); 61 | } 62 | 63 | void deleteList_test() 64 | { 65 | IntList intlist; 66 | cout << "依次向循环链表哨兵后面插入: \n"; 67 | for (int i = 1; i <= 20; ++i){ 68 | cout << i << " "; 69 | intlist.insertBack(i); 70 | } 71 | auto value_ptr = intlist.search(10); 72 | bool sign = intlist.deleteList(value_ptr); 73 | cout << "\n正序输出: \n"; 74 | intlist.order_print(); 75 | cout << "逆序输出:\n"; 76 | intlist.reverse_order_print(); 77 | } 78 | int main() 79 | { 80 | cout << "***************************循环链表默认构造函数***************************\n"; 81 | initList_test(); 82 | cout << "***************************循环链表在哨兵后面插入*************************\n"; 83 | insertBack_test(); 84 | cout << "*******************************循环链表查找*******************************\n"; 85 | search_test(); 86 | cout << "*******************************循环链表插入*******************************\n"; 87 | insert_test(); 88 | cout << "*******************************循环链表删除*******************************\n"; 89 | deleteList_test(); 90 | 91 | return 0; 92 | } 93 | 94 | -------------------------------------------------------------------------------- /list_algorithm/doublyLinkedListNode/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: doublyLinkedListNode.h doublyLinkedListNode_test.cpp 8 | $(c++) $(VERSION) -o Test doublyLinkedListNode_test.cpp 9 | -------------------------------------------------------------------------------- /list_algorithm/doublyLinkedListNode/doublyLinkedListNode.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: doublyLinkedListNode.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月14日 星期三 21时30分14秒 6 | ************************************************************************/ 7 | 8 | #ifndef _DOUBLYLINKEDLISTNODE_H 9 | #define _DOUBLYLINKEDLISTNODE_H 10 | #include 11 | #include 12 | #include 13 | // DoublyLinkedListNode: 双向链表的节点 算法导论10.2 14 | /* 15 | * 任何一个节点都有两个强引用指向前驱节点和后继节点.节点还有一个'key'成员包含具体的数据 16 | */ 17 | template 18 | struct DoublyLinkedListNode 19 | { 20 | typedef KType KeyType; 21 | //**************************构造函数********************************** 22 | // 默认构造函数,所有的数据成员变量都采用默认值 23 | DoublyLinkedListNode(): 24 | key(KeyType()), 25 | prev(std::shared_ptr()), 26 | next(std::shared_ptr()) 27 | { } 28 | // 显示构造函数 29 | /* 30 | * \parameter val: 节点要保存的数据内容. 31 | * 指定'key'成员需要赋值的数据. 32 | */ 33 | explicit DoublyLinkedListNode(const KeyType &val): 34 | key(val), 35 | prev(std::shared_ptr()), 36 | next(std::shared_ptr()) 37 | { } 38 | //**************************成员函数********************************** 39 | // to_string: 返回该节点的字符串描述 40 | /* 41 | * \return: 本节点的描述字符串 42 | * 该函数打印本节点的'key',以及前驱节点(若存在),后继节点(若存在)的'key' 43 | */ 44 | virtual std::string to_string() 45 | { 46 | std::ostringstream os; 47 | os << "node " << key; 48 | 49 | os << "\n\t prev_node: "; 50 | if (prev) 51 | os << prev->key; 52 | else 53 | os << "nullptr"; 54 | 55 | os << "\n\t next_node: "; 56 | if (next) 57 | os << next->key; 58 | else 59 | os << "nullptr"; 60 | 61 | return os.str(); 62 | } 63 | public: 64 | //**************************数据结构********************************** 65 | KeyType key; // 链表的数据 66 | std::shared_ptr prev; // 前驱指针 67 | std::shared_ptr next; // 后继指针 68 | }; 69 | #endif 70 | -------------------------------------------------------------------------------- /list_algorithm/doublyLinkedListNode/doublyLinkedListNode_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: doublyLinkedListNode_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月14日 星期三 21时59分35秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include "doublyLinkedListNode.h" 11 | typedef DoublyLinkedListNode IntList; 12 | 13 | void Test() 14 | { 15 | DoublyLinkedListNode intList(DoublyLinkedListNode(11)); 16 | cout << intList.to_string() << endl; 17 | } 18 | 19 | void Test1() 20 | { 21 | DoublyLinkedListNode intList; 22 | cout << intList.to_string() << endl; 23 | } 24 | 25 | void Test2() 26 | { 27 | typedef DoublyLinkedListNode Node; 28 | auto head = std::make_shared(0); 29 | head->next = std::make_shared(1); 30 | head->next->next = std::make_shared(2); 31 | 32 | head->next->prev = head; 33 | head->next->next->prev = head->next; 34 | cout << head->next->to_string() << endl; 35 | 36 | } 37 | 38 | int main() 39 | { 40 | Test(); 41 | Test1(); 42 | Test2(); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /list_algorithm/doubly_linked_list/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: doublyLinkedList.h doublyLinkedList_test.cpp 8 | $(c++) $(VERSION) -o Test doublyLinkedList_test.cpp 9 | -------------------------------------------------------------------------------- /list_algorithm/doubly_linked_list/doublyLinkedList.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: doublyLinkedList.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月14日 星期三 22时22分22秒 6 | ************************************************************************/ 7 | 8 | #ifndef _DOUBLYLINKEDLIST_H 9 | #define _DOUBLYLINKEDLIST_H 10 | #include "../doublyLinkedListNode/doublyLinkedListNode.h" 11 | // DoublyLinkedList: 双向链表 算法导论10.2 12 | /* 13 | * 双向链表通过head,tail指向节点对象, 其中head表示链表的头,tail表示链表的尾. 14 | * 当head为空的时候链表为一个空链表,当tail为空的时候链表为一个空链表. 15 | */ 16 | template 17 | class DoublyLinkedList 18 | { 19 | public: 20 | typedef NodeT NodeType; // 链表的节点类型 21 | typedef typename NodeT::KeyType KeyType; // 链表节点存储数据的类型 22 | //******************************默认构造函数************************** 23 | DoublyLinkedList(): 24 | head(std::shared_ptr()), 25 | tail(std::shared_ptr()) 26 | { } 27 | //******************************成员函数****************************** 28 | // insertBack: 向双向链表的尾部插入数据 29 | /* 30 | * \parameter key: 待插入的数据; 31 | * \return void. 32 | */ 33 | void insertBack(const KeyType &key) 34 | { 35 | // 链表为空的时候 36 | if (!head){ 37 | auto data = std::make_shared(key); 38 | head = data; 39 | tail = data; 40 | } 41 | else{ 42 | // 链表非空的时候 43 | auto data = std::make_shared(key); 44 | tail->next = data; 45 | tail->next->prev = tail; 46 | tail = data; 47 | } 48 | } 49 | // insertFront: 向双向链表的头部插入数据 50 | /* 51 | * \parameter key: 待插入的数据; 52 | * \return void. 53 | */ 54 | void insertFront(const KeyType &key) 55 | { 56 | // 链表为空的时候 57 | if (!head){ 58 | auto data = std::make_shared(key); 59 | head = data; 60 | tail = data; 61 | } 62 | else{ 63 | // 链表非空的时候 64 | auto data = std::make_shared(key); 65 | head->prev = data; 66 | head->prev->next = head; 67 | head = data; 68 | } 69 | } 70 | // search: 采用简单的线性搜索方法 71 | /* 72 | * \parameter key: 待查询的数据; 73 | * \return 返回指向查询数据的指针(第一次出现的位置). 74 | * 线性搜索,时间复杂度为O(N). 75 | */ 76 | std::shared_ptr search(const KeyType &key) 77 | { 78 | std::shared_ptr value = std::shared_ptr(); 79 | if (!head) 80 | std::cout << "The doubly linked list is empty!\n"; 81 | else{ 82 | for (auto current = head; current != NULL; current = current->next){ 83 | if (key == current->key){ 84 | value = current; 85 | break; 86 | } 87 | } 88 | } 89 | return value; 90 | } 91 | // deleteList: 在链表中删除给定元素指针 92 | /* 93 | * \parameter value: 指向待删除元素的指针; 94 | * \return sign(标志删除是否成功). 95 | * 删除一个元素指针所耗费的时间为O(1). 96 | */ 97 | bool deleteList(std::shared_ptr &value) 98 | { 99 | if (value == NULL) 100 | return false; 101 | bool sign = false; 102 | if (value == head){ 103 | head->next->prev = std::shared_ptr(); 104 | head = value->next; 105 | value.reset(); 106 | sign = true; 107 | } 108 | else if (value == tail){ 109 | tail->prev->next = std::shared_ptr(); 110 | tail = value->prev; 111 | value.reset(); 112 | sign = true; 113 | } 114 | else{ 115 | value->prev->next = value->next; 116 | value->next->prev = value->prev; 117 | value.reset(); 118 | sign = true; 119 | } 120 | return sign; 121 | 122 | } 123 | // insert: 在给定指针的后面插入元素 124 | /* 125 | * \parameter value: 把元素'key'插入到value指针后面; 126 | * \parameter key: 待插入的值; 127 | * \return sign(标志插入是否成功). 128 | * 插入一个元素所耗费的时间为O(1). 129 | */ 130 | bool insert(std::shared_ptr &value, const KeyType key) 131 | { 132 | if (value == NULL) 133 | return false; 134 | bool sign = false; 135 | if (value == tail){ 136 | insertBack(key); 137 | sign = true; 138 | } 139 | else{ 140 | auto key_ptr = std::make_shared(key); 141 | key_ptr->next = value->next; 142 | key_ptr->prev = value; 143 | value->next->prev = key_ptr; 144 | value->next = key_ptr; 145 | sign = true; 146 | } 147 | return sign; 148 | } 149 | 150 | // order_print:顺序遍历链表 151 | /* 152 | * \return void. 153 | * 顺序遍历双向链表,打印其'key'. 154 | */ 155 | void order_print() 156 | { 157 | if (!head) 158 | std::cout << "The doubly linked list is empty!\n"; 159 | else{ 160 | for (auto current = head; current != NULL; current = current->next) 161 | std::cout << current->key << " "; 162 | std::cout << std::endl; 163 | } 164 | } 165 | // reverse_order_print: 逆序遍历链表 166 | /* 167 | * \return void. 168 | * 逆序遍历双向链表,打印其'key'. 169 | */ 170 | void reverse_order_print() 171 | { 172 | if (!head) 173 | std::cout << "The doubly linked list is enpty!\n"; 174 | else{ 175 | for (auto current = tail; current != NULL; current = current->prev) 176 | std::cout << current->key << " "; 177 | std::cout << std::endl; 178 | } 179 | } 180 | private: 181 | //******************************数据结构****************************** 182 | std::shared_ptr head; // 链表的头 183 | std::shared_ptr tail; // 链表的尾 184 | }; 185 | #endif 186 | -------------------------------------------------------------------------------- /list_algorithm/doubly_linked_list/doublyLinkedList_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: doublyLinkedList_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月15日 星期四 10时28分24秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include "doublyLinkedList.h" 11 | #include "../doublyLinkedListNode/doublyLinkedListNode.h" 12 | typedef DoublyLinkedList> IntList; 13 | void insertBack_test() 14 | { 15 | IntList intlist; 16 | cout << "依次向链表尾部中插入:\n "; 17 | for (int i = 0; i <= 20; ++i){ 18 | cout << i << " "; 19 | intlist.insertBack(i); 20 | } 21 | cout << "\n顺序遍历列表:\n "; 22 | intlist.order_print(); 23 | cout << "逆序遍历链表:\n"; 24 | intlist.reverse_order_print(); 25 | } 26 | 27 | void insertFront_test() 28 | { 29 | IntList intlist; 30 | cout << "依次向链表的头部插入:\n"; 31 | for (int i = 0; i <= 20; ++i){ 32 | cout << i << " "; 33 | intlist.insertFront(i); 34 | } 35 | cout << "\n顺序遍历链表:\n"; 36 | intlist.order_print(); 37 | cout << "逆序遍历链表:\n"; 38 | intlist.reverse_order_print(); 39 | } 40 | 41 | void search_test() 42 | { 43 | IntList intlist; 44 | cout << "依次向链表尾部中插入:\n "; 45 | for (int i = 0; i <= 20; ++i){ 46 | cout << i << " "; 47 | intlist.insertBack(i); 48 | } 49 | auto value = intlist.search(10); 50 | cout << "\n已找到链表中指定的元素: " << value->key << endl; 51 | } 52 | 53 | void deleteList_test() 54 | { 55 | IntList intlist; 56 | cout << "依次向链表尾部中插入:\n "; 57 | for (int i = 0; i <= 20; ++i){ 58 | cout << i << " "; 59 | intlist.insertBack(i); 60 | } 61 | auto value = intlist.search(10); 62 | bool sign = intlist.deleteList(value); 63 | cout << "\n删除元素是否成功: " << sign << endl; 64 | intlist.order_print(); 65 | intlist.reverse_order_print(); 66 | } 67 | 68 | void insert_test() 69 | { 70 | IntList intlist; 71 | cout << "依次向链表尾部中插入:\n "; 72 | for (int i = 0; i <= 20; ++i){ 73 | cout << i << " "; 74 | intlist.insertBack(i); 75 | } 76 | auto value = intlist.search(10); 77 | bool sign = intlist.insert(value, 100); 78 | cout << "\n插入元素是否成功: " << sign << endl; 79 | intlist.order_print(); 80 | intlist.reverse_order_print(); 81 | } 82 | int main() 83 | { 84 | cout << "*****************双向链表尾部插入****************************\n"; 85 | insertBack_test(); 86 | cout << "*****************双向链表头部插入****************************\n"; 87 | insertFront_test(); 88 | cout << "*****************双向链表查询插入****************************\n"; 89 | search_test(); 90 | cout << "*****************双向链表删除操作****************************\n"; 91 | deleteList_test(); 92 | cout << "*****************双向链表插入操作****************************\n"; 93 | insert_test(); 94 | 95 | return 0; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /list_algorithm/list/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: list_test.cpp list.h 8 | $(c++) $(VERSION) -o Test list_test.cpp 9 | -------------------------------------------------------------------------------- /list_algorithm/list/list.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: list.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月15日 星期四 16时41分49秒 6 | ************************************************************************/ 7 | 8 | #ifndef _LIST_H 9 | #define _LIST_H 10 | #include 11 | #include 12 | #include "../listNode/ListNode.h" 13 | // List: 单向链表 算法导论10.2 14 | /* 15 | * \parameter head: 表头指针; 16 | * insertBack(x): 在链表的尾部插入元素; 17 | * insertFront(x): 在链表的头部插入元素; 18 | * insert(ptr,x): 在给定指针ptr后面插入元素x; 19 | * search(x): 在链表中查找元素x; 20 | * deleteList(ptr): 在链表中删除指针ptr指向的元素; 21 | * order_print(): 顺序打印链表中的元素. 22 | */ 23 | template 24 | class List 25 | { 26 | public: 27 | typedef NodeT NodeType; // 链表的节点类型 28 | typedef typename NodeT::KeyType KeyType; // 链表节点存储的数据类型 29 | //******************************默认构造函数************************** 30 | List(): 31 | head(std::shared_ptr()) 32 | { } 33 | //******************************成员函数****************************** 34 | // insertFront:在链表的头部插入元素 35 | /* 36 | * \parameter key:待插入的元素; 37 | * \return sign(标志是否插入成功). 38 | * 算法复杂度为O(1). 39 | */ 40 | bool insertFront(const KeyType &key) 41 | { 42 | bool sign = false; 43 | if (head == NULL){ 44 | auto data = std::make_shared(key); 45 | head = data; 46 | sign = true; 47 | } 48 | else{ 49 | auto data = std::make_shared(key); 50 | data->next = head; 51 | head = data; 52 | sign = true; 53 | } 54 | return sign; 55 | } 56 | // insertBack:在链表的尾部插入元素 57 | /* 58 | * \parameter key:带插入的元素; 59 | * \return sign(标志是否插入成功). 60 | * 算法复杂度为O(N). 61 | */ 62 | bool insertBack(const KeyType &key) 63 | { 64 | bool sign = false; 65 | if (head == NULL){ 66 | auto data = std::make_shared(key); 67 | head = data; 68 | sign = true; 69 | } 70 | else{ 71 | auto current = head; 72 | while (current->next != NULL) 73 | current = current->next; 74 | auto data = std::make_shared(key); 75 | current->next = data; 76 | sign = true; 77 | } 78 | return sign; 79 | } 80 | // insert: 在给定位置后面插入元素 81 | /* 82 | * \parameter val_ptr: 在指针val_ptr后面插入key; 83 | * \parameter key: 在指针val_ptr后面插入key; 84 | * \return sign(指示是否插入成功). 85 | * 算法复杂度: O(N). 86 | */ 87 | bool insert(const std::shared_ptr &val_ptr, const KeyType &key) 88 | { 89 | if (!head){ 90 | std::cout << "The list is empty!\n"; 91 | return false; 92 | } 93 | if (!val_ptr){ 94 | std::cout << "此指针为空!\n"; 95 | return false; 96 | } 97 | bool sign = false; 98 | auto current = head; 99 | while (current != val_ptr && current != NULL) 100 | current = current->next; 101 | if (current != NULL){ 102 | auto data = std::make_shared(key); 103 | data->next = current->next; 104 | current->next = data; 105 | sign = true; 106 | } 107 | else 108 | std::cout << "没有该元素" << std::endl; 109 | return sign; 110 | } 111 | // search: 简单的线性搜索算法 112 | /* 113 | * \parameter key: 待查找的元素key; 114 | * \return 指向已查找到元素的指针. 115 | * 算法复杂度: O(N). 116 | */ 117 | std::shared_ptr search(const KeyType &key) 118 | { 119 | if (head == NULL){ 120 | std::cout << "The list is empty!\n"; 121 | return std::shared_ptr(); 122 | } 123 | auto current = head; 124 | while (current != NULL && current->key != key) 125 | current = current->next; 126 | if (current != NULL) 127 | return current; 128 | else 129 | return std::shared_ptr(); 130 | } 131 | // deleteList: 单向链表的删除操作 132 | /* 133 | * \parameter val_ptr: 删除列表中val_ptr指向的元素; 134 | * \return sign(标志删除是否成功). 135 | * 算法复杂度: O(N). 136 | */ 137 | bool deleteList(std::shared_ptr &val_ptr) 138 | { 139 | if (head == NULL){ 140 | std::cout << "The list is empty!"; 141 | return false; 142 | } 143 | if (val_ptr == NULL){ 144 | std::cout << "此指针为空!"; 145 | return false; 146 | } 147 | // 删除头指针的情况 148 | if (val_ptr == head){ 149 | head = val_ptr->next; 150 | val_ptr.reset(); 151 | return true; 152 | } 153 | auto sign = false; 154 | auto current = head; 155 | auto front_ptr = head; 156 | while (current != val_ptr && current != NULL){ 157 | front_ptr = current; 158 | current = current->next; 159 | } 160 | if (current == NULL) 161 | std::cout << "未找到此指针\n"; 162 | else{ 163 | front_ptr->next = current->next; 164 | val_ptr.reset(); 165 | sign = true; 166 | } 167 | return sign; 168 | } 169 | // order_print: 顺序遍历链表 170 | /* 171 | * \return void. 172 | * 顺序遍历单向链表,时间复杂度为O(N). 173 | */ 174 | void order_print() 175 | { 176 | if (head == NULL) 177 | std::cout << "The list is empty!\n"; 178 | else{ 179 | for (auto current = head; current != NULL; current = current->next) 180 | std::cout << current->key << " "; 181 | std::cout << std::endl; 182 | } 183 | } 184 | private: 185 | //******************************数据结构****************************** 186 | std::shared_ptr head; // 链表的头指针 187 | }; 188 | #endif 189 | -------------------------------------------------------------------------------- /list_algorithm/list/list_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: list_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月15日 星期四 19时08分15秒 6 | ************************************************************************/ 7 | 8 | #include 9 | #include "list.h" 10 | using std::cout; using std::endl; 11 | 12 | typedef List> IntList; 13 | void insertFront_test() 14 | { 15 | IntList intlist; 16 | cout << "依次向链表头部插入: \n"; 17 | for (int i = 0; i <= 20; ++i){ 18 | cout << i << " "; 19 | intlist.insertFront(i); 20 | } 21 | cout << "\n顺序遍历链表:\n"; 22 | intlist.order_print(); 23 | } 24 | void insertBack_test() 25 | { 26 | IntList intlist; 27 | cout << "依次向链表尾部插入: \n"; 28 | for (int i = 0; i <= 20; ++i){ 29 | cout << i << " "; 30 | intlist.insertBack(i); 31 | } 32 | cout << "\n顺序遍历链表:\n"; 33 | intlist.order_print(); 34 | } 35 | void search_test() 36 | { 37 | IntList intlist; 38 | cout << "依次向链表尾部插入: \n"; 39 | for (int i = 0; i <= 20; ++i){ 40 | cout << i << " "; 41 | intlist.insertBack(i); 42 | } 43 | cout << "\n遍历单向链表查找给定元素10:\n "; 44 | cout << (intlist.search(10)->key) << endl; 45 | } 46 | 47 | void insert_test() 48 | { 49 | IntList intlist; 50 | cout << "依次向链表尾部插入: \n"; 51 | for (int i = 0; i <= 20; ++i){ 52 | cout << i << " "; 53 | intlist.insertBack(i); 54 | } 55 | auto data_ptr = intlist.search(10); 56 | cout << "\n在10后面插入100:\n" << endl; 57 | cout << "插入是否成功: " << intlist.insert(data_ptr,100) << endl; 58 | // 遍历链表 59 | intlist.order_print(); 60 | } 61 | 62 | void deleteList_test() 63 | { 64 | IntList intlist; 65 | cout << "依次向链表尾部插入: \n"; 66 | for (int i = 0; i <= 20; ++i){ 67 | cout << i << " "; 68 | intlist.insertBack(i); 69 | } 70 | auto data_ptr = intlist.search(10); 71 | cout << "\n删除元素10:\n" << endl; 72 | cout << "删除是否成功: " << intlist.deleteList(data_ptr) << endl; 73 | // 遍历链表 74 | intlist.order_print(); 75 | } 76 | 77 | int main() 78 | { 79 | cout << "************************单向链表头部插入*********************\n"; 80 | insertFront_test(); 81 | cout << "************************单向链表尾部插入*********************\n"; 82 | insertBack_test(); 83 | cout << "************************单向链表查找*************************\n"; 84 | search_test(); 85 | cout << "************************单向链表插入*********************\n"; 86 | insert_test(); 87 | cout << "************************单向链表的删除*******************\n"; 88 | deleteList_test(); 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /list_algorithm/listNode/ListNode.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: ListNode.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月15日 星期四 16时06分17秒 6 | ************************************************************************/ 7 | 8 | #ifndef _LISTNODE_H 9 | #define _LISTNODE_H 10 | #include 11 | #include 12 | #include 13 | // ListNode: 单向链表的节点 算法导论10.2 14 | /* 15 | * 16 | */ 17 | template 18 | struct ListNode 19 | { 20 | typedef KType KeyType; 21 | //*******************************构造函数***************************** 22 | // 默认构造函数,所有的数据成员变量都采用默认值 23 | ListNode(): 24 | key(KeyType()), 25 | next(std::shared_ptr()) 26 | { } 27 | // 显式构造函数 28 | /* 29 | * \parameter val: 节点要保存的数据内容. 30 | * 指定'key'成员需要赋值的数据. 31 | */ 32 | explicit ListNode(const KeyType &val): 33 | key(val), 34 | next(std::shared_ptr()) 35 | { } 36 | //*******************************成员函数***************************** 37 | // to_string: 返回该节点的字符串描述 38 | /* 39 | * \return: 返回本节点的描述字符串. 40 | * 该函数打印本节点的'key',以及后继节点(若存在)的'key'. 41 | */ 42 | virtual std::string to_string() 43 | { 44 | std::ostringstream os; 45 | os << "node " << key; 46 | os << "\n\tnext_node: "; 47 | if (next) 48 | os << next->key; 49 | else 50 | os << "nullptr"; 51 | return os.str(); 52 | } 53 | //*******************************数据结构***************************** 54 | KeyType key; // 链表的数据 55 | std::shared_ptr next; // 后继指针 56 | }; 57 | #endif 58 | -------------------------------------------------------------------------------- /list_algorithm/listNode/ListNode_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: ListNode_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月15日 星期四 16时22分29秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include "ListNode.h" 11 | 12 | typedef ListNode IntList; 13 | void Test() 14 | { 15 | IntList intlist; 16 | cout << intlist.to_string() << endl; 17 | } 18 | void Test1() 19 | { 20 | auto head = std::make_shared(1); 21 | head->next = std::make_shared(2); 22 | cout << head->to_string() << endl; 23 | cout << head->next->to_string() << endl; 24 | 25 | } 26 | 27 | int main() 28 | { 29 | Test(); 30 | Test1(); 31 | 32 | return 0; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /list_algorithm/listNode/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: ListNode.h ListNode_test.cpp 8 | $(c++) $(VERSION) -o Test ListNode_test.cpp 9 | -------------------------------------------------------------------------------- /queue_algorithm/min_queue/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: minqueue.h minqueue_test.cpp 8 | $(c++) $(VERSION) -o Test minqueue_test.cpp 9 | -------------------------------------------------------------------------------- /queue_algorithm/min_queue/minqueue_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: minqueue_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月08日 星期四 11时24分22秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include "minqueue.h" 11 | // 当最小优先队列存放的是int*数据时,相应的比较函数对象 12 | typedef std::function, std::shared_ptr)> IntCompareType; 13 | // 当最小优先级队列存放的是int*数据时,获取key的函数对象 14 | typedef std::function)> IntGetType; 15 | // 存放的是int*数据的最小优先级队列,其关键字就是int本身 16 | typedef MinQueue IntMinqueueType; 17 | 18 | IntCompareType intCompare=[](std::shared_ptr first, std::shared_ptr second) {return (*first < *second);}; 19 | IntGetType intGetType=[](std::shared_ptr node)->int& {return *node;}; 20 | 21 | // 测试最小优先队列的成员函数insert() 22 | void insertTest() 23 | { 24 | cout << "*************Minqueue成员函数insert的测试:************************\n"; 25 | cout << "********int型数据的测试:***************\n"; 26 | IntMinqueueType minQueue(10, intCompare, intGetType); 27 | cout << "依次插入1,2,3,4,5,6,7,8,9,10返回元素插入的位置:\n"; 28 | for (int i = 1; i <= 10; ++i){ 29 | int index = minQueue.insert(std::make_shared(i)); 30 | cout << index << " "; 31 | } 32 | cout << endl; 33 | 34 | IntMinqueueType minQueue1(10, intCompare, intGetType); 35 | cout << "依次插入10,9,8,7,6,5,4,3,2,1返回元素插入的位置:\n"; 36 | for (int i = 10; i >= 1; --i){ 37 | int index = minQueue1.insert(std::make_shared(i)); 38 | cout << index << " "; 39 | } 40 | cout << endl; 41 | 42 | IntMinqueueType minQueue2(10, intCompare, intGetType); 43 | cout << "依次插入1,-1,2,-2,3,-3,4,-4,5,-5返回元素插入的位置:\n"; 44 | for (int i = 1; i <= 5; ++i){ 45 | int index = minQueue2.insert(std::make_shared(i)); 46 | cout << index << " "; 47 | index = minQueue2.insert(std::make_shared(-i)); 48 | cout << index << " "; 49 | } 50 | cout << endl; 51 | 52 | IntMinqueueType minQueue3(10, intCompare, intGetType); 53 | cout << "依次插入1,1,2,2,3,3,4,4,5,5返回元素插入的位置:\n"; 54 | for (int i = 1; i <= 5; ++i){ 55 | int index = minQueue3.insert(std::make_shared(i)); 56 | cout << index << " "; 57 | index = minQueue3.insert(std::make_shared(i)); 58 | cout << index << " "; 59 | } 60 | cout << endl; 61 | } 62 | 63 | // 测试最小优先队列的成员函数min 64 | void minTest() 65 | { 66 | cout << "*************MinQueue成员函数min的测试********************\n"; 67 | IntMinqueueType minQueue(10, intCompare, intGetType); 68 | cout << "在序列: "; 69 | for (int i = 1; i <= 20; ++i){ 70 | cout << i << " "; 71 | minQueue.insert(std::make_shared(i)); 72 | } 73 | auto result = minQueue.min(); 74 | cout << "\n最小值为: " << *result << endl; 75 | 76 | IntMinqueueType minQueue1(10, intCompare, intGetType); 77 | cout << "在序列: "; 78 | for (int i = 10; i >= 1; --i){ 79 | cout << i << " "; 80 | minQueue1.insert(std::make_shared(i)); 81 | } 82 | result = minQueue1.min(); 83 | cout << "\n最小值为: " << *result << endl; 84 | 85 | IntMinqueueType minQueue2(10, intCompare, intGetType); 86 | cout << "在序列: "; 87 | for (int i = 1; i <= 5; ++i){ 88 | cout << i << " "; 89 | minQueue2.insert(std::make_shared(i)); 90 | cout << i << " "; 91 | minQueue2.insert(std::make_shared(i)); 92 | } 93 | result = minQueue2.min(); 94 | cout << "\n最小值为: " << *result << endl; 95 | 96 | IntMinqueueType minQueue3(10, intCompare, intGetType); 97 | cout << "在序列: "; 98 | for (int i = 1; i <= 5; ++i){ 99 | cout << i << " "; 100 | minQueue3.insert(std::make_shared(i)); 101 | cout << -i << " "; 102 | minQueue3.insert(std::make_shared(-i)); 103 | } 104 | result = minQueue3.min(); 105 | cout << "\n最小值为: " << *result << endl; 106 | } 107 | 108 | // 测试最小优先队列的成员函数extract_min 109 | void extract_minTest() 110 | { 111 | 112 | cout << "*************MinQueue成员函数extract_min的测试********************\n"; 113 | IntMinqueueType minQueue(10, intCompare, intGetType); 114 | cout << "在序列: "; 115 | for (int i = 1; i <= 20; ++i){ 116 | cout << i << " "; 117 | minQueue.insert(std::make_shared(i)); 118 | } 119 | for (int i = 1; i <= 20; ++i){ 120 | auto result = minQueue.extract_min(); 121 | cout << "\n最小值为(且删除这个最小值): " << *result << endl; 122 | } 123 | 124 | 125 | IntMinqueueType minQueue1(10, intCompare, intGetType); 126 | cout << "在序列: "; 127 | for (int i = 10; i >= 1; --i){ 128 | cout << i << " "; 129 | minQueue1.insert(std::make_shared(i)); 130 | } 131 | for (int i = 1; i <= 10; ++i){ 132 | auto result = minQueue1.extract_min(); 133 | cout << "\n最小值为(且删除这个最小值): " << *result << endl; 134 | } 135 | 136 | IntMinqueueType minQueue2(10, intCompare, intGetType); 137 | cout << "在序列: "; 138 | for (int i = 1; i <= 5; ++i){ 139 | cout << i << " "; 140 | minQueue2.insert(std::make_shared(i)); 141 | cout << i << " "; 142 | minQueue2.insert(std::make_shared(i)); 143 | } 144 | for (int i = 1; i <= 10; ++i){ 145 | auto result = minQueue2.extract_min(); 146 | cout << "\n最小值为(且删除这个最小值): " << *result << endl; 147 | } 148 | 149 | IntMinqueueType minQueue3(10, intCompare, intGetType); 150 | cout << "在序列: "; 151 | for (int i = 1; i <= 5; ++i){ 152 | cout << i << " "; 153 | minQueue3.insert(std::make_shared(i)); 154 | cout << -i << " "; 155 | minQueue3.insert(std::make_shared(-i)); 156 | } 157 | for (int i = 1; i <= 10; ++i){ 158 | auto result = minQueue3.extract_min(); 159 | cout << "\n最小值为(且删除这个最小值): " << *result << endl; 160 | } 161 | } 162 | 163 | int main() 164 | { 165 | cout << "*******************************int型整数的测试***********************************" << endl; 166 | insertTest(); 167 | minTest(); 168 | extract_minTest(); 169 | 170 | return 0; 171 | } 172 | -------------------------------------------------------------------------------- /queue_algorithm/queue/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: queue.h queue_test.cpp 8 | $(c++) $(VERSION) -o Test queue_test.cpp 9 | -------------------------------------------------------------------------------- /queue_algorithm/queue/queue.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: queue.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月13日 星期二 14时11分15秒 6 | ************************************************************************/ 7 | 8 | #ifndef _QUEUE_H 9 | #define _QUEUE_H 10 | #include 11 | #include 12 | #include 13 | // Queue: 队列 算法导论10.1 14 | /* 15 | * 在队列中,被删除的是最先插入的元素,队列的实现是一种先进先出的数据结构. 16 | * 队列需要支持的操作: 17 | * --enQueue(S,x): 向队列中插入一个新元素x; 18 | * --deQueue(S): 队列中弹出一个元素; 19 | */ 20 | template 21 | class Queue 22 | { 23 | public: 24 | //****************************构造函数******************************* 25 | Queue(std::size_t numbers): head(0), tail(0) {data.resize(numbers);} 26 | Queue(): head(0), tail(0) {data.resize(20);} 27 | ~Queue() = default; 28 | //****************************成员函数******************************* 29 | // enQueue: 向队列中插入一个元素 30 | /* 31 | * \parameter num: 指向入队元素的指针; 32 | * \return void. 33 | * 当head=tail+1时队列是满的,禁止插入新元素. 34 | */ 35 | void enQueue(std::shared_ptr num) 36 | { 37 | // 检查上溢 38 | if (head % data.size() == (tail + 1) % data.size()){ 39 | std::cerr << "队列已满,禁止插入新元素" << endl; 40 | return; 41 | } 42 | data[tail] = num; 43 | ++tail; // tail自增 44 | if (tail >= data.size()) 45 | tail %= data.size(); 46 | } 47 | // deQueue: 出队 48 | /* 49 | * \retrun 返回出队的元素. 50 | * 当head=tail时队列为空,禁止出队. 51 | */ 52 | std::shared_ptr deQueue() 53 | { 54 | // 检查下溢 55 | if (head % data.size() == tail % data.size()){ 56 | std::cerr << "队列为空,禁止出队" << endl; 57 | return std::shared_ptr(); 58 | } 59 | std::shared_ptr temp = data[head]; 60 | ++head; // head自增 61 | head %= data.size(); 62 | return temp; 63 | } 64 | // empty: 检查队列是否为空 65 | /* 66 | * \return bool: 当队列为空返回false,队列不为空返回true. 67 | * 当head=tail时队列为空. 68 | */ 69 | bool empty() 70 | { 71 | bool isEmpty = true; 72 | if (head % data.size() == tail % data.size()) 73 | isEmpty = false; 74 | return isEmpty; 75 | } 76 | private: 77 | //****************************数据结构******************************* 78 | std::vector> data; // 队列的数据 79 | std::size_t head; // 队头 80 | std::size_t tail; // 队尾 81 | }; 82 | #endif 83 | -------------------------------------------------------------------------------- /queue_algorithm/queue/queue_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: queue_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月13日 星期二 15时57分16秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include "queue.h" 11 | 12 | typedef Queue IntQueue; 13 | typedef Queue DoubleQueue; 14 | 15 | void intTest() 16 | { 17 | IntQueue intQueue(20); 18 | cout << "插入的元素分别为: " << endl; 19 | for (int i = 0; i != 22; ++i){ 20 | cout << i << endl; 21 | intQueue.enQueue(std::make_shared(i)); 22 | } 23 | cout << "依次出队: " << endl; 24 | for (int i = 0; i != 22; ++i){ 25 | auto val_ptr = intQueue.deQueue(); 26 | if (val_ptr) 27 | cout << *val_ptr << " "; 28 | } 29 | } 30 | 31 | void doubleTest() 32 | { 33 | DoubleQueue doubleQueue(20); 34 | cout << "插入的元素分别为: " << endl; 35 | for (int i = 0; i != 22; ++i){ 36 | cout << i*0.01 << endl; 37 | doubleQueue.enQueue(std::make_shared(i*0.01)); 38 | } 39 | cout << "依次出队: " << endl; 40 | for (int i = 0; i != 22; ++i){ 41 | auto val_ptr = doubleQueue.deQueue(); 42 | if (val_ptr) 43 | cout << *val_ptr << " "; 44 | } 45 | } 46 | int main() 47 | { 48 | intTest(); 49 | doubleTest(); 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /select_algorithm/good_select/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: goodSelect.h goodSelect_test.cpp 8 | $(c++) $(VERSION) -o Test goodSelect_test.cpp 9 | -------------------------------------------------------------------------------- /select_algorithm/good_select/goodSelect.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: goodSelect.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月12日 星期一 09时57分57秒 6 | ************************************************************************/ 7 | 8 | #ifndef _GOODSELECT_H 9 | #define _GOODSELECT_H 10 | 11 | #include 12 | #include 13 | #include 14 | // insertSort: 插入排序 算法导论2.1 15 | /* 16 | * \parameter begin: 待排序序列的起始迭代器(也可以是指向数组中某元素的指针); 17 | * \parameter end: 待排序序列的终止迭代器(也可以是指向数组中某元素的指针); 18 | * \parameter compare: 一个可调用对象,可用于比较两个对象的小于比较,默认为std::less; 19 | * \return void. 20 | * 21 | * 算法性能: O(N^2), 原址排序. 22 | * 算法基本思想: 插入排序是对少量元素的排序,它是一个有效的算法.假设数组A[1,...,n]排序: 23 | * 设当前排序元素是A[i],则A[1,...,i-1]是排序好的,A[i]在A[1,...,i-1]中找 24 | * 到它的位置,然后插入其中. 25 | * 26 | */ 27 | template::value_type>> 28 | void insertSort(const Iterator begin, const Iterator end, CompareType compare = CompareType()) 29 | { 30 | auto size = std::distance(begin, end); 31 | assert(size > 0); 32 | for (auto current = begin; current != end; ++current){ 33 | auto smallNext = current; // 指向比*current小的元素中,最大的那一个 34 | auto key = *current; 35 | while (smallNext != begin && compare(key, *(smallNext - 1))){ 36 | *smallNext = *(smallNext - 1); // 后移 37 | --smallNext; 38 | } 39 | *smallNext = key; 40 | } 41 | } 42 | // partition: 快速排序算法中的划分算法 算法导论7.1 随机化版本在7.3 43 | /* 44 | * \parameter begin: 待划分序列的起始迭代器(也可以是指向数组中某元素的指针); 45 | * \parameter end: 待划分序列的终止迭代器(也可以是指向数组中某元素的指针); 46 | * \parameter partitioned_iter: 指定划分元素对应的迭代器(也可以是指向数组中某元素的指针); 47 | * \parameter compare: 一个可调用对象,可用于比较两个对象的小于比较, 默认为std::less; 48 | * \retrun void. 49 | * 50 | * 算法性能: 时间复杂度为O(N), 原址操作. 51 | * 算法基本思想: 假定对数组A[p,...,r]划分: 52 | * --划分的目的是找到一个主元素假定q,使其满足: 53 | * --A[p,...,q-1]的所有元素都小于A[q]; 54 | * --A[q+1,...,r]的所有元素都大于A[q]. 55 | * --假定主元为A[r]; 56 | * --循环不等式: 令current=begin, i=begin; 57 | * --若A[current] < A[r], 则交换A[r]和A[current], i右移, current右移; 58 | * --若A[current] > A[r], current右移.(进行下一个元素的判定). 59 | * 60 | */ 61 | template::value_type>> 62 | Iterator partition(const Iterator begin, const Iterator end, 63 | const Iterator partitioned_iter, CompareType compare = CompareType()) 64 | { 65 | assert(std::distance(begin, partitioned_iter) >= 0 && std::distance(partitioned_iter, end) > 0 66 | && std::distance(begin, end) > 0); 67 | std::swap(*partitioned_iter, *(end - 1)); // 把待定主元交换到序列最后一个元素 68 | auto i = begin; 69 | for (auto current = begin; current != (end - 1); ++current){ 70 | if (compare(*current, *(end - 1))) 71 | std::swap(*i++, *current); 72 | } 73 | std::swap(*i, *(end - 1)); 74 | 75 | return i; 76 | } 77 | // goodSelect: 最坏情况下为线性时间的选择算法 算法导论9.3 78 | /* 79 | * \parameter begin: 待选择序列的起始迭代器(也可以是指向数组中某元素的指针); 80 | * \parameter end: 待选择序列的终止迭代器(也可以是指向数组中某元素的指针); 81 | * \parameter rank: 指定选取的顺序数,0为最小,1为次小,...依次类推; 82 | * \parameter compare: 一个可调用对象,可以用于对两个对象的小于比较,默认为std::less; 83 | * \return 第rank小的元素. 84 | * 85 | * 算法基本思想: 86 | * --1.将输入数组的n个元素划分为n/5组,每组5个元素,且最多只有一组由剩下的n%5个元素组成; 87 | * --2.寻找这n/5组中每一组的中位数: 首先对每组元素进行插入排序,然后确定每组有序元素的中位数; 88 | * --3.对第2步中找出的这n/5个中位数,递归调用goodSelsct以找出其中位数x(如果有偶数个中位数,为了方便,约定x是较小的中位数); 89 | * --4.利用修改过的partition版本,按中位数的中位数x对输入数组进行划分.让k比划分的低区中的元素数目多1, 90 | * 因此x是第k小的元素,并且有n-k个元素在划分的高区; 91 | * --5.如果i=k,则返回x.如果ik,则在高区递归查找第i-k小的元素. 92 | * 93 | * 算法性能: 最坏情况下运行时间为O(N), 非原地操作. 94 | * 95 | */ 96 | template::value_type>> 97 | typename std::iterator_traits::value_type 98 | goodSelect(const Iterator begin, const Iterator end, 99 | typename std::iterator_traits::difference_type rank, CompareType compare = CompareType()) 100 | { 101 | typedef typename std::iterator_traits::value_type T; 102 | auto size = std::distance(begin, end); 103 | assert(size > 0); 104 | assert(rank < size); 105 | // 基准情形 106 | if (size == 1) 107 | return *begin; 108 | // 将序列划分为5个元素一组的区间, 最后一组可能不满5个元素;对每组进行排序,取出其中值放入vector中 109 | auto iter = begin; 110 | std::vector middle_nums; 111 | while (iter < end){ 112 | auto from = iter; 113 | auto to = from + 5; 114 | if (to > end) 115 | to = end; 116 | insertSort(from, to, compare); 117 | middle_nums.push_back(*(from+(to-from-1)/2)); 118 | iter += 5; 119 | } 120 | // 取出这些中值的中值 121 | T mid_of_middles = goodSelect(middle_nums.begin(), middle_nums.end(), middle_nums.size()/2, compare); // 所有中值的中值 122 | iter = begin; 123 | while (std::distance(iter, end) > 0 && *iter != mid_of_middles) // 得到中值的中值在原序列中的位置 124 | iter++; 125 | // 划分 126 | auto mid_of_middles_iter = partition(begin, end, iter, compare); // 以中值的中值作为一个划分值 127 | // 判别 128 | auto mid_of_middles_rank = std::distance(begin, mid_of_middles_iter); // 中值的中值在划分之后的排序 129 | if (mid_of_middles_rank == rank) // 找到了该排位的数 130 | return *mid_of_middles_iter; 131 | else if (mid_of_middles_rank < rank) // 已知某排位的数位较低,则指定排位数的元素在它的右侧 132 | // mid_of_middles_iter + 1,则找右侧的第rank-mid_of_middles_rank-1位 133 | return goodSelect(mid_of_middles_iter + 1, end, rank - mid_of_middles_rank - 1, compare); 134 | else 135 | return goodSelect(begin, mid_of_middles_iter, rank, compare); 136 | } 137 | #endif 138 | -------------------------------------------------------------------------------- /select_algorithm/good_select/goodSelect_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: goodSelect_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月12日 星期一 14时58分48秒 6 | ************************************************************************/ 7 | #include 8 | using std::cout; using std::endl; 9 | #include 10 | using std::vector; 11 | #include 12 | using std::begin; using std::end; 13 | #include "goodSelect.h" 14 | 15 | bool compare(int num1, int num2) 16 | { 17 | return num1 > num2; 18 | } 19 | 20 | template 21 | void print(const Iterator begin, const Iterator end) 22 | { 23 | for (auto current = begin; current != end; ++current) 24 | cout << *current << " "; 25 | cout << endl; 26 | } 27 | 28 | void Test1() 29 | { 30 | vector vec{1,2,3,4,5,6,7,8,9,10}; 31 | vector vec1{10,9,8,7,6,5,4,3,2,1}; 32 | vector vec2{1,1,1,1,1,5,5,5,5,5}; 33 | vector vec3{1}; 34 | 35 | int min = goodSelect(vec.begin(), vec.end(), 0); 36 | cout << "序列: "; 37 | print(vec.begin(), vec.end()); 38 | cout << "的最小值为 " << min << endl; 39 | 40 | 41 | min = goodSelect(vec1.begin(), vec1.end(), 1); 42 | cout << "序列: "; 43 | print(vec1.begin(), vec1.end()); 44 | cout << "的次小值为 " << min << endl; 45 | 46 | 47 | min = goodSelect(vec2.begin(), vec2.end(), 0); 48 | cout << "序列: "; 49 | print(vec2.begin(), vec2.end()); 50 | cout << "的最小值为 " << min << endl; 51 | 52 | min = goodSelect(vec3.begin(), vec3.end(), 0); 53 | cout << "序列: "; 54 | print(vec3.begin(), vec3.end()); 55 | cout << "的最小值为 " << min << endl; 56 | 57 | } 58 | 59 | void Test2() 60 | { 61 | vector vec{1,2,3,4,5,6,7,8,9,10}; 62 | vector vec1{10,9,8,7,6,5,4,3,2,1}; 63 | vector vec2{1,1,1,1,1,5,5,5,5,5}; 64 | vector vec3{1}; 65 | 66 | int min = goodSelect(vec.begin(), vec.end(), 0, compare); 67 | cout << "序列: "; 68 | print(vec.begin(), vec.end()); 69 | cout << "的最大值为 " << min << endl; 70 | 71 | min = goodSelect(vec1.begin(), vec1.end(), 1, compare); 72 | cout << "序列: "; 73 | print(vec1.begin(), vec1.end()); 74 | cout << "的次大值为 " << min << endl; 75 | 76 | min = goodSelect(vec2.begin(), vec2.end(), 0, compare); 77 | cout << "序列: "; 78 | print(vec2.begin(), vec2.end()); 79 | cout << "的最大值为 " << min << endl; 80 | 81 | min = goodSelect(vec3.begin(), vec3.end(), 0, compare); 82 | cout << "序列: "; 83 | print(vec3.begin(), vec3.end()); 84 | cout << "的最大值为 " << min << endl; 85 | } 86 | 87 | void Test3() 88 | { 89 | int data1[10] = {1,2,3,4,5,6,7,8,9,10}; 90 | int data2[10] = {10,9,8,7,6,5,4,3,2,1}; 91 | int data3[10] = {1,1,1,1,1,5,5,5,5,5}; 92 | int data4[1] = {1}; 93 | 94 | int min = goodSelect(begin(data1), end(data1), 0); 95 | cout << "序列: "; 96 | print(begin(data1), end(data1)); 97 | cout << "的最小值为: " << min << endl; 98 | 99 | min = goodSelect(begin(data2), end(data2), 1); 100 | cout << "序列: "; 101 | print(begin(data2), end(data2)); 102 | cout << "的次小值为: " << min << endl; 103 | 104 | min = goodSelect(begin(data3), end(data3), 0); 105 | cout << "序列: "; 106 | print(begin(data3), end(data3)); 107 | cout << "的最小值为: " << min << endl; 108 | 109 | min = goodSelect(begin(data4), end(data4), 0); 110 | cout << "序列: "; 111 | print(begin(data4), end(data4)); 112 | cout << "的最小值为: " << min << endl; 113 | } 114 | 115 | void Test4() 116 | { 117 | int data1[10] = {1,2,3,4,5,6,7,8,9,10}; 118 | int data2[10] = {10,9,8,7,6,5,4,3,2,1}; 119 | int data3[10] = {1,1,1,1,1,5,5,5,5,5}; 120 | int data4[1] = {1}; 121 | 122 | int min = goodSelect(begin(data1), end(data1), 0, compare); 123 | cout << "序列: "; 124 | print(begin(data1), end(data1)); 125 | cout << "的最大值为: " << min << endl; 126 | 127 | min = goodSelect(begin(data2), end(data2), 1, compare); 128 | cout << "序列: "; 129 | print(begin(data2), end(data2)); 130 | cout << "的次大值为: " << min << endl; 131 | 132 | min = goodSelect(begin(data3), end(data3), 0, compare); 133 | cout << "序列: "; 134 | print(begin(data3), end(data3)); 135 | cout << "的最大值为: " << min << endl; 136 | 137 | min = goodSelect(begin(data4), end(data4), 0, compare); 138 | cout << "序列: "; 139 | print(begin(data4), end(data4)); 140 | cout << "的最大值为: " << min << endl; 141 | } 142 | 143 | 144 | int main() 145 | { 146 | cout << "***********vector整型数组求最小值**********" << endl; 147 | Test1(); 148 | cout << "***********vector整型数组求最大值**********" << endl; 149 | Test2(); 150 | cout << "*************C整型数组求最小值*************" << endl; 151 | Test3(); 152 | cout << "*************C整型数组求最大值*************" << endl; 153 | Test4(); 154 | 155 | return 0; 156 | } 157 | -------------------------------------------------------------------------------- /select_algorithm/minimum/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: minimum.h minimum_test.cpp 8 | $(c++) $(VERSION) -o Test minimum_test.cpp 9 | -------------------------------------------------------------------------------- /select_algorithm/minimum/minimum.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: minimum.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月11日 星期日 10时59分55秒 6 | ************************************************************************/ 7 | 8 | #ifndef _MINIMUM_H 9 | #define _MINIMUM_H 10 | #include 11 | #include 12 | // minimum: 从一个集合中选择选择最小元素和最大元素的问题 算法导论9.1 13 | /* 14 | * \parameter begin: 待排序序列的起始迭代器(也可以是指向数组中某元素的指针); 15 | * \parameter end: 待排序序列的终止迭代器(也可以是指向数组中某元素的指针); 16 | * \parameter compare: 一个可调用对象,可用于比较两个对象的小于,默认为std::less; 17 | * \return 这个序列中的最值(typename std::iterator_traits::value_type). 18 | * 19 | * 算法性能: 时间复杂度为: O(N). 20 | * 算法基本思想: 依次遍历集合中的每个元素,并记录下当前的最小元素. 21 | * 22 | */ 23 | template::value_type>> 24 | typename std::iterator_traits::value_type 25 | minimum(const Iterator begin, const Iterator end, CompareType compare = CompareType()) 26 | { 27 | assert(begin != end); // 保证输入的序列不是空序列 28 | typedef typename std::iterator_traits::value_type T; 29 | T min = *begin; 30 | for (auto current = begin; current != end; ++current){ 31 | if (compare(*current, min)) 32 | min = *current; 33 | } 34 | 35 | return min; 36 | } 37 | #endif 38 | -------------------------------------------------------------------------------- /select_algorithm/minimum/minimum_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: minimum_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月11日 星期日 11时11分50秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include 11 | using std::vector; 12 | #include "minimum.h" 13 | #include 14 | using std::begin; using std::end; 15 | 16 | bool compare(int num1, int num2) 17 | { 18 | return num1 > num2; 19 | } 20 | 21 | 22 | template 23 | void print(const Iterator begin, const Iterator end) 24 | { 25 | for (auto current = begin; current != end; ++current) 26 | cout << *current << " "; 27 | cout << endl; 28 | } 29 | 30 | void Test1() 31 | { 32 | vector vec{1,2,3,4,5,6,7,8,9,10}; 33 | vector vec1{10,9,8,7,6,5,4,3,2,1}; 34 | vector vec2{1,1,1,1,1,5,5,5,5,5}; 35 | vector vec3{1}; 36 | 37 | int min = minimum(vec.begin(), vec.end()); 38 | cout << "序列: "; 39 | print(vec.begin(), vec.end()); 40 | cout << "的最小值为 " << min << endl; 41 | 42 | min = minimum(vec1.begin(), vec1.end()); 43 | cout << "序列: "; 44 | print(vec1.begin(), vec1.end()); 45 | cout << "的最小值为 " << min << endl; 46 | 47 | min = minimum(vec2.begin(), vec2.end()); 48 | cout << "序列: "; 49 | print(vec2.begin(), vec2.end()); 50 | cout << "的最小值为 " << min << endl; 51 | 52 | min = minimum(vec3.begin(), vec3.end()); 53 | cout << "序列: "; 54 | print(vec3.begin(), vec3.end()); 55 | cout << "的最小值为 " << min << endl; 56 | } 57 | 58 | void Test2() 59 | { 60 | vector vec{1,2,3,4,5,6,7,8,9,10}; 61 | vector vec1{10,9,8,7,6,5,4,3,2,1}; 62 | vector vec2{1,1,1,1,1,5,5,5,5,5}; 63 | vector vec3{1}; 64 | 65 | int min = minimum(vec.begin(), vec.end(), compare); 66 | cout << "序列: "; 67 | print(vec.begin(), vec.end()); 68 | cout << "的最大值为 " << min << endl; 69 | 70 | min = minimum(vec1.begin(), vec1.end(), compare); 71 | cout << "序列: "; 72 | print(vec1.begin(), vec1.end()); 73 | cout << "的最大值为 " << min << endl; 74 | 75 | min = minimum(vec2.begin(), vec2.end(), compare); 76 | cout << "序列: "; 77 | print(vec2.begin(), vec2.end()); 78 | cout << "的最大值为 " << min << endl; 79 | 80 | min = minimum(vec3.begin(), vec3.end(), compare); 81 | cout << "序列: "; 82 | print(vec3.begin(), vec3.end()); 83 | cout << "的最大值为 " << min << endl; 84 | } 85 | 86 | void Test3() 87 | { 88 | int data1[10] = {1,2,3,4,5,6,7,8,9,10}; 89 | int data2[10] = {10,9,8,7,6,5,4,3,2,1}; 90 | int data3[10] = {1,1,1,1,1,5,5,5,5,5}; 91 | int data4[1] = {1}; 92 | 93 | int min = minimum(begin(data1), end(data1)); 94 | cout << "序列: "; 95 | print(begin(data1), end(data1)); 96 | cout << "的最小值为: " << min << endl; 97 | 98 | min = minimum(begin(data2), end(data2)); 99 | cout << "序列: "; 100 | print(begin(data2), end(data2)); 101 | cout << "的最小值为: " << min << endl; 102 | 103 | min = minimum(begin(data3), end(data3)); 104 | cout << "序列: "; 105 | print(begin(data3), end(data3)); 106 | cout << "的最小值为: " << min << endl; 107 | 108 | min = minimum(begin(data4), end(data4)); 109 | cout << "序列: "; 110 | print(begin(data4), end(data4)); 111 | cout << "的最小值为: " << min << endl; 112 | } 113 | 114 | void Test4() 115 | { 116 | int data1[10] = {1,2,3,4,5,6,7,8,9,10}; 117 | int data2[10] = {10,9,8,7,6,5,4,3,2,1}; 118 | int data3[10] = {1,1,1,1,1,5,5,5,5,5}; 119 | int data4[1] = {1}; 120 | 121 | int min = minimum(begin(data1), end(data1), compare); 122 | cout << "序列: "; 123 | print(begin(data1), end(data1)); 124 | cout << "的最大值为: " << min << endl; 125 | 126 | min = minimum(begin(data2), end(data2), compare); 127 | cout << "序列: "; 128 | print(begin(data2), end(data2)); 129 | cout << "的最大值为: " << min << endl; 130 | 131 | min = minimum(begin(data3), end(data3), compare); 132 | cout << "序列: "; 133 | print(begin(data3), end(data3)); 134 | cout << "的最大值为: " << min << endl; 135 | 136 | min = minimum(begin(data4), end(data4), compare); 137 | cout << "序列: "; 138 | print(begin(data4), end(data4)); 139 | cout << "的最大值为: " << min << endl; 140 | } 141 | 142 | 143 | int main() 144 | { 145 | cout << "***********vector整型数组求最小值**********" << endl; 146 | Test1(); 147 | cout << "***********vector整型数组求最大值**********" << endl; 148 | Test2(); 149 | cout << "*************C整型数组求最小值*************" << endl; 150 | Test3(); 151 | cout << "*************C整型数组求最大值*************" << endl; 152 | Test4(); 153 | 154 | return 0; 155 | } 156 | 157 | -------------------------------------------------------------------------------- /select_algorithm/randomized_select/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: randomizedSelect_test.cpp randomizedSelect.h 8 | $(c++) $(VERSION) -o Test randomizedSelect_test.cpp 9 | -------------------------------------------------------------------------------- /select_algorithm/randomized_select/randomizedSelect.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: randomizedSelect.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月11日 星期日 15时08分33秒 6 | ************************************************************************/ 7 | 8 | #ifndef _RANDOMIZEDSELECT_H 9 | #define _RANDOMIZEDSELECT_H 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | // randomizedPartition: 快速排序算法中的划分算法 算法导论7.1 16 | /* 17 | * \parameter begin: 待选取序列的起始迭代器(也可以是指向数组中某元素的指针); 18 | * \parameter end: 待选取序列的终止迭代器(也可以是指向数组中某元素的指针); 19 | * \parameter partitioned_iter: 指定划分元素对应的迭代器(也可以是指向数组中某元素的指针); 20 | * \return 返回主元素的指针. 21 | * 22 | * 算法基本思想: 假定对数组A[p,...,r]划分: 23 | * --划分的目的是找到一个主元假定q,使其满足: 24 | * --A[p,...,q-1]的所有元素都小于A[q]; 25 | * --A[q+1,...,r]的所有元素都大于A[q]. 26 | * --假定主元为A[r]; 27 | * --循环不等式: 令current=begin, i=begin; 28 | * --若A[current] < A[r], 则交换A[r]和A[current], i右移, current右移; 29 | * --若A[current] > A[r], current右移.(进行下一个元素的判定). 30 | * 算法时间复杂度: O(N). 31 | * 32 | */ 33 | template::value_type>> 34 | Iterator randomizedPartition(const Iterator begin, const Iterator end, 35 | const Iterator partitioned_iter, CompareType compare = CompareType()) 36 | { 37 | assert(begin != end); // 序列不能是一个空序列 38 | assert(std::distance(begin, partitioned_iter) >= 0 && std::distance(partitioned_iter, end) > 0); 39 | 40 | auto x = *partitioned_iter; 41 | auto i = begin; 42 | std::swap(*partitioned_iter, *(end - 1)); // 元素交换 43 | for(auto current = begin; current != end; ++current){ 44 | if (compare(*current, x)) 45 | std::swap(*i++, *current); 46 | } 47 | std::swap(*i, *(end - 1)); 48 | 49 | return i; 50 | } 51 | // randomiezdSelect: 随机选择算法(期望为线性时间的选择算法) 52 | /* 53 | * \parameter begin: 待选取序列的起始迭代器(也可以是指向数组中某元素的指针); 54 | * \parameter end: 待选取序列的终止迭代器(也可以是指向数组中某元素的指针); 55 | * \parameter minIndex: 选取排序第几的元素(0表示最小(或最大),1表示次小(次大),依次类推); 56 | * \parameter compare: 一个可调用的对象,可用于比较两个对象的小于比较,默认为std::less; 57 | * \return 排序minIndex的元素. 58 | * 59 | * 算法基本思想: 假设对数组A[p,...,r]选择, 选择第k小的元素: 60 | * --随机选择主元: 随机选取数组一个下标q,A[q]作为划分元素; 61 | * --划分: 利用A[q]划分数组, 获得数组A[q]在序列是第m小; 62 | * --判定: 63 | * --若m==k, 则找到了这个元素, 返回A[q]; 64 | * --若mk, 则说明指定的元素在A[p,...,q-1]中,且位于这个新数组的的k小, 67 | * 此时递归调用randomiezdSelect(begin, q, k); 68 | * 时间复杂度: 最坏的情况为 O(N^2), 期望时间复杂度为 O(N); 69 | * 70 | * 算法特性: 原地操作. 71 | * 72 | */ 73 | template::value_type>> 74 | typename std::iterator_traits::value_type 75 | randomiezdSelect(const Iterator begin, const Iterator end, 76 | std::size_t minIndex, CompareType compare = CompareType()) 77 | { 78 | auto size = std::distance(begin, end); 79 | assert(size >= 0); // 序列不能是一个空序列 80 | assert(size >= minIndex); 81 | // 基准情形 82 | if (size <= 1) 83 | return *begin; 84 | std::default_random_engine e; 85 | std::uniform_int_distribution u(0,size); 86 | auto partitioned_iter = randomizedPartition(begin, end, begin + u(e), compare); 87 | auto smallerNumbers = std::distance(begin, partitioned_iter); 88 | if (minIndex == smallerNumbers) 89 | return *partitioned_iter; 90 | if (minIndex < smallerNumbers) 91 | return randomiezdSelect(begin, partitioned_iter, minIndex, compare); 92 | else if (minIndex > smallerNumbers) 93 | return randomiezdSelect(partitioned_iter + 1, end, minIndex - smallerNumbers - 1); 94 | 95 | } 96 | #endif 97 | -------------------------------------------------------------------------------- /select_algorithm/randomized_select/randomizedSelect_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: randomizedSelect_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月11日 星期日 16时35分41秒 6 | ************************************************************************/ 7 | #include 8 | using std::cout; using std::endl; 9 | #include 10 | using std::vector; 11 | #include 12 | using std::begin; using std::end; 13 | #include "randomizedSelect.h" 14 | 15 | bool compare(int num1, int num2) 16 | { 17 | return num1 > num2; 18 | } 19 | 20 | 21 | template 22 | void print(const Iterator begin, const Iterator end) 23 | { 24 | for (auto current = begin; current != end; ++current) 25 | cout << *current << " "; 26 | cout << endl; 27 | } 28 | 29 | void Test1() 30 | { 31 | vector vec{1,2,3,4,5,6,7,8,9,10}; 32 | vector vec1{10,9,8,7,6,5,4,3,2,1}; 33 | vector vec2{1,1,1,1,1,5,5,5,5,5}; 34 | vector vec3{1}; 35 | 36 | int min = randomiezdSelect(vec.begin(), vec.end(), 0); 37 | cout << "序列: "; 38 | print(vec.begin(), vec.end()); 39 | cout << "的最小值为 " << min << endl; 40 | 41 | 42 | min = randomiezdSelect(vec1.begin(), vec1.end(), 1); 43 | cout << "序列: "; 44 | print(vec1.begin(), vec1.end()); 45 | cout << "的次小值为 " << min << endl; 46 | 47 | 48 | min = randomiezdSelect(vec2.begin(), vec2.end(), 0); 49 | cout << "序列: "; 50 | print(vec2.begin(), vec2.end()); 51 | cout << "的最小值为 " << min << endl; 52 | 53 | min = randomiezdSelect(vec3.begin(), vec3.end(), 0); 54 | cout << "序列: "; 55 | print(vec3.begin(), vec3.end()); 56 | cout << "的最小值为 " << min << endl; 57 | 58 | } 59 | 60 | void Test2() 61 | { 62 | vector vec{1,2,3,4,5,6,7,8,9,10}; 63 | vector vec1{10,9,8,7,6,5,4,3,2,1}; 64 | vector vec2{1,1,1,1,1,5,5,5,5,5}; 65 | vector vec3{1}; 66 | 67 | int min = randomiezdSelect(vec.begin(), vec.end(), 0, compare); 68 | cout << "序列: "; 69 | print(vec.begin(), vec.end()); 70 | cout << "的最大值为 " << min << endl; 71 | 72 | min = randomiezdSelect(vec1.begin(), vec1.end(), 1, compare); 73 | cout << "序列: "; 74 | print(vec1.begin(), vec1.end()); 75 | cout << "的次大值为 " << min << endl; 76 | 77 | min = randomiezdSelect(vec2.begin(), vec2.end(), 0, compare); 78 | cout << "序列: "; 79 | print(vec2.begin(), vec2.end()); 80 | cout << "的最大值为 " << min << endl; 81 | 82 | min = randomiezdSelect(vec3.begin(), vec3.end(), 0, compare); 83 | cout << "序列: "; 84 | print(vec3.begin(), vec3.end()); 85 | cout << "的最大值为 " << min << endl; 86 | } 87 | 88 | void Test3() 89 | { 90 | int data1[10] = {1,2,3,4,5,6,7,8,9,10}; 91 | int data2[10] = {10,9,8,7,6,5,4,3,2,1}; 92 | int data3[10] = {1,1,1,1,1,5,5,5,5,5}; 93 | int data4[1] = {1}; 94 | 95 | int min = randomiezdSelect(begin(data1), end(data1), 0); 96 | cout << "序列: "; 97 | print(begin(data1), end(data1)); 98 | cout << "的最小值为: " << min << endl; 99 | 100 | min = randomiezdSelect(begin(data2), end(data2), 1); 101 | cout << "序列: "; 102 | print(begin(data2), end(data2)); 103 | cout << "的次小值为: " << min << endl; 104 | 105 | min = randomiezdSelect(begin(data3), end(data3), 0); 106 | cout << "序列: "; 107 | print(begin(data3), end(data3)); 108 | cout << "的最小值为: " << min << endl; 109 | 110 | min = randomiezdSelect(begin(data4), end(data4), 0); 111 | cout << "序列: "; 112 | print(begin(data4), end(data4)); 113 | cout << "的最小值为: " << min << endl; 114 | } 115 | 116 | void Test4() 117 | { 118 | int data1[10] = {1,2,3,4,5,6,7,8,9,10}; 119 | int data2[10] = {10,9,8,7,6,5,4,3,2,1}; 120 | int data3[10] = {1,1,1,1,1,5,5,5,5,5}; 121 | int data4[1] = {1}; 122 | 123 | int min = randomiezdSelect(begin(data1), end(data1), 0, compare); 124 | cout << "序列: "; 125 | print(begin(data1), end(data1)); 126 | cout << "的最大值为: " << min << endl; 127 | 128 | min = randomiezdSelect(begin(data2), end(data2), 1, compare); 129 | cout << "序列: "; 130 | print(begin(data2), end(data2)); 131 | cout << "的次大值为: " << min << endl; 132 | 133 | min = randomiezdSelect(begin(data3), end(data3), 0, compare); 134 | cout << "序列: "; 135 | print(begin(data3), end(data3)); 136 | cout << "的最大值为: " << min << endl; 137 | 138 | min = randomiezdSelect(begin(data4), end(data4), 0, compare); 139 | cout << "序列: "; 140 | print(begin(data4), end(data4)); 141 | cout << "的最大值为: " << min << endl; 142 | } 143 | 144 | 145 | int main() 146 | { 147 | cout << "***********vector整型数组求最小值**********" << endl; 148 | Test1(); 149 | cout << "***********vector整型数组求最大值**********" << endl; 150 | Test2(); 151 | cout << "*************C整型数组求最小值*************" << endl; 152 | Test3(); 153 | cout << "*************C整型数组求最大值*************" << endl; 154 | Test4(); 155 | 156 | return 0; 157 | } 158 | -------------------------------------------------------------------------------- /sort_algorithm/bucket_sort/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: bucketSort.h bucketSort_test.cpp 8 | $(c++) $(VERSION) -o Test bucketSort_test.cpp 9 | -------------------------------------------------------------------------------- /sort_algorithm/bucket_sort/bucketSort.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: bucketSort.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月10日 星期六 20时46分42秒 6 | ************************************************************************/ 7 | 8 | #ifndef _BUCKETSORT_H 9 | #define _BUCKETSORT_H 10 | #include 11 | #include 12 | #include 13 | #include "../quick_sort/quickSort.h" 14 | const std::size_t real_bucket_num = 10; // 桶排序时划分10个小区间 15 | // bucketSort: 桶排序 算法导论8.4 16 | /* 17 | * \parameter begin: 待排序序列的起始迭代器(也可以是指向数组中某元素的指针); 18 | * \parameter end: 待排序序列的终止迭代器(也可以是指向数组中某元素的指针); 19 | * \parameter min_value: 待排序序列元素的下界(不一定是最紧下界); 20 | * \parameter max_value: 待排序序列元素的上届(不一定是最紧上界); 21 | * \return void. 22 | * 23 | * 算法基本思想: 桶排序将[0, 1]区间划分为n个相同大小的子区间, 或称为桶. 24 | * 然后,将n个输入数分别放到各个桶中.为了得到输出结果,我们先对 25 | * 每个桶中的数进行排序, 然后遍历每个桶, 按照次序把各个桶中的 26 | * 元素列出来即可. 27 | * 算法性能: 桶排序算法假设输入数据服从均匀分布,平均情况下它的时间代价是O(N). 28 | * --非原地排序算法. 29 | */ 30 | template 31 | void bucketSort(const Iterator begin, const Iterator end, 32 | const typename std::iterator_traits::value_type &min_value, 33 | const typename std::iterator_traits::value_type &max_value) 34 | { 35 | assert(min_value < max_value); // 确保最小值要小于最大值 36 | // 迭代器指向对象值的类型 37 | typedef typename std::iterator_traits::value_type T; 38 | std::vector buckets[real_bucket_num]; 39 | for (auto current = begin; current != end; ++current){ 40 | // 归一化处理 41 | int index = (*current - min_value) * real_bucket_num / (max_value - min_value); 42 | buckets[index].push_back(*current); // 把元素放到桶中 43 | } 44 | // 对每一个区间进行排序 45 | std::size_t inserted_total = 0; 46 | for (int i = 0; i != real_bucket_num; ++i){ 47 | quickSort(buckets[i].begin(), buckets[i].end()); 48 | std::copy(buckets[i].begin(), buckets[i].end(), begin + inserted_total); // 非原址排序 49 | inserted_total += buckets[i].size(); 50 | } 51 | } 52 | #endif 53 | -------------------------------------------------------------------------------- /sort_algorithm/bucket_sort/bucketSort_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: bucketSort_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月10日 星期六 21时57分35秒 6 | ************************************************************************/ 7 | #include 8 | using std::cout; using std::endl; 9 | #include 10 | using std::begin; using std::end; 11 | #include 12 | using std::vector; 13 | #include 14 | using std::sort; 15 | #include "bucketSort.h" 16 | 17 | // 数组输出函数 18 | template 19 | void print(const Iterator begin, const Iterator end) 20 | { 21 | for (auto current = begin; current != end; ++current) 22 | cout << *current << " "; 23 | cout << endl; 24 | } 25 | 26 | void Test1() 27 | { 28 | double data1[10] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.99}; 29 | double data2[10] = {0.99, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1}; 30 | double data3[10] = {0.1, 0.1, 0.1, 0.1, 0.1, 0.5, 0.5, 0.5, 0.5, 0.5}; 31 | double data4[1] = {0.2}; 32 | double data5[10] = {0.32, 0.45, 0.33, 0.456, 0.342, 0.456, 0.87, 0.78, 0.98, 0.99}; 33 | 34 | double compareData1[10] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,0.99}; 35 | double compareData2[10] = {0.99, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1}; 36 | double compareData3[10] = {0.1, 0.1, 0.1, 0.1, 0.1, 0.5, 0.5, 0.5, 0.5, 0.5}; 37 | double compareData4[1] = {0.2}; 38 | double compareData5[10] = {0.32, 0.45, 0.33, 0.456, 0.342, 0.456, 0.87, 0.78, 0.98, 0.99}; 39 | 40 | bucketSort(begin(data1), end(data1),0, 1); 41 | sort(begin(compareData1), end(compareData1)); 42 | 43 | bucketSort(begin(data2), end(data2),0, 1); 44 | sort(begin(compareData2), end(compareData2)); 45 | 46 | bucketSort(begin(data3), end(data3),0, 1); 47 | sort(begin(compareData3), end(compareData3)); 48 | 49 | bucketSort(begin(data4), end(data4),0, 1); 50 | sort(begin(compareData4), end(compareData4)); 51 | 52 | bucketSort(begin(data5), end(data5),0, 1); 53 | sort(begin(compareData5), end(compareData5)); 54 | 55 | // 输出排序后的数组 56 | cout << "****************对升序数组进行测试*********************\n"; 57 | cout << "bucketSort排序结果:\n"; 58 | print(begin(data1), end(data1)); 59 | cout << "sort排序结果:\n"; 60 | print(begin(compareData1), end(compareData1)); 61 | 62 | cout << "****************对降序数组进行测试*********************\n"; 63 | cout << "bucketSort排序结果:\n"; 64 | print(begin(data2), end(data2)); 65 | cout << "函数库sort排序结果:\n"; 66 | print(begin(compareData2), end(compareData2)); 67 | 68 | cout << "****************对有重复数字进行测试*******************\n"; 69 | cout << "bucketSort排序结果:\n"; 70 | print(begin(data3), end(data3)); 71 | cout << "函数库sort排序结果:\n"; 72 | print(begin(compareData3), end(compareData3)); 73 | 74 | cout << "****************单个数组元素的测试*********************\n"; 75 | cout << "bucketSort排序结果:\n"; 76 | print(begin(data4), end(data4)); 77 | cout << "函数库sort排序结果:\n"; 78 | print(begin(compareData4), end(compareData4)); 79 | 80 | cout << "****************混乱数组元素的测试*********************\n"; 81 | cout << "bucketSort排序结果:\n"; 82 | print(begin(data5), end(data5)); 83 | cout << "函数库sort排序结果:\n"; 84 | print(begin(compareData5), end(compareData5)); 85 | } 86 | 87 | void Test2() 88 | { 89 | vector data1{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.99}; 90 | vector compareData1(data1.begin(), data1.end()); 91 | vector data2{0.99, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1}; 92 | vector compareData2(data2.begin(), data2.end()); 93 | vector data3{0.1, 0.1, 0.1, 0.1, 0.1, 0.5, 0.5, 0.5, 0.5, 0.5}; 94 | vector compareData3(data3.begin(), data3.end()); 95 | vector data4{0.5}; 96 | vector compareData4{0.5}; 97 | vector data5{0.32, 0.45, 0.33, 0.456, 0.342, 0.456, 0.87, 0.78, 0.98, 0.99}; 98 | vector compareData5(data5.begin(), data5.end()); 99 | 100 | bucketSort(data1.begin(), data1.end(), 0, 1); 101 | sort(compareData1.begin(), compareData1.end()); 102 | 103 | bucketSort(data2.begin(), data2.end(), 0, 1); 104 | sort(compareData2.begin(), compareData2.end()); 105 | 106 | bucketSort(data3.begin(), data3.end(), 0, 1); 107 | sort(compareData3.begin(), compareData3.end()); 108 | 109 | bucketSort(data4.begin(), data4.end(), 0, 1); 110 | sort(compareData4.begin(), compareData4.end()); 111 | 112 | bucketSort(data5.begin(), data5.end(), 0, 1); 113 | sort(compareData5.begin(), compareData5.end()); 114 | 115 | cout << "****************对升序数组进行测试*********************\n"; 116 | cout << "bucketSort排序结果:\n"; 117 | print(data1.begin(), data1.end()); 118 | cout << "函数库sort排序结果:\n"; 119 | print(compareData1.begin(), compareData1.end()); 120 | 121 | cout << "****************对降序数组进行测试*********************\n"; 122 | cout << "bucketSort排序结果:\n"; 123 | print(data2.begin(), data2.end()); 124 | cout << "函数库sort排序结果:\n"; 125 | print(compareData2.begin(), compareData2.end()); 126 | 127 | cout << "****************对有重复数字进行测试*******************\n"; 128 | cout << "bucketSort排序结果:\n"; 129 | print(data3.begin(), data3.end()); 130 | cout << "函数库sort排序结果:\n"; 131 | print(compareData3.begin(), compareData3.end()); 132 | 133 | cout << "****************对单个数字进行测试*********************\n"; 134 | cout << "bucketSort排序结果\n"; 135 | print(data4.begin(), data4.end()); 136 | cout << "函数库sort排序结果:\n"; 137 | print(compareData4.begin(), compareData4.end()); 138 | 139 | cout << "****************对混乱数据进行测试*********************\n"; 140 | cout << "bucketSort排序结果:\n"; 141 | print(data5.begin(), data5.end()); 142 | cout << "函数库sort排序结果:\n"; 143 | print(compareData5.begin(), compareData5.end()); 144 | 145 | } 146 | 147 | int main() 148 | { 149 | 150 | cout << "****************对C数组升序排列测试********************\n"; 151 | Test1(); 152 | 153 | cout << "****************对vector数组升序排列测试***************\n"; 154 | Test2(); 155 | 156 | return 0; 157 | } 158 | -------------------------------------------------------------------------------- /sort_algorithm/counting_sort/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: countingSort.h countingSort_test.cpp 8 | $(c++) $(VERSION) -o Test countingSort_test.cpp 9 | -------------------------------------------------------------------------------- /sort_algorithm/counting_sort/countingSort.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: countingSort.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月09日 星期五 10时17分32秒 6 | ************************************************************************/ 7 | 8 | #ifndef _COUNTINGSORT_H 9 | #define _COUNTINGSORT_H 10 | #include 11 | #include 12 | // countingSort: 计数排序 算法导论8.2 13 | /* 14 | * \parameter begin: 待排序序列的起始迭代器(也可以是指向数组中某元素的指针); 15 | * \parameter end: 待排序序列的终止迭代器(也可以是指向数组中某元素的指针); 16 | * \parameter maxVal: 待排序序列中的最大值. 17 | * \return void. 18 | * 19 | * 算法性能:时间复杂度 O(N). 空间复杂度O(N);算法只能够适应于整数排序. 20 | * 21 | * 算法基本思想: 对每一个输入元素x,确定小于x的元素的个数.利用这一信息,就可以直接 22 | * --把x放在它在输出数组中的位置上了.例如,如果有17个元素小于x,则x就应该在第18个输出位置 23 | * --上.当有几个元素相同时,这一方案要略做修改.因为不能把它们放在同一个输出位置上. 24 | * 25 | * 算法特点: 计数排序已经不属于比较排序算法了, 在代码中也完全没有输入元素之间的比较操作. 26 | * --计数排序一个重要的特点就是它是稳定的.具有相同值的元素在输出数组中的相对次序与它们 27 | * --在输入数组中的相对次序相同.也就是说,对两个相同的数来说,在输入数组中先出现数,在输出数组 28 | * --中的相对次序也相同. 29 | * 30 | */ 31 | template 32 | void countingSort(const Iterator begin, const Iterator end, 33 | const typename std::iterator_traits::value_type &maxVal) 34 | { 35 | typedef typename std::iterator_traits::value_type T; // 迭代器指向对象值的类型 36 | // 在编译的时候断言T的类型是不是整型,计数排序算法只支持整数类型的排序算法 37 | static_assert(std::is_integral::value, "sequence to be must be integer!"); 38 | auto size = std::distance(begin, end); 39 | if (size <= 1) 40 | return; 41 | std::vector cuntingArray(maxVal+1,0); 42 | // 计数过程(cuntingArray[i]保存的就是等于i元素的个数) 43 | for (auto current = begin; current != end; ++current) 44 | cuntingArray[*current] += 1; 45 | // 通过加总计算确定每一个i=0,1,...,k,有多少输入元素是小于或等于i的 46 | for (decltype(cuntingArray.size()) i = 1; i != cuntingArray.size(); ++i) 47 | cuntingArray[i] += cuntingArray[i-1]; 48 | // 把每个元素A[j]放到它输出数组B的正确位置上. 49 | std::vector temSortArray(size,0); 50 | for (auto current = begin; current != end; ++current){ 51 | temSortArray[cuntingArray[*current] - 1] = *current; 52 | cuntingArray[*current] -= 1; 53 | } 54 | std::copy(temSortArray.begin(), temSortArray.end(), begin); 55 | } 56 | #endif 57 | -------------------------------------------------------------------------------- /sort_algorithm/counting_sort/countingSort_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: countingSort_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月09日 星期五 11时12分38秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | #include 11 | using std::cout; using std::endl; 12 | #include 13 | using std::begin; using std::end; 14 | #include 15 | using std::vector; 16 | #include 17 | using std::sort; 18 | #include "countingSort.h" 19 | 20 | // 数组输出函数 21 | template 22 | void print(const Iterator begin, const Iterator end) 23 | { 24 | for (auto current = begin; current != end; ++current) 25 | cout << *current << " "; 26 | cout << endl; 27 | } 28 | void Test1() 29 | { 30 | int data1[10] = {1,2,3,4,5,6,7,8,9,10}; 31 | int data2[10] = {10,9,8,7,6,5,4,3,2,1}; 32 | int data3[10] = {1,1,1,1,1,5,5,5,5,5}; 33 | int data4[1] = {2}; 34 | int compareData1[10] = {1,2,3,4,5,6,7,8,9,10}; 35 | int compareData2[10] = {10,9,8,7,6,5,4,3,2,1}; 36 | int compareData3[10] = {1,1,1,1,1,5,5,5,5,5}; 37 | int compareData4[1] = {2}; 38 | 39 | countingSort(begin(data1), end(data1),10); 40 | sort(begin(compareData1), end(compareData1)); 41 | 42 | countingSort(begin(data2), end(data2),10); 43 | sort(begin(compareData2), end(compareData2)); 44 | 45 | countingSort(begin(data3), end(data3),5); 46 | sort(begin(compareData3), end(compareData3)); 47 | 48 | countingSort(begin(data4), end(data4),2); 49 | sort(begin(compareData4), end(compareData4)); 50 | 51 | // 输出排序后的数组 52 | cout << "****************对升序数组进行测试*********************\n"; 53 | cout << "countingSort排序结果:\n"; 54 | print(begin(data1), end(data1)); 55 | cout << "sort排序结果:\n"; 56 | print(begin(compareData1), end(compareData1)); 57 | 58 | cout << "****************对降序数组进行测试*********************\n"; 59 | cout << "countingSort排序结果:\n"; 60 | print(begin(data2), end(data2)); 61 | cout << "函数库sort排序结果:\n"; 62 | print(begin(compareData2), end(compareData2)); 63 | 64 | cout << "****************对有重复数字进行测试*******************\n"; 65 | cout << "countingSort排序结果:\n"; 66 | print(begin(data3), end(data3)); 67 | cout << "函数库sort排序结果:\n"; 68 | print(begin(compareData3), end(compareData3)); 69 | 70 | cout << "****************单个数组元素的测试*********************\n"; 71 | cout << "countingSort排序结果:\n"; 72 | print(begin(data4), end(data4)); 73 | cout << "函数库sort排序结果:\n"; 74 | print(begin(compareData4), end(compareData4)); 75 | } 76 | 77 | void Test2() 78 | { 79 | cout << "***********测试计数排序算法只使用于整数排序************\n"; 80 | double data1[10] = {2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0}; 81 | double compareData1[10] = {2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0}; 82 | 83 | // 这句话在编译的时候就不会通过,因为不能通过static_assert断言测试. 84 | //countingSort(begin(data1), end(data1), 3); 85 | sort(begin(compareData1), end(compareData1)); 86 | // 输出排序后的数组 87 | cout << "函数库sort排序的结果:\n"; 88 | print(begin(compareData1), end(compareData1)); 89 | } 90 | 91 | void Test3() 92 | { 93 | vector data1 = {1,2,3,4,5,6,7,8,9,10}; 94 | vector data2 = {10,9,8,7,6,5,4,3,2,1}; 95 | vector data3 = {1,1,1,1,1,5,5,5,5,5}; 96 | vector data4 = {2}; 97 | 98 | vector compareData1(data1.begin(), data1.end()); 99 | vector compareData2(data2.begin(), data2.end()); 100 | vector compareData3(data3.begin(), data3.end()); 101 | vector compareData4(data4.begin(), data4.end()); 102 | 103 | countingSort(data1.begin(), data1.end(), 10); 104 | sort(compareData1.begin(), compareData1.end()); 105 | 106 | countingSort(data2.begin(), data2.end(), 10); 107 | sort(compareData2.begin(), compareData2.end()); 108 | 109 | countingSort(data3.begin(), data3.end(), 5); 110 | sort(compareData3.begin(), compareData3.end()); 111 | 112 | countingSort(data4.begin(), data4.end(), 2); 113 | sort(compareData4.begin(), compareData4.end()); 114 | 115 | // 输出排序结果 116 | cout << "****************对升序数组进行测试*********************\n"; 117 | cout << "countingSort排序结果:\n"; 118 | print(data1.begin(), data1.end()); 119 | cout << "函数库sort排序结果:\n"; 120 | print(compareData1.begin(), compareData1.end()); 121 | 122 | cout << "****************对降序数组进行测试*********************\n"; 123 | cout << "countingSort排序结果:\n"; 124 | print(data2.begin(), data2.end()); 125 | cout << "函数库sort排序结果:\n"; 126 | print(compareData2.begin(), compareData2.end()); 127 | 128 | cout << "****************对有重复数字进行测试*******************\n"; 129 | cout << "countingSort排序结果:\n"; 130 | print(data3.begin(), data3.end()); 131 | cout << "函数库sort排序结果:\n"; 132 | print(compareData3.begin(), compareData3.end()); 133 | 134 | cout << "****************单个数组元素的测试*********************\n"; 135 | cout << "countingSort排序结果:\n"; 136 | print(data4.begin(), data4.end()); 137 | cout << "函数库sort排序结果:\n"; 138 | print(compareData4.begin(), compareData4.end()); 139 | } 140 | 141 | int main() 142 | { 143 | cout << "******************对C数组升序排列测试******************\n"; 144 | Test1(); 145 | cout << "***************测试计数排序只能用于整数排序************\n"; 146 | Test2(); 147 | 148 | cout << "******************对vector数组升序排列测试*************\n"; 149 | Test3(); 150 | 151 | return 0; 152 | } 153 | -------------------------------------------------------------------------------- /sort_algorithm/heap_sort/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: heapSort.h heapSort_test.cpp 8 | $(c++) $(VERSION) -o Test heapSort_test.cpp 9 | -------------------------------------------------------------------------------- /sort_algorithm/heap_sort/heapSort.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: heapSort.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月07日 星期三 12时39分23秒 6 | ************************************************************************/ 7 | 8 | #ifndef _HEAPSORT_H 9 | #define _HEAPSORT_H 10 | 11 | #include 12 | #include 13 | #include 14 | // HeapSort: 用于堆排序的堆, 算法导论 6.1~6.4 15 | /* 16 | * 堆排序的算法思想: 假设对数组A[p,...,r]排序 17 | * --首先对数组建成一个最大堆.然后第一个元素就是堆中的最大元素. 18 | * --将第一个元素与最后一个元素交换,同时堆的规模缩减1(对剩下的元素重新 19 | * --建立一个新堆),再将堆维持为最大堆的性质.不断循环最后得到一个排序好 20 | * --的序列. 21 | * 22 | * 算法性能: O(NlogN), 原址排序; 23 | * 在算法导论 8.1中证明了: (定理8.1)在最坏的情况下任何比较排序算法都需要做\omega(NlogN)次比较. 24 | * 25 | * 堆排序和归并排序都是渐进最优的比较排序算法. 26 | * 27 | */ 28 | template::value_type>> 29 | class HeapSort 30 | { 31 | public: 32 | HeapSort(): from(0), size(0) { } 33 | HeapSort(Iterator begin, std::size_t num): from(begin), size(num) { } 34 | HeapSort(const HeapSort &hs): from(hs.from), size(hs.size) { } // 拷贝构造函数 35 | HeapSort& operator= (const HeapSort &hs) 36 | { 37 | from = hs.from; 38 | size = hs.size; 39 | 40 | return *this; 41 | } 42 | ~HeapSort() = default; // 析构函数 43 | // operator() 堆排序算法启动. 44 | /* 45 | * \parameter begin: 待排序序列的起始迭代器(也可以是指向数组中某元素的指针); 46 | * \parameter end: 待排序序列的终止迭代器(也可以是指向数组中某元素的指针); 47 | * \parameter compare: 一个可调用对象,可用于两个对象的小于比较,默认std::less; 48 | * \return void. 49 | * 50 | */ 51 | void operator() (const Iterator begin, const Iterator end, CompareType compare = CompareType()) 52 | { 53 | from = begin; 54 | size = std::distance(begin, end); 55 | buildMaxHeap(compare); // 建立最大堆 56 | while (size > 0){ 57 | std::swap(*from, *(from + size - 1)); 58 | --size; 59 | heapify(0, compare); 60 | } 61 | } 62 | 63 | private: 64 | // 数据结构 65 | Iterator from; // 堆根节点的位置 66 | std::size_t size; // 堆大小 67 | 68 | // 私有成员函数 69 | // parentIndex: 返回一个节点父节点的位置. 70 | /* 71 | * \parameter elementIndex: 子节点位置; 72 | * \parameter valid: bool值,用于返回,指示父节点是否有效; 73 | * \return 父节点的位置(std::size_t). 74 | * 75 | * --根据最大堆的性质,一个子节点elementIndex的父节点的位置为(elementIndex-1)/2 76 | * --超出堆大小的节点,其父节点无效. 77 | * 78 | */ 79 | std::size_t parentIndex(std::size_t elementIndex, bool &valid) 80 | { 81 | if (elementIndex >= size){ 82 | valid = false; // 无效结果 83 | return 0; 84 | } 85 | valid = true; // 有效结果 86 | if (elementIndex == 0) 87 | return 0; // 根节点的父节点就是自己 88 | else 89 | return (elementIndex - 1) / 2; 90 | } 91 | 92 | // lchildIndex: 返回一个节点的左子节点位置. 93 | /* ! 94 | * \parameter elementIndex: 节点位置; 95 | * \parameter valid: bool值,用于返回指示子节点是否有效; 96 | * \return 左子节点的位置(std::size_t) 97 | * 98 | * --根据最大堆的性质,一个节点elementIndexde左子节点的位置为:(elementIndexde*2+1) 99 | * --当最大堆大小为0,1时,它没有左子节点,左子节点无效 100 | * --当左子节点超过堆大小时, 无效 101 | * 102 | */ 103 | std::size_t lchildIndex(std::size_t elementIndex, bool &valid) 104 | { 105 | if (size < 2){ 106 | valid = false; // 数组元素太少无效结果 107 | return 0; 108 | } 109 | if (elementIndex > (size - 2) / 2){ 110 | valid = false; // 超出范围,无效 111 | return 0; 112 | } 113 | valid = true; 114 | return (elementIndex * 2 + 1); 115 | } 116 | 117 | // rchildIndex: 返回一个节点右节点的位置. 118 | /* ! 119 | * \parameter elementIndex: 节点位置; 120 | * \parameter valid: bool值, 用于返回指示子节点是否有效; 121 | * \return 右节点的位置(std::size_t) 122 | * 123 | * --根据最大堆的性质,一个节点elementIndex右节点的位置为:(elementIndexde*2+2) 124 | * --当最大堆大小超过0,1时,它没有右节点,右节点无效 125 | * --当右节点超过堆大小时,无效. 126 | * 127 | */ 128 | std::size_t rchildIndex(std::size_t elementIndex, bool &vaild) 129 | { 130 | if (size < 3){ 131 | vaild = false; // 数组元素太少,无效结果 132 | return 0; 133 | } 134 | if (elementIndex > (size - 3) / 2){ 135 | vaild = false; // 超出范围,无效结果 136 | return 0; 137 | } 138 | vaild = true; 139 | return (elementIndex * 2 + 2); 140 | } 141 | 142 | // heapify: 维护堆的性质(最大堆) 143 | /* 144 | * \parameter elementIndex: 要维护以该节点为根节点子堆的性质; 145 | * \parameter compare: 一个可调用对象,用于两个对象的小于比较,默认为std::less; 146 | * \return void 147 | * 148 | * 算法思想: 首先调用比较该节点与左右孩子节点的最大值.如果最大值为节点本身那么就 149 | * 维持了最大堆的性质,返回; 如果最大值不是它本身,那么必然是左,右孩子节点之一,将该 150 | * 最大节点(假设为左孩子节点)交换到根节点,然后以左孩子节点递归调用heapify操作. 151 | * 152 | * 算法复杂度: O(logN), 对于一个树高为h的节点来说,时间复杂度为O(h). 153 | * 原址操作. 154 | * 155 | */ 156 | void heapify(std::size_t elementIndex, CompareType compare = CompareType()) 157 | { 158 | if (elementIndex >= size) 159 | return; 160 | auto maxIndex = elementIndex; 161 | bool left_valid = true; 162 | bool right_valid = true; 163 | auto leftIndex = lchildIndex(elementIndex, left_valid); // 给出左孩子节点的位置 164 | auto rightIndex = rchildIndex(elementIndex, right_valid); // 给出右孩子节点的位置 165 | 166 | // 如果左孩子节点存在 167 | if (left_valid){ 168 | if (compare(*(from + maxIndex), *(from + leftIndex))) 169 | maxIndex = leftIndex; 170 | } 171 | 172 | // 如果右孩子节点存在 173 | if (right_valid){ 174 | if (compare(*(from + maxIndex), *(from + rightIndex))) 175 | maxIndex = rightIndex; 176 | } 177 | 178 | // 如果最大节点位置不是本身 179 | if (maxIndex != elementIndex){ 180 | std::swap(*(from + elementIndex), *(from + maxIndex)); 181 | heapify(maxIndex, compare); // 递归调用 182 | } 183 | } 184 | 185 | // buildMaxHeap: 建堆 186 | /* 187 | * \parameter compare: 一个可调用的对象,可用于两个对象的小于比较,默认为std::less; 188 | * \return void. 189 | * 190 | * 算法性能: 时间复杂度为: O(NlogN). 191 | * --原地操作. 192 | * 算法思想: 从后一半元素依次向前调用heapify. 子数组A[n/2+1,...,n]的元素都是树的叶节点. 193 | * 194 | */ 195 | void buildMaxHeap(CompareType compare = CompareType()) 196 | { 197 | if (size <= 1) 198 | return; 199 | int index = (size - 1) / 2; 200 | while (index >= 0){ 201 | heapify(index, compare); 202 | --index; 203 | } 204 | } 205 | }; 206 | #endif 207 | -------------------------------------------------------------------------------- /sort_algorithm/insert_sort/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: insertSortTest 6 | 7 | insertSortTest: insertSortTest.cpp insertSort.h 8 | $(c++) $(VERSION) -o insertSortTest insertSortTest.cpp 9 | -------------------------------------------------------------------------------- /sort_algorithm/insert_sort/insertSort.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: insertSort.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月06日 星期二 11时05分43秒 6 | ************************************************************************/ 7 | 8 | #ifndef _INSERTSORT_H 9 | #define _INSERTSORT_H 10 | // insertSort.h 算法导论第二章 2.1; 11 | /* \parameter begin: 待排序序列的起始迭代器(也可以是指向数组中某元素的指针); 12 | * \parameter end: 待排序序列的终止迭代器(也可以是指向数组中某元素的指针); 13 | * \parameter compare: 一个可调用对象,可用于比较两个对象的小于比较,默认为std::less; 14 | * \return void; 15 | * 16 | * 算法性能O(N^2). 17 | * 原址排序. 18 | * 算法具体思想: 插入排序对于少量元素的排序,它是一个有效的算法. 假设数组A[1,...,n]排序: 19 | * 设当前排序的元素是A[i],则A[1,...i-1]是排序好的,A[i]在A[1,...,i-1]中找到它的位置,然后插入其中. 20 | */ 21 | #include 22 | template::value_type>> 23 | void insertSort(const Iterator begin, const Iterator end, CompareType compare=CompareType()) 24 | { 25 | // typedef typename std::iterator_traits::value_type T; // 迭代器指向对象的值的类型 26 | auto size = std::distance(begin, end); 27 | if (size <= 1) 28 | return; 29 | auto current = begin; 30 | while (++current != end){ 31 | auto smallNext = current; // 指向比*current小的元素中 最大的那一个a 32 | auto key = *current; 33 | while (smallNext != begin && compare(key, *(smallNext-1))){ 34 | *smallNext = *(smallNext - 1); // 后移 35 | --smallNext; 36 | } 37 | *smallNext = key; 38 | } 39 | } 40 | #endif 41 | -------------------------------------------------------------------------------- /sort_algorithm/merge_sort/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: mergeSort.h mergeSort_test.cpp 8 | $(c++) $(VERSION) -o Test mergeSort_test.cpp 9 | -------------------------------------------------------------------------------- /sort_algorithm/merge_sort/mergeSort.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: mergeSort.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月07日 星期三 08时42分15秒 6 | ************************************************************************/ 7 | 8 | #ifndef _MERGESORT_H 9 | #define _MERGESORT_H 10 | 11 | #include 12 | #include 13 | #include 14 | // merge 算法导论 2.3.1 15 | /*! 16 | *\parameter begin: begin...middle之间为已排好序列; 17 | *\parameter end: middle...end之间为已排好序列; 18 | *\parameter middle: begin...middle; middle...end都为已排好序列; 19 | *\parameter compare: 一个可调用对象,可用于比较两个对象的小于比较,默认为std::less; 20 | *\retrun void; 21 | * 22 | * 算法性能: O(N); 23 | * 归并思想: 假设对数组A[p...q...r]归并: 24 | * --拷贝: 将数组A[p...q]拷贝到数组L; 将数组A[q+1...r]拷贝到数组R, 25 | * --归并: 从左到右依次取L,R中较小的元素,存放到A中. 26 | * 非原址排序,归并需要额外的空间 O(N). 27 | */ 28 | template::value_type>> 29 | void merge(const Iterator begin, const Iterator end, const Iterator middle, CompareType compare = CompareType()) 30 | { 31 | typedef typename std::iterator_traits::value_type T; // 迭代器指向对象的类型 32 | if (std::distance(begin, middle) <= 0 || std::distance(middle, end) <= 0) return; 33 | std::vector result(begin, end); // 暂存结果 34 | auto current = result.begin(); 35 | auto left_current = begin; // 左侧序列的当前比较位置 36 | auto right_current = middle; // 右侧序列的当前比较位置 37 | while (left_current != middle && right_current != end){ 38 | if (compare(*left_current, *right_current)) 39 | *current++ = *left_current++; 40 | else 41 | *current++ = *right_current++; 42 | } 43 | // 当左侧被搬空的时候 44 | if (left_current == middle && right_current != end) 45 | std::copy(right_current, end, current); 46 | // 当右侧被搬空的时候 47 | if (right_current == end && left_current != middle) 48 | std::copy(left_current, middle, current); 49 | // 把排序结果返回原来的序列 50 | std::copy(result.begin(), result.end(), begin); 51 | } 52 | 53 | // mergeSort 算法导论2.3.1 54 | /*! 55 | * \parameter begin: 待排序序列的起始迭代器(也可以是指向数组某元素的指针) 56 | * \parameter end: 待排序序列的终止迭代器(也可以是指向数组某元素的指针) 57 | * \parameter compare: 一个可调用对象, 可用于比较两个对象小于, 默认std::less 58 | * \return void 59 | * 60 | * 算法性能: O(NlogN); 61 | * -- 在归并阶段的算法性能: O(logN); 62 | * 63 | * 算法思想: 假设对数组A[p,...,r]排序: 64 | * -- 分解: 将数组A[p,...,r]平均划分为两个数组A[p,...,q-1], A[q,...,r],依次划分直到每个子数组只有一个元素; 65 | * -- 归并: 对排好序的两个数组A[p,...,q-1], A[q,...,r]进行合并; 66 | * 整个算法需要额外的空间 O(N); 67 | */ 68 | template::value_type>> 69 | void mergeSort(const Iterator begin, const Iterator end, CompareType compare = CompareType()) 70 | { 71 | auto size = std::distance(begin, end); 72 | if (size > 1){ 73 | Iterator middle = begin + size / 2; 74 | mergeSort(begin, middle, compare); 75 | mergeSort(middle, end, compare); 76 | merge(begin, end, middle, compare); 77 | } 78 | } 79 | #endif 80 | -------------------------------------------------------------------------------- /sort_algorithm/merge_sort/mergeSort_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: mergeSort_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月07日 星期三 10时13分27秒 6 | ************************************************************************/ 7 | #include 8 | using std::cout; using std::endl; 9 | #include 10 | using std::begin; using std::end; 11 | #include 12 | using std::vector; 13 | #include 14 | using std::sort; 15 | #include "mergeSort.h" 16 | 17 | // 数组输出函数 18 | template 19 | void print(const Iterator begin, const Iterator end) 20 | { 21 | for (auto current = begin; current != end; ++current) 22 | cout << *current << " "; 23 | cout << endl; 24 | } 25 | // 降序 26 | bool compareInt(int num1, int num2) 27 | { 28 | return num1 > num2; 29 | } 30 | 31 | bool compareDouble(double num1, double num2) 32 | { 33 | return num1 > num2; 34 | } 35 | 36 | void Test1() 37 | { 38 | int data1[10] = {1,2,3,4,5,6,7,8,9,10}; 39 | int data2[10] = {10,9,8,7,6,5,4,3,2,1}; 40 | int data3[10] = {1,1,1,1,1,5,5,5,5,5}; 41 | int data4[1] = {2}; 42 | int compareData1[10] = {1,2,3,4,5,6,7,8,9,10}; 43 | int compareData2[10] = {10,9,8,7,6,5,4,3,2,1}; 44 | int compareData3[10] = {1,1,1,1,1,5,5,5,5,5}; 45 | int compareData4[1] = {2}; 46 | 47 | mergeSort(begin(data1), end(data1)); 48 | sort(begin(compareData1), end(compareData1)); 49 | 50 | mergeSort(begin(data2), end(data2)); 51 | sort(begin(compareData2), end(compareData2)); 52 | 53 | mergeSort(begin(data3), end(data3)); 54 | sort(begin(compareData3), end(compareData3)); 55 | 56 | mergeSort(begin(data4), end(data4)); 57 | sort(begin(compareData4), end(compareData4)); 58 | 59 | // 输出排序后的数组 60 | cout << "****************对升序数组进行测试*********************\n"; 61 | cout << "insertSort排序结果:\n"; 62 | print(begin(data1), end(data1)); 63 | cout << "sort排序结果:\n"; 64 | print(begin(compareData1), end(compareData1)); 65 | 66 | cout << "****************对降序数组进行测试*********************\n"; 67 | cout << "insertSort排序结果:\n"; 68 | print(begin(data2), end(data2)); 69 | cout << "函数库sort排序结果:\n"; 70 | print(begin(compareData2), end(compareData2)); 71 | 72 | cout << "****************对有重复数字进行测试*******************\n"; 73 | cout << "insertSort排序结果:\n"; 74 | print(begin(data3), end(data3)); 75 | cout << "函数库sort排序结果:\n"; 76 | print(begin(compareData3), end(compareData3)); 77 | 78 | cout << "****************单个数组元素的测试*********************\n"; 79 | cout << "insertSort排序结果:\n"; 80 | print(begin(data4), end(data4)); 81 | cout << "函数库sort排序结果:\n"; 82 | print(begin(compareData4), end(compareData4)); 83 | } 84 | 85 | void Test2() 86 | { 87 | vector data1{1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2.0}; 88 | vector compareData1(data1.begin(), data1.end()); 89 | vector data2{2.0,1.9,1.8,1.7,1.6,1.5,1.4,1.3,1.2,1.1}; 90 | vector compareData2(data2.begin(), data2.end()); 91 | vector data3{1.1,1.1,1.1,1.1,1.1,2.2,2.2,2.2,2.2,2.2}; 92 | vector compareData3(data3.begin(), data3.end()); 93 | vector data4{1.1}; 94 | vector compareData4{1.1}; 95 | 96 | mergeSort(data1.begin(), data1.end()); 97 | sort(compareData1.begin(), compareData1.end()); 98 | 99 | mergeSort(data2.begin(), data2.end()); 100 | sort(compareData2.begin(), compareData2.end()); 101 | 102 | mergeSort(data3.begin(), data3.end()); 103 | sort(compareData3.begin(), compareData3.end()); 104 | 105 | mergeSort(data4.begin(), data4.end()); 106 | sort(compareData4.begin(), compareData4.end()); 107 | 108 | cout << "****************对升序数组进行测试*********************\n"; 109 | cout << "insertSort排序结果:\n"; 110 | print(data1.begin(), data1.end()); 111 | cout << "函数库sort排序结果:\n"; 112 | print(compareData1.begin(), compareData1.end()); 113 | 114 | cout << "****************对降序数组进行测试*********************\n"; 115 | cout << "insertSort排序结果:\n"; 116 | print(data2.begin(), data2.end()); 117 | cout << "函数库sort排序结果:\n"; 118 | print(compareData2.begin(), compareData2.end()); 119 | 120 | cout << "****************对有重复数字进行测试*******************\n"; 121 | cout << "insertSort排序结果:\n"; 122 | print(data3.begin(), data3.end()); 123 | cout << "函数库sort排序结果:\n"; 124 | print(compareData3.begin(), compareData3.end()); 125 | 126 | cout << "****************对单个数字进行测试*********************\n"; 127 | cout << "insertSort排序结果\n"; 128 | print(data4.begin(), data4.end()); 129 | cout << "函数库sort排序结果:\n"; 130 | print(compareData4.begin(), compareData4.end()); 131 | } 132 | 133 | void Test3() 134 | { 135 | int data1[10] = {1,2,3,4,5,6,7,8,9,10}; 136 | int data2[10] = {10,9,8,7,6,5,4,3,2,1}; 137 | int data3[10] = {1,1,1,1,1,5,5,5,5,5}; 138 | int data4[1] = {2}; 139 | int compareData1[10] = {1,2,3,4,5,6,7,8,9,10}; 140 | int compareData2[10] = {10,9,8,7,6,5,4,3,2,1}; 141 | int compareData3[10] = {1,1,1,1,1,5,5,5,5,5}; 142 | int compareData4[1] = {2}; 143 | 144 | mergeSort(begin(data1), end(data1), compareInt); 145 | sort(begin(compareData1), end(compareData1), compareInt); 146 | 147 | mergeSort(begin(data2), end(data2), compareInt); 148 | sort(begin(compareData2), end(compareData2), compareInt); 149 | 150 | mergeSort(begin(data3), end(data3), compareInt); 151 | sort(begin(compareData3), end(compareData3), compareInt); 152 | 153 | mergeSort(begin(data4), end(data4), compareInt); 154 | sort(begin(compareData4), end(compareData4), compareInt); 155 | 156 | // 输出排序后的数组 157 | cout << "****************对升序数组进行测试*********************\n"; 158 | cout << "insertSort排序结果:\n"; 159 | print(begin(data1), end(data1)); 160 | cout << "sort排序结果:\n"; 161 | print(begin(compareData1), end(compareData1)); 162 | 163 | cout << "****************对降序数组进行测试*********************\n"; 164 | cout << "insertSort排序结果:\n"; 165 | print(begin(data2), end(data2)); 166 | cout << "函数库sort排序结果:\n"; 167 | print(begin(compareData2), end(compareData2)); 168 | 169 | cout << "****************对有重复数字进行测试*******************\n"; 170 | cout << "insertSort排序结果:\n"; 171 | print(begin(data3), end(data3)); 172 | cout << "函数库sort排序结果:\n"; 173 | print(begin(compareData3), end(compareData3)); 174 | 175 | cout << "****************单个数组元素的测试*********************\n"; 176 | cout << "insertSort排序结果:\n"; 177 | print(begin(data4), end(data4)); 178 | cout << "函数库sort排序结果:\n"; 179 | print(begin(compareData4), end(compareData4)); 180 | } 181 | 182 | void Test4() 183 | { 184 | vector data1{1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2.0}; 185 | vector compareData1(data1.begin(), data1.end()); 186 | vector data2{2.0,1.9,1.8,1.7,1.6,1.5,1.4,1.3,1.2,1.1}; 187 | vector compareData2(data2.begin(), data2.end()); 188 | vector data3{1.1,1.1,1.1,1.1,1.1,2.2,2.2,2.2,2.2,2.2}; 189 | vector compareData3(data3.begin(), data3.end()); 190 | vector data4{1.1}; 191 | vector compareData4{1.1}; 192 | 193 | mergeSort(data1.begin(), data1.end(), compareDouble); 194 | sort(compareData1.begin(), compareData1.end(), compareDouble); 195 | 196 | mergeSort(data2.begin(), data2.end(), compareDouble); 197 | sort(compareData2.begin(), compareData2.end(), compareDouble); 198 | 199 | mergeSort(data3.begin(), data3.end(), compareDouble); 200 | sort(compareData3.begin(), compareData3.end(), compareDouble); 201 | 202 | mergeSort(data4.begin(), data4.end(), compareDouble); 203 | sort(compareData4.begin(), compareData4.end(), compareDouble); 204 | 205 | cout << "****************对升序数组进行测试*********************\n"; 206 | cout << "insertSort排序结果:\n"; 207 | print(data1.begin(), data1.end()); 208 | cout << "函数库sort排序结果:\n"; 209 | print(compareData1.begin(), compareData1.end()); 210 | 211 | cout << "****************对降序数组进行测试*********************\n"; 212 | cout << "insertSort排序结果:\n"; 213 | print(data2.begin(), data2.end()); 214 | cout << "函数库sort排序结果:\n"; 215 | print(compareData2.begin(), compareData2.end()); 216 | 217 | cout << "****************对有重复数字进行测试*******************\n"; 218 | cout << "insertSort排序结果:\n"; 219 | print(data3.begin(), data3.end()); 220 | cout << "函数库sort排序结果:\n"; 221 | print(compareData3.begin(), compareData3.end()); 222 | 223 | cout << "****************对单个数字进行测试*********************\n"; 224 | cout << "insertSort排序结果\n"; 225 | print(data4.begin(), data4.end()); 226 | cout << "函数库sort排序结果:\n"; 227 | print(compareData4.begin(), compareData4.end()); 228 | } 229 | 230 | int main() 231 | { 232 | cout << "****************对C数组升序排列测试********************\n"; 233 | Test1(); 234 | 235 | cout << "****************对vector数组升序排列测试***************\n"; 236 | Test2(); 237 | 238 | cout << "****************对C数组降序排列测试********************\n"; 239 | Test3(); 240 | 241 | cout << "****************对vector数组降序排列测试***************\n"; 242 | Test4(); 243 | 244 | return 0; 245 | } 246 | -------------------------------------------------------------------------------- /sort_algorithm/quick_sort/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: quickSort.h quickSort_test.cpp 8 | $(c++) $(VERSION) -o Test quickSort_test.cpp 9 | -------------------------------------------------------------------------------- /sort_algorithm/quick_sort/quickSort.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: quickSort.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月08日 星期四 20时49分32秒 6 | ************************************************************************/ 7 | 8 | #ifndef _QUICKSORT_H 9 | #define _QUICKSORT_H 10 | 11 | #include 12 | #include 13 | #include 14 | // partition: 算法导论第7章 快速排序算法中的划分算法. 15 | /* 16 | * \parameter begin: 待划分序列的起始迭代器(也可以是指向数组中某元素的指针); 17 | * \parameter end: 待划分的终止迭代器(也可以是指向数组中某元素的指针); 18 | * \parameter partitioned_iter: 指定划分元素的对应的迭代器 (也可以是指向数组中某元素的指针); 19 | * \parameter compare: 一个可调用对象,可用于比较两个对象的小于(默认为std::less); 20 | * \return 返回主元素的位置. 21 | * 22 | * 算法基本思想: 假设对数组A[p,...,r]划分: 23 | * --划分的目的是找到一个主元假定q,使其满足: 24 | * --A[p,...,q-1]的所有元素都小于A[q]; 25 | * --A[q+1,...,r]的所有元素都大于A[q]. 26 | * --假定划分主元为A[r]; 27 | * --循环不等式: 令current = begin, i = begin; 28 | * --若A[current] < A[r], 则交换A[i]和A[current], i右移, current右移 29 | * --若A[current] >= A[r], current右移.(进行下一个元素的判定). 30 | * 31 | * 时间复杂度: O(N). 32 | * 算法特性: 原址排序. 33 | * 34 | */ 35 | template::value_type>> 36 | Iterator partition(const Iterator begin, const Iterator end, 37 | const Iterator partitioned_iter, CompareType compare = CompareType()) 38 | { 39 | auto size = std::distance(begin, end); 40 | if (size <= 0) 41 | throw std::invalid_argument("decreate_key error: 输入序列的范围有误"); 42 | auto x = *partitioned_iter; 43 | auto i = begin; 44 | std::swap(*partitioned_iter, *(end - 1)); 45 | for (auto current = begin; current != end; ++current){ 46 | if (compare(*current, x)) 47 | std::swap(*i++, *current); 48 | } 49 | std::swap(*i, *(end - 1)); 50 | return i; 51 | } 52 | // quickSort: 快速排序算法 算法导论第七章 53 | /* 54 | * \parameter begin: 待划分序列的起始迭代器(也可以是指向数组中某元素的指针); 55 | * \parameter end: 待划分的终止迭代器(也可以是指向数组中某元素的指针); 56 | * \parameter compare: 一个可调用对象,可用于比较两个对象的小于(默认为std::less); 57 | * \return void. 58 | * 59 | * 算法基本思想: 60 | * --分解: 数组A[p,...,r]被划分为两个(可能为空)子数组A[p,...,q-1]和A[q+1,...,r], 61 | * 使得A[p,...,q-1]中的每一个元素都小于等于A[q],而A[q]也小于等于A[q+1,...,r]中的 62 | * 每个元素; 63 | * --解决: 通过递归调用快速排序,对子数组A[p,...,q-1]和A[q+1,...,r]进行排序; 64 | * --合并: 由于子数组都是原址排序,所以不需要合并操作: 数组A[p,...,r]已经有序. 65 | * 66 | * 算法性能: 最坏情况下时间复杂度为O(N^2), 在元素互异的情况下,期望时间复杂度为O(NlogN). 67 | * 68 | */ 69 | template::value_type>> 70 | void quickSort(const Iterator begin, const Iterator end, CompareType compare = CompareType()) 71 | { 72 | auto size = std::distance(begin, end); 73 | if (size <= 1) 74 | return; 75 | auto partitioned_iter = partition(begin, end, end - 1, compare); 76 | quickSort(begin, partitioned_iter, compare); 77 | quickSort(partitioned_iter + 1, end, compare); 78 | } 79 | #endif 80 | -------------------------------------------------------------------------------- /sort_algorithm/radix_sort/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: radixSort.h radixSort_test.cpp 8 | $(c++) $(VERSION) -o Test radixSort_test.cpp 9 | -------------------------------------------------------------------------------- /sort_algorithm/radix_sort/radixSort.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: radixSort.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月10日 星期六 15时25分34秒 6 | ************************************************************************/ 7 | 8 | #ifndef _RADIXSORT_H 9 | #define _RADIXSORT_H 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | // digi_on_N: 获取正整数指定位数上的数字. 16 | /* 17 | * \parameter num: 待抽取数字的正整数; 18 | * \parameter n: 指定的位数(0表示个位, 1表示十位, ...依次类推); 19 | * \return 指定正整数指定位数上的数字. 20 | * 21 | * 注意:这里的T必须为某个整数类型, 由static_assert(std::is_integral::value, "...")确保; 22 | * 23 | */ 24 | template 25 | T digi_on_N(T num, std::size_t n) 26 | { 27 | // 必须针对整数类型才能取指定位数上的数字 28 | static_assert(std::is_integral::value, "T must be integer!"); 29 | return num / static_cast(std::pow(10,n)) % 10; 30 | } 31 | // countingSort: 计数排序 算法导论8.2 32 | /* 33 | * \parameter begin: 待排序序列的起始迭代器(也可以是指向数组中某元素的指针); 34 | * \parameter end: 待排序序列的终止迭代器(也可以是指向数组中某元素的指针); 35 | * \parameter maxVal: 待排序序列中的最大值; 36 | * \parameter n: 指定按照位数排序(0表示个位, 1表示十位, ...依次类推); 37 | * \return void. 38 | * 39 | * 算法性能: 算法的时间复杂度为O(N); 40 | * 算法特点: 保证了稳定性, 稳定性在计数排序算法中是非常重要的.稳定性就是在序列中相同的数字,经过 41 | * 排序算法以后依旧按照原先出现的次序出现. 42 | * 算法基本思想: 对每一个输入元素x, 确定小于x的元素个数. 利用这一信息,就可以直接把x放到它在输出数组 43 | * 中的位置上了. 44 | * 此算法并不属于原址排序算法, 同时也不属于比较排序算法. 45 | */ 46 | template 47 | void countingSort(const Iterator begin, const Iterator end, 48 | const typename std::iterator_traits::value_type &maxVal, std::size_t n) 49 | { 50 | // 迭代器指向元素的类型 51 | typedef typename std::iterator_traits::value_type T; 52 | auto size = std::distance(begin, end); 53 | std::vector countingArray(maxVal + 1, 0); 54 | // 等于i元素的个数 55 | for (auto current = begin; current != end; ++current) 56 | countingArray[digi_on_N(*current, n)] += 1; 57 | // 记住比该数小的元素共有多少个 58 | for (decltype(countingArray.size()) i = 1; i != countingArray.size(); ++i) 59 | countingArray[i] += countingArray[i - 1]; 60 | // 把元素放回到正确的位置上 61 | std::vector tempResult(size, 0); 62 | for (auto current = end - 1; current != begin - 1; --current){ 63 | tempResult[countingArray[digi_on_N(*current, n)] - 1] = *current; 64 | countingArray[digi_on_N(*current, n)] -= 1; 65 | } 66 | // 把排序好的元素返回到数组中 67 | std::copy(tempResult.begin(), tempResult.end(), begin); 68 | } 69 | // radixSort: 基数排序 算法导论8.3. 70 | /* 71 | * \parameter begin: 待排序序列的起始迭代器(也可以是指向数组中某元素的指针); 72 | * \parameter end: 待排序序列的终止迭代器(也可以是指向数组中某元素的指针); 73 | * \parameter radix_width: 待排序元素(必须是整数)的最大位宽, 必须非0(由assert(radix_width!=0)确保); 74 | * \return void. 75 | * 76 | * 算法性能:给定n个d位数,其中每一个数为有k个可能的值.如果基数排序算法使用的是稳定的计数排序算法那么 77 | * 算法的时间复杂度为O(d(n+k)). 78 | * 算法的基本思想: 依次对所给数字中的个位, 十位,...排序(注意,一定要使用稳定的排序算法). 79 | * 此算法不属于比较排序算法, 是否是原址排序取决于你对每一位数所使用的排序算法. 80 | * 81 | */ 82 | template 83 | void radixSort(const Iterator begin, const Iterator end, std::size_t radix_width) 84 | { 85 | // 迭代器指向元素的类型 86 | typedef typename std::iterator_traits::value_type T; 87 | assert(radix_width != 0); // 检测位数为有效位, 0属于无效位 88 | // 在编译的时候确保 (基数排序只适合对整数类型的数据进行排序) 89 | static_assert(std::is_integral::value, "sequence to be sorted must be integer!"); 90 | auto size = std::distance(begin, end); 91 | if (size <= 1) 92 | return; 93 | // 对每一位都使用计数排序方法进行排序 94 | for (int i = 0; i <= radix_width; ++i) 95 | countingSort(begin, end, 9, i); 96 | } 97 | #endif 98 | -------------------------------------------------------------------------------- /sort_algorithm/radix_sort/radixSort_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: radixSort_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月10日 星期六 17时16分38秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | #include 11 | using std::cout; using std::endl; 12 | #include 13 | using std::begin; using std::end; 14 | #include 15 | using std::vector; 16 | #include 17 | using std::sort; 18 | #include "radixSort.h" 19 | 20 | // 数组输出函数 21 | template 22 | void print(const Iterator begin, const Iterator end) 23 | { 24 | for (auto current = begin; current != end; ++current) 25 | cout << *current << " "; 26 | cout << endl; 27 | } 28 | void Test1() 29 | { 30 | int data1[10] = {101, 111, 121, 131, 141, 151, 161, 171, 181, 191}; 31 | int data2[10] = {191, 181, 171, 161, 151, 141, 131, 121, 111, 101}; 32 | int data3[10] = {111, 111, 111, 111, 111, 555, 555, 555, 555, 555}; 33 | int data4[1] = {222}; 34 | int data5[7] = {329, 457, 657, 839, 436, 720, 355}; 35 | 36 | int compareData1[10] = {101, 111, 121, 131, 141, 151, 161, 171, 181, 191}; 37 | int compareData2[10] = {191, 181, 171, 161, 151, 141, 131, 121, 111, 101}; 38 | int compareData3[10] = {111, 111, 111, 111, 111, 555, 555, 555, 555, 555}; 39 | int compareData4[1] = {222}; 40 | int compareData5[7] = {329, 457, 657, 839, 436, 720, 355}; 41 | 42 | radixSort(begin(data1), end(data1),3); 43 | sort(begin(compareData1), end(compareData1)); 44 | 45 | radixSort(begin(data2), end(data2),3); 46 | sort(begin(compareData2), end(compareData2)); 47 | 48 | radixSort(begin(data3), end(data3),3); 49 | sort(begin(compareData3), end(compareData3)); 50 | 51 | radixSort(begin(data4), end(data4),3); 52 | sort(begin(compareData4), end(compareData4)); 53 | 54 | radixSort(begin(data5), end(data5), 3); 55 | sort(begin(compareData5), end(compareData5)); 56 | 57 | // 输出排序后的数组 58 | cout << "****************对升序数组进行测试*********************\n"; 59 | cout << "countingSort排序结果:\n"; 60 | print(begin(data1), end(data1)); 61 | cout << "sort排序结果:\n"; 62 | print(begin(compareData1), end(compareData1)); 63 | 64 | cout << "****************对降序数组进行测试*********************\n"; 65 | cout << "countingSort排序结果:\n"; 66 | print(begin(data2), end(data2)); 67 | cout << "函数库sort排序结果:\n"; 68 | print(begin(compareData2), end(compareData2)); 69 | 70 | cout << "****************对有重复数字进行测试*******************\n"; 71 | cout << "countingSort排序结果:\n"; 72 | print(begin(data3), end(data3)); 73 | cout << "函数库sort排序结果:\n"; 74 | print(begin(compareData3), end(compareData3)); 75 | 76 | cout << "****************单个数组元素的测试*********************\n"; 77 | cout << "countingSort排序结果:\n"; 78 | print(begin(data4), end(data4)); 79 | cout << "函数库sort排序结果:\n"; 80 | print(begin(compareData4), end(compareData4)); 81 | 82 | cout << "****************凌乱数组元素的测试**********************\n"; 83 | cout << "countingSort排序结果:\n"; 84 | print(begin(data5), end(data5)); 85 | cout << "函数库sort排序结果:\n"; 86 | print(begin(compareData5), end(compareData5)); 87 | } 88 | 89 | void Test2() 90 | { 91 | cout << "***********测试计数排序算法只使用于整数排序************\n"; 92 | double data1[10] = {101, 111, 121, 131, 141, 151, 161, 171, 181, 191}; 93 | double compareData1[10] = {101, 111, 121, 131, 141, 151, 161, 171, 181, 191}; 94 | 95 | // 这句话在编译的时候就不会通过,因为不能通过static_assert断言测试. 96 | //countingSort(begin(data1), end(data1), 3); 97 | sort(begin(compareData1), end(compareData1)); 98 | // 输出排序后的数组 99 | cout << "函数库sort排序的结果:\n"; 100 | print(begin(compareData1), end(compareData1)); 101 | } 102 | 103 | void Test3() 104 | { 105 | vector data1 = {101, 111, 121, 131, 141, 151, 161, 171, 181, 191}; 106 | vector data2 = {191, 181, 171, 161, 151, 141, 131, 121, 111, 101}; 107 | vector data3 = {111, 111, 111, 111, 111, 555, 555, 555, 555, 555}; 108 | vector data4 = {222}; 109 | vector data5 = {329, 457, 657, 839, 436, 720, 355}; 110 | 111 | vector compareData1(data1.begin(), data1.end()); 112 | vector compareData2(data2.begin(), data2.end()); 113 | vector compareData3(data3.begin(), data3.end()); 114 | vector compareData4(data4.begin(), data4.end()); 115 | vector compareData5(data5.begin(), data5.end()); 116 | 117 | radixSort(data1.begin(), data1.end(), 3); 118 | sort(compareData1.begin(), compareData1.end()); 119 | 120 | radixSort(data2.begin(), data2.end(), 3); 121 | sort(compareData2.begin(), compareData2.end()); 122 | 123 | radixSort(data3.begin(), data3.end(), 3); 124 | sort(compareData3.begin(), compareData3.end()); 125 | 126 | radixSort(data4.begin(), data4.end(), 3); 127 | sort(compareData4.begin(), compareData4.end()); 128 | 129 | radixSort(data5.begin(), data5.end(), 3); 130 | sort(compareData5.begin(), compareData5.end()); 131 | 132 | // 输出排序结果 133 | cout << "****************对升序数组进行测试*********************\n"; 134 | cout << "countingSort排序结果:\n"; 135 | print(data1.begin(), data1.end()); 136 | cout << "函数库sort排序结果:\n"; 137 | print(compareData1.begin(), compareData1.end()); 138 | 139 | cout << "****************对降序数组进行测试*********************\n"; 140 | cout << "countingSort排序结果:\n"; 141 | print(data2.begin(), data2.end()); 142 | cout << "函数库sort排序结果:\n"; 143 | print(compareData2.begin(), compareData2.end()); 144 | 145 | cout << "****************对有重复数字进行测试*******************\n"; 146 | cout << "countingSort排序结果:\n"; 147 | print(data3.begin(), data3.end()); 148 | cout << "函数库sort排序结果:\n"; 149 | print(compareData3.begin(), compareData3.end()); 150 | 151 | cout << "****************单个数组元素的测试*********************\n"; 152 | cout << "countingSort排序结果:\n"; 153 | print(data4.begin(), data4.end()); 154 | cout << "函数库sort排序结果:\n"; 155 | print(compareData4.begin(), compareData4.end()); 156 | 157 | cout << "****************对凌乱数组元素的测试*******************\n"; 158 | cout << "countingSort排序结果:\n"; 159 | print(data5.begin(), data5.end()); 160 | cout << "函数库sort排序结果:\n"; 161 | print(compareData5.begin(), compareData5.end()); 162 | } 163 | 164 | int main() 165 | { 166 | cout << "******************对C数组升序排列测试******************\n"; 167 | Test1(); 168 | cout << "***************测试计数排序只能用于整数排序************\n"; 169 | Test2(); 170 | 171 | cout << "******************对vector数组升序排列测试*************\n"; 172 | Test3(); 173 | 174 | return 0; 175 | } 176 | -------------------------------------------------------------------------------- /stack_algorithm/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: stack.h stack_test.cpp 8 | $(c++) $(VERSION) -o Test stack_test.cpp 9 | -------------------------------------------------------------------------------- /stack_algorithm/stack.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: stack.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月13日 星期二 09时47分23秒 6 | ************************************************************************/ 7 | 8 | #ifndef _STACK_H 9 | #define _STACK_H 10 | #include 11 | #include 12 | #include 13 | #include 14 | // Stack: 栈 算法导论10.1 15 | /* 16 | * 在栈中,被删除的是最近插入的元素:栈的实现是一种后进先出的数据结构 17 | * 栈需要支持的操作: 18 | * --empty(S): 检查栈是否为空; 19 | * --push(S,x): 向栈中压入一个元素; 20 | * --pop(S): 栈中弹出一个元素. 21 | */ 22 | template 23 | class Stack{ 24 | public: 25 | //*************************构造函数************************** 26 | Stack(): size(0) {data.resize(0);} 27 | explicit Stack(std::size_t reverse_size): size(0) {data.resize(reverse_size);} 28 | // 拷贝构造函数 29 | Stack(const Stack& stack) 30 | { 31 | size = stack.size; 32 | std::copy(stack.data.begin(), stack.data.begin() + stack.size, data.begin()); 33 | } 34 | // 拷贝赋值运算符 35 | Stack& operator=(const Stack& stack) 36 | { 37 | size = stack.size; 38 | std::copy(stack.data.begin(), stack.data.begin() + stack.size, data.begin()); 39 | return *this; // 返回一个此对象的引用 40 | } 41 | // 析构函数 42 | ~Stack() = default; 43 | //*************************成员函数************************** 44 | // empty: 检查栈是否为空. 45 | bool empty() 46 | { 47 | assert(size >= 0); 48 | return size; 49 | } 50 | // push: 向栈中压入一个元素. 51 | /* 52 | * \parameter element: 待压入栈中元素的指针; 53 | * \return void. 54 | * 55 | * 压入过程: 56 | * --检查element是不是一个空指针,若空指针则终止程序; 57 | * --一旦栈已满,则把栈的容量增加一倍(为防止特殊的情况,如size=0,此时将栈容量设置为栈长度一倍加2); 58 | * --将element压入栈的末尾. 59 | */ 60 | void push(std::shared_ptr element) 61 | { 62 | if (!element) return; // 参数指针为一个空指针 63 | if (size == data.size()) data.resize(size * 2 + 2); // 扩容 64 | std::size_t index = size; 65 | ++size; // 自增 66 | data[index] = element; 67 | } 68 | // pop: 栈中弹出一个元素. 69 | /* 70 | * 当栈为空的时候,弹出一个空指针. 71 | * 把栈中最头部的元素弹出. 72 | */ 73 | std::shared_ptr pop() 74 | { 75 | bool isempty = empty(); 76 | if (!isempty) return std::shared_ptr(); 77 | --size; // 自减 78 | if (size <= data.size() / 4) 79 | data.resize(size * 2 + 2); // 内存管理 80 | return data[size]; 81 | } 82 | private: 83 | //*************************数据结构************************** 84 | std::vector> data; // 栈的数据 85 | std::size_t size; // 栈的大小 86 | }; 87 | #endif 88 | -------------------------------------------------------------------------------- /stack_algorithm/stack_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: stack_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月13日 星期二 10时51分54秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include "stack.h" 11 | 12 | typedef Stack IntStack; 13 | typedef Stack DoubleStack; 14 | 15 | void intTest() 16 | { 17 | IntStack intStack(0); 18 | // 测试栈是否为空 19 | cout << "初始化后栈是否为空: " << intStack.empty() << endl; 20 | // 向栈中插入元素 21 | cout << "依次向栈中插入元素: \n"; 22 | for (int i = 0; i <= 10; ++i){ 23 | cout << i << " "; 24 | intStack.push(std::make_shared(i)); 25 | } 26 | cout << endl; 27 | // 弹出栈中所有元素后 28 | cout << "依次弹出栈中所有元素: \n"; 29 | while (intStack.empty()) 30 | cout << *intStack.pop() << " "; 31 | cout << endl; 32 | } 33 | 34 | void doubleTest() 35 | { 36 | DoubleStack doubleStack(0); 37 | // 测试栈是否为空 38 | cout << "初始化后栈是否为空: " << doubleStack.empty() << endl; 39 | // 向栈中插入元素 40 | cout << "依次向栈中插入元素: " << endl; 41 | for (int i = 0; i <= 10; ++i){ 42 | double val = i * 0.01; 43 | doubleStack.push(std::make_shared(val)); 44 | cout << val << " "; 45 | } 46 | cout << endl; 47 | cout << "依次弹出栈中元素: \n"; 48 | while (doubleStack.empty()) 49 | cout << *doubleStack.pop() << " "; 50 | cout << endl; 51 | } 52 | 53 | 54 | int main() 55 | { 56 | cout << "*******************对int型数据测试***************************\n"; 57 | intTest(); 58 | cout << "*****************对double型数据测试**************************\n"; 59 | doubleTest(); 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /subset_algorithm/merge_subset_sum/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: mergeSubsetSum.h mergeSubsetSum_test.cpp 8 | $(c++) $(VERSION) -o Test mergeSubsetSum_test.cpp 9 | -------------------------------------------------------------------------------- /subset_algorithm/merge_subset_sum/mergeSubsetSum.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: mergeSubsetSum.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月06日 星期二 19时25分56秒 6 | ************************************************************************/ 7 | 8 | #ifndef _MERGESUBSETSUM_H 9 | #define _MERGESUBSETSUM_H 10 | // 寻找最大相连子序列和的递归算法(该算法同时适应求最小相连子序列的递归算法,只需要修改compare即可) 11 | // 数据结构与算法分析--C++语言描述 2.4.3 12 | // 算法导论 4.1 13 | 14 | /* 15 | *\parameter begin: 待计算序列的起始迭代器; 16 | *\parameter end: 待计算序列的终止迭代器; 17 | *\parameter compare: 一个可调用的对象,可用于比较两个对象的小于,默认为std::less; 18 | *\return std::iterator_traits::value_type; 19 | * 20 | * 算法性能O(NlogN) 21 | * 22 | * 算法具体思想: 把一整个序列分成两个部分,分别在左侧求解最大相连子序列和,在右侧计算 23 | * 出最大相连子序列和.整个序列的最大子序列和为左侧最大值,右侧最大值,横跨左右和, 24 | * 三个中的最大值; 25 | * 26 | */ 27 | #include 28 | #include 29 | template::value_type>> 30 | typename std::iterator_traits::value_type 31 | megre(Iterator begin, Iterator end, CompareType compare=CompareType()) 32 | { 33 | typedef typename std::iterator_traits::value_type T; 34 | // 基准情形 35 | if (std::distance(begin, end) <= 1) 36 | return *begin; 37 | // 递归情形 38 | auto center = begin + (std::distance(begin, end)) / 2; 39 | T maxLeftSum = megre(begin, center, compare); 40 | T maxRightSum = megre(center+1, end, compare); 41 | 42 | // 左侧 43 | T maxLeftBounderSum = *center; 44 | T leftBounderSum = *center - *center; 45 | for (auto middle = center; middle != begin-1; --middle){ 46 | leftBounderSum += *middle; 47 | if (compare(maxLeftSum, leftBounderSum)) 48 | maxLeftBounderSum = leftBounderSum; 49 | } 50 | 51 | // 右侧 52 | T maxRightBounderSum = *(center+1); 53 | T rightBounderSum = *(center+1) - *(center+1); 54 | for (auto middle = center+1; middle != end; ++middle){ 55 | rightBounderSum += *middle; 56 | if (compare(maxRightSum, rightBounderSum)) 57 | maxRightBounderSum = rightBounderSum; 58 | } 59 | 60 | // 返回三种情况的最大值 61 | auto max = maxLeftSum; 62 | if (compare(max, maxRightSum)) 63 | max = maxRightSum; 64 | if (compare(max, maxLeftBounderSum + maxRightBounderSum)) 65 | max = maxLeftBounderSum + maxRightBounderSum; 66 | 67 | return max; 68 | } 69 | #endif 70 | -------------------------------------------------------------------------------- /subset_algorithm/merge_subset_sum/mergeSubsetSum_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: mergeSubSetSum_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月06日 星期二 20时32分06秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include 11 | using std::vector; 12 | #include 13 | using std::array; 14 | #include "mergeSubsetSum.h" 15 | 16 | bool compare(int num1, int num2) 17 | { 18 | return num1 > num2; 19 | } 20 | 21 | void Test1() 22 | { 23 | vector vec1{1,2,3,4,5,6,7,8,9,10}; 24 | vector vec2{1,-2,3,-4,5,-6,7,-8,9,-10}; 25 | vector vec4{-1,-2,-3,-4,-5,-6,-7,-8,-9,-10}; 26 | cout << "*********************递归算法的测试*************************\n"; 27 | int max = megre(vec1.cbegin(), vec1.cend()); 28 | int min = megre(vec1.cbegin(), vec1.cend(), compare); 29 | cout << "********************全部都是正数的数组**********************\n"; 30 | // 输出数组 31 | for (auto i : vec1) 32 | cout << i << " "; 33 | cout << endl; 34 | cout <<"最大相连子序列和:\t" << max <<"\n" 35 | << "最小相连子序列和:\t" << min << endl; 36 | max = megre(vec2.cbegin(), vec2.cend()); 37 | min = megre(vec2.cbegin(), vec2.cend(),compare); 38 | cout << "********************有正数有负数的数组**********************\n"; 39 | for (auto i : vec2) 40 | cout << i << " "; 41 | cout << endl; 42 | cout << "最大相连子序列和:\t" << max << "\n" 43 | << "最小相连子序列和:\t" << min << endl; 44 | cout << "*********************全部都是负数的数组*********************\n"; 45 | for (auto i : vec4) 46 | cout << i << " "; 47 | cout << endl; 48 | max = megre(vec4.cbegin(), vec4.cend()); 49 | min = megre(vec4.cbegin(), vec4.cend(),compare); 50 | cout << "最大相连子序列和:\t" << max << "\n" 51 | << "最小相连子序列和:\t" << min << endl; 52 | } 53 | 54 | int main() 55 | { 56 | Test1(); 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /subset_algorithm/online_subset_sum/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: onlineSubsetSum.h onlineSubsetSum_test.cpp 8 | $(c++) $(VERSION) -o Test onlineSubsetSum_test.cpp 9 | -------------------------------------------------------------------------------- /subset_algorithm/online_subset_sum/onlineSubsetSum.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: onlineSubsetSum.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月06日 星期二 21时11分49秒 6 | ************************************************************************/ 7 | 8 | #ifndef _ONLINESUBSETSUM_H 9 | #define _ONLINESUBSETSUM_H 10 | // 寻找最大相连子序列和的初始算法(该算法同时也适用于求最小相连子序列和,只需要修改compare即可) 11 | // 数据结构与算法分析--C++语言描述 2.4.3 12 | // 算法导论4.1 13 | /* 14 | *\parameter begin: 待计算序列的起始迭代器(也可以指向数组中某元素数组的指针); 15 | *\parameter end: 待计算序列的终止迭代器(也可以指向数组中某元素数组的指针); 16 | *\parameter compare: 一个可调用的对象,可用于比较两个对象的小于,默认为std::less; 17 | *\return std::iterator_traits::value_type; 18 | * 19 | *算法性能: O(N) 20 | *算法的具体思想: 明确可知: 在取最小相连序列和的时候,当 thisSsum > maxSum && thisSum > 0 21 | *则最小序列和不可能以thisSum开头; 同理在取最大相连序列和的时候, 当thisSum < maxSum && thisSum <0 22 | *则最大序列和不可能以thisSum开头; 23 | */ 24 | #include 25 | #include 26 | template::value_type>> 27 | typename std::iterator_traits::value_type 28 | online(Iterator begin, Iterator end, compareType compare=compareType()) 29 | { 30 | auto size = std::distance(begin, end); 31 | if (size < 1){ 32 | std::cerr << "您所输入的序列范围有误\n"; 33 | return -1; 34 | } 35 | 36 | typedef typename std::iterator_traits::value_type T; 37 | T maxSum = *begin; 38 | T thisSum = *begin - *begin; 39 | for (auto index = begin; index != end; ++index){ 40 | thisSum += *index; 41 | if (compare(maxSum, thisSum)) 42 | maxSum = thisSum; 43 | else if (compare(thisSum, maxSum) && compare(thisSum, *begin - *begin)) 44 | thisSum = *begin - *begin; 45 | } 46 | 47 | return maxSum; 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /subset_algorithm/online_subset_sum/onlineSubsetSum_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: onlineSubsetSum_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月06日 星期二 21时39分55秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include 11 | using std::vector; 12 | #include 13 | using std::array; 14 | #include "onlineSubsetSum.h" 15 | 16 | bool compare(int num1, int num2) 17 | { 18 | return num1 > num2; 19 | } 20 | 21 | void Test1() 22 | { 23 | vector vec1{1,2,3,4,5,6,7,8,9,10}; 24 | vector vec2{1,-2,3,-4,5,-6,7,-8,9,-10}; 25 | vector vec4{-1,-2,-3,-4,-5,-6,-7,-8,-9,-10}; 26 | cout << "*********************递归算法的测试*************************\n"; 27 | int max = online(vec1.cbegin(), vec1.cend()); 28 | int min = online(vec1.cbegin(), vec1.cend(), compare); 29 | cout << "********************全部都是正数的数组**********************\n"; 30 | // 输出数组 31 | for (auto i : vec1) 32 | cout << i << " "; 33 | cout << endl; 34 | cout <<"最大相连子序列和:\t" << max <<"\n" 35 | << "最小相连子序列和:\t" << min << endl; 36 | max = online(vec2.cbegin(), vec2.cend()); 37 | min = online(vec2.cbegin(), vec2.cend(),compare); 38 | cout << "********************有正数有负数的数组**********************\n"; 39 | for (auto i : vec2) 40 | cout << i << " "; 41 | cout << endl; 42 | cout << "最大相连子序列和:\t" << max << "\n" 43 | << "最小相连子序列和:\t" << min << endl; 44 | cout << "*********************全部都是负数的数组*********************\n"; 45 | for (auto i : vec4) 46 | cout << i << " "; 47 | cout << endl; 48 | max = online(vec4.cbegin(), vec4.cend()); 49 | min = online(vec4.cbegin(), vec4.cend(),compare); 50 | cout << "最大相连子序列和:\t" << max << "\n" 51 | << "最小相连子序列和:\t" << min << endl; 52 | } 53 | 54 | int main() 55 | { 56 | Test1(); 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /subset_algorithm/original_subset_sum/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: originalSubsetSum.h originalSubsetSum_Test.cpp 8 | $(c++) $(VERSION) -o Test originalSubsetSum_Test.cpp 9 | -------------------------------------------------------------------------------- /subset_algorithm/original_subset_sum/originalSubsetSum.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: originalSubsetSum.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月06日 星期二 16时40分53秒 6 | ************************************************************************/ 7 | 8 | #ifndef _ORIGINALSUBSETSUM_H 9 | #define _ORIGINALSUBSETSUM_H 10 | // 寻找最大相连子序列和的暴力算法(该算法同时适用于求最小相连子序列和,只需要修改compare即可) 11 | // 数据结构与算法分析--C++语言描述 2.4.3 12 | // 算法导论 4.1 13 | /* ! 14 | *\parameter begin: 待计算序列的起始迭代器(也可以是指向数组中某元素数组的指针); 15 | *\parameter end: 待计算序列的终止迭代器(也可以是指向数组中某元素数组的指针); 16 | *\parameter compare: 一个可调用的对象,可用于比较两个对象的小于,默认为std::less; 17 | *\return std::iterator_traits::value_type 18 | *算法性能O(N^2) 19 | * 20 | *算法的具体思想: 依次遍历序列中的子序列,然后计算子序列和,给出最大的值. 21 | */ 22 | #include 23 | #include 24 | template::value_type>> 25 | typename std::iterator_traits::value_type 26 | original(Iterator begin, Iterator end, CompareType compare=CompareType()) 27 | { 28 | auto size = std::distance(begin, end); 29 | if (size < 1){ 30 | std::cerr << "您输入的序列范围有误.\n"; 31 | return -1; 32 | } 33 | typedef typename std::iterator_traits::value_type T; 34 | T goodSum = *begin; 35 | while (begin != end){ 36 | T subsetSum = *begin - *begin; 37 | for (auto current = begin; current != end; ++current){ 38 | subsetSum += *current; 39 | if (compare(goodSum, subsetSum)) 40 | goodSum = subsetSum; 41 | } 42 | ++begin; 43 | } 44 | return goodSum; 45 | } 46 | #endif 47 | -------------------------------------------------------------------------------- /subset_algorithm/original_subset_sum/originalSubsetSum_Test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: originalSubsetSum_Test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月06日 星期二 17时11分54秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include 11 | using std::vector; 12 | #include 13 | using std::array; 14 | #include "originalSubsetSum.h" 15 | 16 | bool compare(int num1, int num2) 17 | { 18 | return num1 > num2; 19 | } 20 | 21 | void Test1() 22 | { 23 | vector vec1{1,2,3,4,5,6,7,8,9,10}; 24 | vector vec2{1,-2,3,-4,5,-6,7,-8,9,-10}; 25 | vector vec3; 26 | vector vec4{-1,-2,-3,-4,-5,-6,-7,-8,-9,-10}; 27 | cout << "*********************初始算法的测试*************************\n"; 28 | int max = original(vec1.cbegin(), vec1.cend()); 29 | int min = original(vec1.cbegin(), vec1.cend(), compare); 30 | cout << "********************全部都是正数的数组**********************\n"; 31 | // 输出数组 32 | for (auto i : vec1) 33 | cout << i << " "; 34 | cout << endl; 35 | cout <<"最大相连子序列和:\t" << max <<"\n" 36 | << "最小相连子序列和:\t" << min << endl; 37 | max = original(vec2.cbegin(), vec2.cend()); 38 | min = original(vec2.cbegin(), vec2.cend(),compare); 39 | cout << "********************有正数有负数的数组**********************\n"; 40 | for (auto i : vec2) 41 | cout << i << " "; 42 | cout << endl; 43 | cout << "最大相连子序列和:\t" << max << "\n" 44 | << "最小相连子序列和:\t" << min << endl; 45 | cout << "********************空序列**********************************\n"; 46 | max = original(vec3.cbegin(), vec3.cend()); 47 | min = original(vec3.cbegin(), vec3.cend(), compare); 48 | cout << "最大相连子序列和:\t" << max << "\n" 49 | << "最小相连子序列和:\t" << min << endl; 50 | cout << "*********************全部都是负数的数组*********************\n"; 51 | for (auto i : vec4) 52 | cout << i << " "; 53 | cout << endl; 54 | max = original(vec4.cbegin(), vec4.cend()); 55 | min = original(vec4.cbegin(), vec4.cend(),compare); 56 | cout << "最大相连子序列和:\t" << max << "\n" 57 | << "最小相连子序列和:\t" << min << endl; 58 | } 59 | 60 | int main() 61 | { 62 | Test1(); 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /tree_algorithm/RedBlackTree/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: RedBlackTree.h RedBlackTree_test.cpp 8 | $(c++) $(VERSION) -o Test RedBlackTree_test.cpp 9 | -------------------------------------------------------------------------------- /tree_algorithm/RedBlackTree/RedBlackTree_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: RedBlackTree_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月26日 星期一 22时56分55秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include "RedBlackTree.h" 11 | typedef RedBlackTree> IntTree; 12 | typedef RedBlackTreeNode Node; 13 | IntTree normalTree; // 标准红黑树 14 | // setUp: 产生一棵新的红黑树(1:黑色; 0:红色) 15 | /* 16 | * 7<1> 17 | * // \\ 18 | * 4<1> 13<1> 19 | * // \\ // \\ 20 | * 3<1> 6<1> 9<1> 17<0> 21 | * // // \\ 22 | * 2<0> 15<1> 18<1> 23 | * \\ 24 | * 20<0> 25 | */ 26 | bool setUp() 27 | { 28 | std::shared_ptr nodes[11]; 29 | nodes[0] = std::make_shared(15); 30 | nodes[1] = std::make_shared(6); 31 | nodes[2] = std::make_shared(7); 32 | nodes[3] = std::make_shared(3); 33 | nodes[4] = std::make_shared(4); 34 | nodes[5] = std::make_shared(2); 35 | nodes[6] = std::make_shared(13); 36 | nodes[7] = std::make_shared(9); 37 | nodes[8] = std::make_shared(18); 38 | nodes[9] = std::make_shared(17); 39 | nodes[10] = std::make_shared(20); 40 | for (std::size_t i = 0; i != 11; ++i) 41 | normalTree.insert(nodes[i]); 42 | cout << "********************插入操作测试(返回所有节点信息)********************\n"; 43 | for (std::size_t i = 0; i != 11; ++i) 44 | cout << nodes[i]->to_string() << endl; 45 | cout << "***********************最小关键值元素测试*****************************\n"; 46 | cout << normalTree.minimum(normalTree.root)->key << std::endl; 47 | cout << "***********************最大关键值元素测试*****************************\n"; 48 | cout << normalTree.maximum(normalTree.root)->key << std::endl; 49 | cout << "***********************前驱节点测试***********************************\n"; 50 | auto max = normalTree.maximum(normalTree.root); 51 | for (std::size_t i = 0; i != 11; ++i){ 52 | cout << max->key << " "; 53 | max = normalTree.predecessor(max); 54 | } 55 | cout << endl; 56 | 57 | cout << "***********************后继节点测试***********************************\n"; 58 | auto min = normalTree.minimum(normalTree.root); 59 | for (std::size_t i = 0; i != 11; ++i){ 60 | cout << min->key << " "; 61 | min = normalTree.successor(min); 62 | } 63 | cout << endl; 64 | cout << "**********************红黑树删除测试**********************************\n"; 65 | // 删除操作 66 | for (int i = 0; i != 11; ++i){ 67 | min = normalTree.minimum(normalTree.root); 68 | cout << "删除" << min->key << "后,排序:\n"; 69 | normalTree.remove(min); 70 | min = normalTree.minimum(normalTree.root); 71 | for (int j = 0; j != (11-i-1); ++j){ 72 | cout << min->key << " "; 73 | min = normalTree.successor(min); 74 | } 75 | cout << endl; 76 | 77 | } 78 | } 79 | int main() 80 | { 81 | setUp(); 82 | return 0; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /tree_algorithm/RedBlackTreeNode/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: RedBlackTreeNode.h RedBlackTreeNode_test.cpp 8 | $(c++) $(VERSION) -o Test RedBlackTreeNode_test.cpp 9 | -------------------------------------------------------------------------------- /tree_algorithm/RedBlackTreeNode/RedBlackTreeNode.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: RedBlackTreeNode.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月26日 星期一 16时04分21秒 6 | ************************************************************************/ 7 | #ifndef _REDBLACKTREENODE_H 8 | #define _REDBLACKTREENODE_H 9 | #include 10 | #include 11 | #include 12 | // BinaryTreeNode 红黑树的节点 算法导论第13章 13 | /* 14 | * 任何一个节点都有两个强引用指向左右子节点,以及一个弱引用指向它的父节点.节点 15 | * 还有一个'key'成员包含具体的数据,以及'color'成员包含节点的颜色. 16 | */ 17 | // 红黑树节点的颜色 18 | enum COLOR{ 19 | RED = 0, // 红色节点 20 | BLACK = 1, // 黑色节点 21 | }; 22 | template 23 | struct RedBlackTreeNode 24 | { 25 | public: 26 | 27 | typedef KType KeyType; //节点保存的数据类型 28 | //**************************构造函数********************************** 29 | //默认构造函数,所有的成员变量都采用默认值 30 | RedBlackTreeNode(): 31 | parent(std::weak_ptr()), 32 | lchild(std::shared_ptr()), 33 | rchild(std::shared_ptr()), 34 | key(KeyType()), 35 | color(BLACK) 36 | { } 37 | //显式构造函数 38 | /* 39 | * \parameter keyvalue: 节点要保存的数据内容. 40 | * 指定'key'成员需要赋值的数据. 41 | */ 42 | explicit RedBlackTreeNode(const KeyType& keyvalue): 43 | parent(std::weak_ptr()), 44 | lchild(std::shared_ptr()), 45 | rchild(std::shared_ptr()), 46 | key(keyvalue), 47 | color(BLACK) 48 | { } 49 | //**************************成员函数********************************** 50 | // to_string: 返回该节点的字符串描述 51 | /* 52 | * \return: 本节点的描述字符串 53 | * 该函数打印本节点的'key',以及父节点(若存在),子节点(若存在),的'key'. 54 | */ 55 | virtual std::string to_string() 56 | { 57 | std::ostringstream os; 58 | os << "node: " << key; 59 | if (auto shared_p = parent.lock()) 60 | os << "\n\t parent: " << shared_p->key; 61 | else 62 | os << "\n\t parent: " << "null_ptr"; 63 | 64 | os << "\n\t left_child: "; 65 | if (lchild) 66 | os << lchild->key << " color: " << lchild->color; 67 | else 68 | os << "nullptr"; 69 | 70 | os << "\n\t right_child: "; 71 | if (rchild) 72 | os << rchild->key << " color: " << rchild->color; 73 | else 74 | os << "nullptr"; 75 | 76 | os << "\n\t color: " << color; 77 | 78 | return os.str(); 79 | } 80 | // to_xml: 返回以该节点为根的子树的'xml'描述 81 | /* 82 | * \return: 本节点子树的'xml'描述字符串. 83 | * 该函数返回以本节点为根的子树的'xml'描述.对子节点递归调用从而生成"xml"数据. 84 | */ 85 | virtual std::string to_xml() 86 | { 87 | std::ostringstream os; 88 | os << "\n" << key << "\n"; 89 | if (auto shared_p = parent.lock()) 90 | os << "\t " << shared_p->key << ""; 91 | else 92 | os << "\t " << "null_ptr" << ""; 93 | 94 | os << "\n\t "; 95 | if (lchild) 96 | os << lchild->to_xml(); 97 | else 98 | os << "nullptr"; 99 | os << ""; 100 | 101 | os << "\n\t "; 102 | if (rchild) 103 | os << rchild->to_xml(); 104 | else 105 | os << "nullptr"; 106 | os << ""; 107 | 108 | os << "\n\t" << color << ""; 109 | 110 | return os.str(); 111 | } 112 | // is_left_child: 判断本节点是否是左子节点 113 | /* 114 | * \return 返回'true'或'false'. 115 | * 该函数判断本节点是否是左子节点.如果本节点的父节点为空,则返回'false'; 116 | * 如果本节点的父节点非空且本节点是父节点的左子节点,则返回'true';否则 117 | * 返回'false'. 118 | */ 119 | bool is_left_child() 120 | { 121 | if (auto shared_p = parent.lock()){ 122 | if (this == shared_p->lchild.get()) 123 | return true; 124 | } 125 | return false; 126 | } 127 | // is_right_child: 判断本节点是否是右节点 128 | /* 129 | * \retrun 返回'false'或'true'. 130 | * 该函数判断本节点是否是右子节点,如果本节点的父节点为空,则返回'false'; 131 | * 如果本节点的父节点非空且本节点是父节点的右子节点,则返回'true';否则 132 | * 返回'false'. 133 | */ 134 | bool is_right_child() 135 | { 136 | if (auto shared_p = parent.lock()){ 137 | if (this == shared_p->rchild.get()) 138 | return true; 139 | } 140 | return false; 141 | } 142 | //**************************数据结构********************************** 143 | std::weak_ptr parent; //节点的父节点的弱引用 144 | std::shared_ptr lchild; //节点的左子节点的强引用 145 | std::shared_ptr rchild; //节点的右子节点的强引用 146 | KeyType key; //节点的保存的数据 147 | COLOR color; //保存节点的颜色 148 | }; 149 | #endif 150 | -------------------------------------------------------------------------------- /tree_algorithm/RedBlackTreeNode/RedBlackTreeNode_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: RedBlackTreeNode_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月26日 星期一 18时57分50秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include "RedBlackTreeNode.h" 11 | 12 | void Test() 13 | { 14 | RedBlackTreeNode intNode(14); 15 | cout << "key: " << intNode.key << endl; 16 | cout << "color: " << intNode.color << endl; 17 | 18 | cout << intNode.to_string() << endl; 19 | cout << intNode.to_xml() << endl; 20 | 21 | cout << "is_left_child " << intNode.is_left_child() << endl; 22 | cout << "is_right_child " << intNode.is_right_child() << endl; 23 | } 24 | 25 | void setUp() 26 | { 27 | typedef RedBlackTreeNode Node; 28 | auto root = std::make_shared(0); 29 | root->lchild = std::make_shared(1); 30 | root->rchild = std::make_shared(2); 31 | root->lchild->parent = root; 32 | root->rchild->parent = root; 33 | cout << "key " << root->key << endl; 34 | cout << "color " << root->color << endl; 35 | cout << root->to_string() << endl; 36 | cout << root->to_xml() << endl; 37 | 38 | cout << "is_left_child " << root->is_left_child() << endl; 39 | cout << "is_right_child " << root->is_right_child() << endl; 40 | 41 | cout << "is_left_child " << root->lchild->is_left_child() << endl; 42 | cout << "is_right_child " << root->rchild->is_right_child() << endl; 43 | } 44 | int main() 45 | { 46 | Test(); 47 | setUp(); 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /tree_algorithm/binary_search_tree/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: binary_search_tree_test.cpp binary_search_tree.h 8 | $(c++) $(VERSION) -o Test binary_search_tree_test.cpp 9 | -------------------------------------------------------------------------------- /tree_algorithm/binary_search_tree/binary_search_tree_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: binary_search_tree_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月24日 星期六 10时30分31秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include 11 | #include "../binarytreeNode/binarytreeNode.h" 12 | #include "binary_search_tree.h" 13 | typedef BinarySearchTree> IntBinarySearchTree; 14 | typedef BinaryTreeNode Node; 15 | typedef Node::KeyType KeyType; 16 | IntBinarySearchTree normalTree; // 生成一棵标准的二叉搜索树 17 | IntBinarySearchTree binarySearchTree; // 生成一棵空的二叉树 18 | // setUp: 产生一棵新的二叉搜索树 19 | /* 20 | * 15 21 | * // \\ 22 | * 6 18 23 | * // \\ // \\ 24 | * 3 7 17 20 25 | * // \\ \\ 26 | * 2 4 13 27 | * // 28 | * 9 29 | */ 30 | bool setUp() 31 | { 32 | std::shared_ptr nodes[11]; 33 | nodes[0] = std::make_shared(15); 34 | nodes[1] = std::make_shared(6); 35 | nodes[2] = std::make_shared(7); 36 | nodes[3] = std::make_shared(3); 37 | nodes[4] = std::make_shared(4); 38 | nodes[5] = std::make_shared(2); 39 | nodes[6] = std::make_shared(13); 40 | nodes[7] = std::make_shared(9); 41 | nodes[8] = std::make_shared(18); 42 | nodes[9] = std::make_shared(17); 43 | nodes[10] = std::make_shared(20); 44 | bool sign = true; 45 | for (std::size_t i = 0; i != 11; ++i){ 46 | bool sign1 = normalTree.insert(nodes[i]); 47 | if (!sign1) 48 | sign = sign1; 49 | } 50 | cout << "*******************二叉树后继节点测试*************************\n"; 51 | for (int i = 0; i != 11; ++i){ 52 | auto value = normalTree.successor(nodes[i]); 53 | if (value) 54 | cout << "节点" << nodes[i]->key << "的后继节点为: " << value->key << endl; 55 | } 56 | cout << "*******************利用后继操作排序***************************\n"; 57 | auto min_ptr = normalTree.minimum(normalTree.root); 58 | while (min_ptr){ 59 | cout << min_ptr->key << " "; 60 | min_ptr = normalTree.successor(min_ptr); 61 | } 62 | cout << endl; 63 | cout << "*******************二叉树前驱节点测试*************************\n"; 64 | for (int i = 0; i != 11; ++i){ 65 | auto value = normalTree.predecessor(nodes[i]); 66 | if (value) 67 | cout << "节点" << nodes[i]->key << "的后继节点为: " << value->key << endl; 68 | } 69 | cout << "*******************利用前驱操作排序***************************\n"; 70 | auto max_ptr = normalTree.maximum(normalTree.root); 71 | while (max_ptr){ 72 | cout << max_ptr->key << " "; 73 | max_ptr = normalTree.predecessor(max_ptr); 74 | } 75 | cout << endl; 76 | cout << "*******************新建二叉搜索树*****************************\n"; 77 | return sign; 78 | } 79 | 80 | bool action(KeyType key) 81 | { 82 | std::cout << key << " "; 83 | } 84 | 85 | void preorderWalk_test() 86 | { 87 | cout << "二叉树的前序遍历:\n"; 88 | normalTree.preorderWalk(normalTree.root, action); 89 | cout << "\n二叉树的中序遍历:\n"; 90 | normalTree.inorderWalk(normalTree.root, action); 91 | cout << "\n二叉树的后序遍历:\n"; 92 | normalTree.postorderWalk(normalTree.root, action); 93 | } 94 | 95 | void minimum_test() 96 | { 97 | cout << "二叉搜索树中的最小值为: \n"; 98 | cout << normalTree.minimum(normalTree.root)->key << endl; 99 | } 100 | 101 | void maximum_test() 102 | { 103 | cout << "二叉搜索树中的最大值为: \n"; 104 | cout << normalTree.maximum(normalTree.root)->key << endl; 105 | } 106 | 107 | void search_test() 108 | { 109 | Node node(20); 110 | auto value = normalTree.search(node); 111 | cout << "二叉搜索树中是否包含元素20: " 112 | << value->key << endl; 113 | } 114 | 115 | void remove_test() 116 | { 117 | std::shared_ptr nodes[11]; 118 | nodes[0] = std::make_shared(15); 119 | nodes[1] = std::make_shared(6); 120 | nodes[2] = std::make_shared(7); 121 | nodes[3] = std::make_shared(3); 122 | nodes[4] = std::make_shared(4); 123 | nodes[5] = std::make_shared(2); 124 | nodes[6] = std::make_shared(13); 125 | nodes[7] = std::make_shared(9); 126 | nodes[8] = std::make_shared(18); 127 | nodes[9] = std::make_shared(17); 128 | nodes[10] = std::make_shared(20); 129 | for (std::size_t i = 0; i != 11; ++i) 130 | binarySearchTree.insert(nodes[i]); 131 | // 删除叶子节点 132 | //binarySearchTree.remove(nodes[0]); 133 | cout << "二叉搜索树按照从小到达的顺序依次为:\n"; 134 | auto min = binarySearchTree.minimum(binarySearchTree.root); 135 | for (int i = 0; i != 11; ++i){ 136 | cout << min->key << " "; 137 | min = binarySearchTree.successor(min); 138 | } 139 | std::cout << endl; 140 | 141 | // 删除操作 142 | for (int i = 0; i != 11; ++i){ 143 | cout << "删除" << nodes[i]->key << "后,排序:\n"; 144 | binarySearchTree.remove(nodes[i]); 145 | min = binarySearchTree.minimum(binarySearchTree.root); 146 | for (int j = 0; j != (11-i-1); ++j){ 147 | cout << min->key << " "; 148 | min = binarySearchTree.successor(min); 149 | } 150 | cout << endl; 151 | } 152 | } 153 | int main() 154 | { 155 | cout << "新建二叉搜索树是否成功: " << setUp() << endl; 156 | cout << "*******************二叉树的遍历测试***************************\n"; 157 | preorderWalk_test(); 158 | cout << "\n"; 159 | cout << "*****************二叉树的最小关键值元素***********************\n"; 160 | minimum_test(); 161 | cout << "*****************二叉树的最大关键值元素***********************\n"; 162 | maximum_test(); 163 | cout << "*****************二叉树的查询操作测试*************************\n"; 164 | search_test(); 165 | cout << "*****************二叉树的删除操作测试*************************\n"; 166 | remove_test(); 167 | return 0; 168 | } 169 | 170 | -------------------------------------------------------------------------------- /tree_algorithm/binarytree/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: binarytree.h binarytree_test.cpp 8 | $(c++) $(VERSION) -o Test binarytree_test.cpp 9 | -------------------------------------------------------------------------------- /tree_algorithm/binarytree/binarytree.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: binarytree.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月14日 星期三 14时09分53秒 6 | ************************************************************************/ 7 | 8 | #ifndef _BINARYTREE_H 9 | #define _BINARYTREE_H 10 | #include 11 | #include "../binarytreeNode/binarytreeNode.h" 12 | // BinataryTree: 二叉树, 算法导论10.4 13 | /* 14 | * 二叉树通过一个root(或引用)指向一个节点对象. 当root为空的时候,树为空. 15 | */ 16 | template 17 | struct BinaryTree 18 | { 19 | typedef NodeT NodeType; // 树的节点类型 20 | typedef typename NodeT::KeyType KeyType; // 树的节点存储数据的类型 21 | //*****************************构造函数******************************* 22 | // 默认构造函数 23 | /* 24 | * 新建的二叉树默认为空. 25 | */ 26 | BinaryTree(): root(std::shared_ptr()) {} 27 | // to_xml: 返回树的'xml'描述. 28 | /* 29 | * \return: 返回树的'xml'描述的字符串. 30 | * 该函数获取本树的'xml'描述. 31 | */ 32 | std::string to_xml() 33 | { 34 | if (root) 35 | return root->to_xml(); 36 | else 37 | return "tree is empty!"; 38 | } 39 | //*****************************数据结构******************************* 40 | std::shared_ptr root; // 树的根节点,是一个指向节点对象的强引用 41 | }; 42 | // preorder_walk: 二叉树的前序遍历 43 | /* 44 | * \parameter root: 二叉树的根节点, 强引用; 45 | * \parameter action: 对二叉树节点执行的操作; 46 | * \return void. 47 | * 本函数执行对二叉树的前序遍历,遍历时执行指定的操作. 48 | * 算法: 49 | * --对本节点执行操作; 50 | * --对左子节点前序遍历; 51 | * --对右子节点前序遍历. 52 | * 算法性能: 时间复杂度为O(N), 空间复杂度为O(N). 53 | */ 54 | template> 55 | void preorder_walk(std::shared_ptr root, 56 | ActionType action=[](typename NodeType::KeyType){}) 57 | { 58 | if (root){ 59 | action(root->key); 60 | if (root->lchild) preorder_walk(root->lchild, action); 61 | if (root->rchild) preorder_walk(root->rchild, action); 62 | } 63 | } 64 | // inorder_walk: 二叉树的中序遍历 65 | /* 66 | * \parameter root: 二叉树的根节点,强引用; 67 | * \parameter action: 对二叉树节点执行的操作; 68 | * \return void. 69 | * 本函数执行对二叉树的中序遍历,遍历时执行指定的操作. 70 | * 算法: 71 | * --对左子节点前序遍历; 72 | * --对本节点执行操作; 73 | * --对右子节点前序遍历; 74 | * 算法性能: 时间复杂度为O(N), 空间复杂度为O(N). 75 | */ 76 | template> 77 | void inorder_walk(std::shared_ptr root, 78 | ActionType action = [](typename NodeType::KeyType){}) 79 | { 80 | if (root){ 81 | if (root->lchild) inorder_walk(root->lchild, action); 82 | action(root->key); 83 | if(root->rchild) inorder_walk(root->rchild, action); 84 | } 85 | } 86 | // postorder_walk: 二叉树的后序遍历 87 | /* 88 | * \parameter root: 二叉树的根节点,强引用; 89 | * \parameter action: 对二叉树节点执行的操作; 90 | * \return void. 91 | * 本函数执行对二叉树的后序遍历, 遍历时执行指定的操作. 92 | * 算法: 93 | * --对左子节点后续遍历; 94 | * --对右子节点后续遍历; 95 | * --对本子节点操作. 96 | * 算法性能: 时间复杂度为O(N), 空间复杂度为O(N). 97 | */ 98 | template> 99 | void postorder_walk(std::shared_ptr root, 100 | ActionType action = [](typename NodeType::KeyType){}) 101 | { 102 | if (root){ 103 | if (root->lchild) postorder_walk(root->lchild, action); 104 | if (root->rchild) postorder_walk(root->rchild, action); 105 | action(root->key); 106 | } 107 | } 108 | #endif 109 | -------------------------------------------------------------------------------- /tree_algorithm/binarytree/binarytree_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: binarytree_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月14日 星期三 18时57分43秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include "binarytree.h" 11 | #include 12 | #include "../binarytreeNode/binarytreeNode.h" 13 | typedef BinaryTree> IntBinaryTree; 14 | typedef BinaryTreeNode Node; 15 | IntBinaryTree normalTree; // 生成一棵标准二叉树 16 | IntBinaryTree emptyTree; // 空树 17 | void SetUp() 18 | { 19 | std::shared_ptr nodes[9]; 20 | for (int i = 0; i < 9; ++i) 21 | nodes[i] = std::make_shared(Node(i)); 22 | nodes[1]->parent = std::weak_ptr(nodes[0]); 23 | nodes[2]->parent = std::weak_ptr(nodes[0]); 24 | nodes[0]->lchild = nodes[1]; 25 | nodes[0]->rchild = nodes[2]; 26 | 27 | nodes[3]->parent = std::weak_ptr(nodes[1]); 28 | nodes[4]->parent = std::weak_ptr(nodes[1]); 29 | nodes[1]->lchild = nodes[3]; 30 | nodes[1]->rchild = nodes[4]; 31 | 32 | nodes[5]->parent = std::weak_ptr(nodes[2]); 33 | nodes[6]->parent = std::weak_ptr(nodes[2]); 34 | nodes[2]->lchild = nodes[5]; 35 | nodes[2]->rchild = nodes[6]; 36 | 37 | nodes[7]->parent = std::weak_ptr(nodes[3]); 38 | nodes[8]->parent = std::weak_ptr(nodes[3]); 39 | nodes[3]->lchild = nodes[7]; 40 | nodes[3]->rchild = nodes[8]; 41 | 42 | normalTree.root = nodes[0]; 43 | } 44 | // 测试二叉树的前序遍历 45 | void preorder_walk_test() 46 | { 47 | cout << "对标准二叉树前序遍历测试:\n"; 48 | std::ostringstream os; 49 | auto do_work = [&os](int val){os << val << ";";}; 50 | preorder_walk(normalTree.root, do_work); 51 | cout << "前序遍历的结果: " << os.str() << endl; 52 | 53 | cout << "对空二叉树前序遍历测试:\n"; 54 | std::ostringstream os1; 55 | auto do_work1 = [&os1](int val){os1 << val << ";";}; 56 | preorder_walk(emptyTree.root, do_work1); 57 | cout << "前序遍历的结果: " << os1.str() << endl; 58 | } 59 | // 测试二叉树的中序遍历 60 | void inorder_walk_test() 61 | { 62 | cout << "对标准二叉树中序遍历测试:\n"; 63 | std::ostringstream os; 64 | auto do_work = [&os](int val){os << val << ";";}; 65 | inorder_walk(normalTree.root, do_work); 66 | cout << "中序遍历的结果: " << os.str() << endl; 67 | 68 | cout << "对空二叉树前序遍历测试:\n"; 69 | std::ostringstream os1; 70 | auto do_work1 = [&os1](int val){os1 << val << ";";}; 71 | inorder_walk(emptyTree.root, do_work1); 72 | cout << "中序遍历的结果: " << os1.str() << endl; 73 | } 74 | // 测试二叉树的后序遍历 75 | void postorder_walk_test() 76 | { 77 | cout << "对标准二叉树后序遍历测试:\n"; 78 | std::ostringstream os; 79 | auto do_work = [&os](int val){os << val << ";";}; 80 | postorder_walk(normalTree.root, do_work); 81 | cout << "后序遍历的结果: " << os.str() << endl; 82 | 83 | cout << "对空二叉树后序遍历测试:\n"; 84 | std::ostringstream os1; 85 | auto do_work1 = [&os1](int val){os1 << val << ";";}; 86 | postorder_walk(emptyTree.root, do_work1); 87 | cout << "后序遍历的结果: " << os1.str() << endl; 88 | } 89 | int main() 90 | { 91 | 92 | SetUp(); 93 | preorder_walk_test(); 94 | inorder_walk_test(); 95 | postorder_walk_test(); 96 | return 0; 97 | } 98 | 99 | -------------------------------------------------------------------------------- /tree_algorithm/binarytreeNode/Makefile: -------------------------------------------------------------------------------- 1 | c++ = g++ 2 | 3 | VERSION = -std=c++0x 4 | 5 | all: Test 6 | 7 | Test: binarytreeNode_test.cpp binarytreeNode.h 8 | $(c++) $(VERSION) -o Test binarytreeNode_test.cpp 9 | -------------------------------------------------------------------------------- /tree_algorithm/binarytreeNode/binarytreeNode.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: binarytreeNode.h 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月14日 星期三 15时55分53秒 6 | ************************************************************************/ 7 | 8 | #ifndef _BINARYTREENODE_H 9 | #define _BINARYTREENODE_H 10 | #include 11 | #include 12 | #include 13 | // BinaryTreeNode 二叉树的节点 算法导论10.4 14 | /* 15 | * 任何一个节点都有两个强引用指向左右子节点,以及一个弱引用指向它的父节点.节点 16 | * 还有一个'key'成员包含具体的数据. 17 | */ 18 | template 19 | struct BinaryTreeNode 20 | { 21 | public: 22 | typedef KType KeyType; //节点保存的数据类型 23 | //**************************构造函数********************************** 24 | //默认构造函数,所有的成员变量都采用默认值 25 | BinaryTreeNode(): 26 | parent(std::weak_ptr()), 27 | lchild(std::shared_ptr()), 28 | rchild(std::shared_ptr()), 29 | key(KeyType()) 30 | { } 31 | //显式构造函数 32 | /* 33 | * \parameter keyvalue: 节点要保存的数据内容. 34 | * 指定'key'成员需要赋值的数据. 35 | */ 36 | explicit BinaryTreeNode(const KeyType& keyvalue): 37 | parent(std::weak_ptr()), 38 | lchild(std::shared_ptr()), 39 | rchild(std::shared_ptr()), 40 | key(keyvalue) 41 | { } 42 | //**************************成员函数********************************** 43 | // to_string: 返回该节点的字符串描述 44 | /* 45 | * \return: 本节点的描述字符串 46 | * 该函数打印本节点的'key',以及父节点(若存在),子节点(若存在),的'key'. 47 | */ 48 | virtual std::string to_string() 49 | { 50 | std::ostringstream os; 51 | os << "node: " << key; 52 | if (auto shared_p = parent.lock()) 53 | os << "\n\t parent: " << shared_p->key; 54 | else 55 | os << "\n\t parent: " << "null_ptr"; 56 | 57 | os << "\n\t left_child: "; 58 | if (lchild) 59 | os << lchild->key; 60 | else 61 | os << "nullptr"; 62 | 63 | os << "\n\t right_child: "; 64 | if (rchild) 65 | os << rchild->key; 66 | else 67 | os << "nullptr"; 68 | 69 | return os.str(); 70 | } 71 | // to_xml: 返回以该节点为根的子树的'xml'描述 72 | /* 73 | * \return: 本节点子树的'xml'描述字符串. 74 | * 该函数返回以本节点为根的子树的'xml'描述.对子节点递归调用从而生成"xml"数据. 75 | */ 76 | virtual std::string to_xml() 77 | { 78 | std::ostringstream os; 79 | os << "\n" << key << "\n"; 80 | if (auto shared_p = parent.lock()) 81 | os << "\t " << shared_p->key << ""; 82 | else 83 | os << "\t " << "null_ptr" << ""; 84 | 85 | os << "\n\t "; 86 | if (lchild) 87 | os << lchild->to_xml(); 88 | else 89 | os << "nullptr"; 90 | os << ""; 91 | 92 | os << "\n\t "; 93 | if (rchild) 94 | os << rchild->to_xml(); 95 | else 96 | os << "nullptr"; 97 | os << ""; 98 | 99 | return os.str(); 100 | } 101 | // is_left_child: 判断本节点是否是左子节点 102 | /* 103 | * \return 返回'true'或'false'. 104 | * 该函数判断本节点是否是左子节点.如果本节点的父节点为空,则返回'false'; 105 | * 如果本节点的父节点非空且本节点是父节点的左子节点,则返回'true';否则 106 | * 返回'false'. 107 | */ 108 | bool is_left_child() 109 | { 110 | if (auto shared_p = parent.lock()){ 111 | if (this == shared_p->lchild.get()) 112 | return true; 113 | } 114 | return false; 115 | } 116 | // is_right_child: 判断本节点是否是右节点 117 | /* 118 | * \retrun 返回'false'或'true'. 119 | * 该函数判断本节点是否是右子节点,如果本节点的父节点为空,则返回'false'; 120 | * 如果本节点的父节点非空且本节点是父节点的右子节点,则返回'true';否则 121 | * 返回'false'. 122 | */ 123 | bool is_right_child() 124 | { 125 | if (auto shared_p = parent.lock()){ 126 | if (this == shared_p->rchild.get()) 127 | return true; 128 | } 129 | return false; 130 | } 131 | //**************************数据结构********************************** 132 | std::weak_ptr parent; //节点的父节点的弱引用 133 | std::shared_ptr lchild; //节点的左子节点的强引用 134 | std::shared_ptr rchild; //节点的右子节点的强引用 135 | KeyType key; //节点的保存的数据 136 | }; 137 | #endif 138 | -------------------------------------------------------------------------------- /tree_algorithm/binarytreeNode/binarytreeNode_test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: binarytreeNode_test.cpp 3 | > Author: ZhirunZheng 4 | > Mail: jiangxizhengzhirun@163.com 5 | > Created Time: 2018年11月14日 星期三 16时09分50秒 6 | ************************************************************************/ 7 | 8 | #include 9 | using std::cout; using std::endl; 10 | #include "binarytreeNode.h" 11 | void Test() 12 | { 13 | BinaryTreeNode intNode(14); 14 | cout << "key " << intNode.key << endl; 15 | cout << intNode.to_string() << endl; 16 | cout << intNode.to_xml() << endl; 17 | cout << "is_left_child " << intNode.is_left_child() << endl; 18 | cout << "is_right_child " << intNode.is_right_child() << endl; 19 | } 20 | 21 | void setup() 22 | { 23 | typedef BinaryTreeNode Node; 24 | auto root_node = std::make_shared(0); 25 | root_node->lchild = std::make_shared(1); 26 | root_node->rchild = std::make_shared(2); 27 | root_node->lchild->parent = root_node; 28 | root_node->rchild->parent = root_node; 29 | 30 | cout << "key " << root_node->key << endl; 31 | cout << root_node->to_string() << endl; 32 | cout << root_node->to_xml() << endl; 33 | 34 | cout << "is_left_child " << root_node->is_left_child() << endl; 35 | cout << "is_right_child " << root_node->is_right_child() << endl; 36 | 37 | cout << "is_left_child " << root_node->lchild->is_left_child() << endl; 38 | cout << "is_right_child " << root_node->rchild->is_right_child() << endl; 39 | 40 | } 41 | 42 | int main() 43 | { 44 | Test(); 45 | 46 | setup(); 47 | 48 | return 0; 49 | } 50 | --------------------------------------------------------------------------------