├── .DS_Store ├── README.md ├── c-cpp ├── .gitignore ├── .gitkeep ├── 05_array │ ├── .gitkeep │ ├── Array_gp.c │ ├── Array_gp.h │ └── array.c ├── 06_linkedlist │ ├── .gitkeep │ ├── Dlist │ │ ├── Dlist.c │ │ └── Dlist.h │ ├── LRUBasedLinkedList.cpp │ ├── list_isPalindrome │ │ ├── LinkList.cpp │ │ └── LinkList.h │ ├── palindromeList │ │ ├── LinkedList.hpp │ │ ├── ListNode.hpp │ │ └── palindromeList.cpp │ ├── single_list.c │ └── singlelist_gc │ │ ├── singleList.c │ │ └── singleList.h ├── 07_linkedlist │ ├── .gitkeep │ ├── LinkedListAlgo.c │ ├── SingleList.cpp │ ├── linked_list.h │ ├── linked_list_algo.hpp │ └── linklist_jinshaohui.c ├── 08_stack │ ├── StackBasedOnArray │ │ ├── StackBasedOnArray.cpp │ │ └── StackBasedOnArray.h │ ├── StackBasedOnLinkedList │ │ ├── StackBasedOnLinkedList.cpp │ │ └── StackBasedOnLinkedList.h │ ├── arrayStack │ │ ├── arrayStack.c │ │ └── arrayStack.h │ ├── linkList │ │ ├── linklist_stack.c │ │ └── linklist_stack.h │ ├── linked_list.h │ └── stack_based_on_linked_list.hpp ├── 09_queue │ ├── .gitkeep │ ├── array_queue.hpp │ ├── array_queue │ │ ├── array_queue.c │ │ └── array_queue.h │ ├── array_queue_test.cc │ ├── block_queue.hpp │ ├── circular_queue.hpp │ ├── circular_queue_test.cc │ ├── concurrency_queue.hpp │ ├── dynamic_array_queue.hpp │ ├── dynamic_array_queue_test.cc │ ├── linked_queue.hpp │ ├── linked_queue_test.cc │ ├── list_queue │ │ ├── list_queue.c │ │ └── list_queue.h │ ├── lock_free_queue.hpp │ └── ring_queue.c ├── 10_recursive │ ├── .gitkeep │ ├── one_two_step.c │ └── one_two_step.cc ├── 11_sorts │ ├── .gitkeep │ ├── sorts.c │ ├── sorts.cpp │ ├── sorts.hpp │ ├── sorts_jinshaohui.c │ └── sorts_test.cc ├── 12_sorts │ ├── .gitkeep │ ├── merge_sort.c │ ├── merge_sort.hpp │ ├── merge_sort_test.cc │ ├── my12_sorts │ │ ├── merge_sort.c │ │ └── quick_sort.c │ ├── quick_sort.c │ ├── quick_sort.hpp │ └── quick_sort_test.cc ├── 13_sorts │ ├── .gitkeep │ ├── bucket_sort.hpp │ ├── bucket_sort_test.cc │ ├── counting_sort.hpp │ ├── counting_sort_test.cc │ └── sort.c ├── 14_sorts │ ├── .gitkeep │ ├── analytics_of_std_sort.md │ └── counting_sort.c ├── 15_bsearch │ ├── .gitkeep │ ├── binary_search.c │ ├── bsearch.hpp │ ├── bsearch_c │ │ ├── bsearch.c │ │ └── sqrt.c │ └── bsearch_test.cc ├── 16_bsearch │ ├── .gitkeep │ ├── bsearch.c │ ├── bsearch_variant.c │ ├── bsearch_varients.hpp │ └── bsearch_varients_test.cc ├── 17_skiplist │ ├── .gitkeep │ ├── SkipList.cpp │ ├── skiplist.c │ ├── skiplist.hpp │ ├── skiplist_c │ │ ├── skiplist.c │ │ └── skiplist.h │ ├── skiplist_test.cc │ ├── skiplist_tr.hpp │ └── skiplist_tr_test.cc ├── 18_hashtable │ ├── .gitkeep │ ├── hash_map.cc │ ├── hashtable.c │ └── listhash │ │ ├── listhash.c │ │ └── listhash.h ├── 19_Dlisthash │ ├── Dlist.h │ ├── LinkedHashMap.c │ └── LinkedHashMap.h ├── 23_binarytree │ ├── binarytree.c │ └── tree │ │ ├── binarytree.c │ │ ├── list_queue.c │ │ └── list_queue.h ├── 24_binarysearchtree │ ├── binary_search_tree.cpp │ ├── binarysearchtree.c │ ├── binarysearchtree.h │ └── bst.c ├── 24_tree │ ├── Trie.c │ └── binarysearchtree.c ├── 28_heap │ └── heap.c ├── 30_Graph │ └── graph.c └── bst.c ├── object-c ├── .DS_Store ├── Array │ ├── MyArray.h │ └── MyArray.m ├── Linklist │ ├── .gitkeep │ ├── ListNode.h │ ├── ListNode.m │ ├── SinglyLinkedList.h │ ├── SinglyLinkedList.m │ └── SinglyLinkedListTests.m ├── Sorts │ ├── Sort.h │ └── Sort.m ├── Stack │ ├── LinkedStack.h │ ├── LinkedStack.m │ ├── LinkedStackTests.m │ ├── ListNode.h │ ├── ListNode.m │ └── stack_practice │ │ ├── ArrayStack.h │ │ ├── ArrayStack.m │ │ ├── BalancedParentheses.h │ │ ├── BalancedParentheses.m │ │ ├── FourOperation.h │ │ ├── FourOperation.m │ │ └── main.m └── bm_match │ ├── BM.h │ ├── BM.m │ └── main.m └── swift ├── .DS_Store ├── Array └── MyArray.swift ├── Linkedlist └── SinglyLinkedList.swift ├── Linkedlist_Algo └── LinkedListAlgo.swift ├── Queue ├── ArrayQueue.swift ├── CircularQueue.swift ├── Queue.swift └── QueueBasedOnLinkedList.swift ├── Sorts └── Sort.swift └── Stack ├── Browser.swift ├── BrowserDemo.swift ├── Stack.swift └── StackBasedOnLinkedList.swift /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/.DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # algo 2 | 常用的算法和数据结构代码实现 3 | * object-c 4 | * swift 5 | * c 6 | 7 | [简书地址](https://www.jianshu.com/u/cde18f686c44) 8 | 9 | ## 算法 10 | * 实现冒泡排序、插入排序、选择排序、桶排序、归并排序、快速排序、计数排序 11 | 12 | ## 数组 13 | * 实现一个支持动态扩容的数组 14 | * 实现一个大小固定的有序数组,支持动态增删改操作 15 | * 实现两个有序数组合并为一个有序数组 16 | 17 | ## 链表 18 | * 实现单链表、循环链表、双向链表,支持增删操作 19 | * 实现单链表反转 20 | * 实现两个有序的链表合并为一个有序链表 21 | * 实现求链表的中间结点 22 | 23 | ## 栈 24 | * 用数组实现一个顺序栈 25 | * 用链表实现一个链式栈 26 | * 编程模拟实现一个浏览器的前进、后退功能 27 | 28 | ## 队列 29 | * 用数组实现一个顺序队列 30 | * 用链表实现一个链式队列 31 | * 实现一个循环队列 32 | -------------------------------------------------------------------------------- /c-cpp/.gitignore: -------------------------------------------------------------------------------- 1 | # main files 2 | main.* 3 | 4 | # executives 5 | a.out 6 | 7 | # objective files 8 | *.o 9 | *.obj 10 | -------------------------------------------------------------------------------- /c-cpp/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/.gitkeep -------------------------------------------------------------------------------- /c-cpp/05_array/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/05_array/.gitkeep -------------------------------------------------------------------------------- /c-cpp/05_array/Array_gp.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/05_array/Array_gp.h -------------------------------------------------------------------------------- /c-cpp/05_array/array.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct array { 6 | int size; 7 | int used; 8 | int *arr; 9 | }; 10 | 11 | void dump(struct array *array) 12 | { 13 | int idx; 14 | 15 | for (idx = 0; idx < array->used; idx++) 16 | printf("[%02d]: %08d\n", idx, array->arr[idx]); 17 | } 18 | 19 | void alloc(struct array *array) 20 | { 21 | array->arr = (int *)malloc(array->size * sizeof(int)); 22 | } 23 | 24 | int insert(struct array *array, int elem) 25 | { 26 | int idx; 27 | if (array->used >= array->size) 28 | return -1; 29 | 30 | for (idx = 0; idx < array->used; idx++) { 31 | if (array->arr[idx] > elem) 32 | break; 33 | } 34 | 35 | if (idx < array->used) 36 | memmove(&array->arr[idx+1], &array->arr[idx], 37 | (array->used - idx) * sizeof(int)); 38 | 39 | array->arr[idx] = elem; 40 | array->used++; 41 | return idx; 42 | } 43 | 44 | int delete(struct array *array, int idx) 45 | { 46 | if (idx < 0 || idx >= array->used) 47 | return -1; 48 | 49 | memmove(&array->arr[idx], &array->arr[idx+1], 50 | (array->used - idx - 1) * sizeof(int)); 51 | array->used--; 52 | return 0; 53 | } 54 | 55 | int search(struct array *array, int elem) 56 | { 57 | int idx; 58 | 59 | for (idx = 0; idx < array->used; idx++) { 60 | if (array->arr[idx] == elem) 61 | return idx; 62 | if (array->arr[idx] > elem) 63 | return -1; 64 | } 65 | 66 | return -1; 67 | } 68 | 69 | int main() 70 | { 71 | int idx; 72 | struct array ten_int = {10, 0, NULL}; 73 | 74 | alloc(&ten_int); 75 | if (!ten_int.arr) 76 | return -1; 77 | insert(&ten_int, 1); 78 | insert(&ten_int, 3); 79 | insert(&ten_int, 2); 80 | printf("=== insert 1, 3, 2\n"); 81 | dump(&ten_int); 82 | 83 | idx = search(&ten_int, 2); 84 | printf("2 is at position %d\n", idx); 85 | idx = search(&ten_int, 9); 86 | printf("9 is at position %d\n", idx); 87 | 88 | printf("=== delete [6] element \n"); 89 | delete(&ten_int, 6); 90 | dump(&ten_int); 91 | printf("=== delete [0] element \n"); 92 | delete(&ten_int, 0); 93 | dump(&ten_int); 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/06_linkedlist/.gitkeep -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/Dlist/Dlist.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: Dlist.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-07 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | 10 | typedef struct DlistNode //双向链表中每一个节点 11 | { 12 | struct DlistNode *prev; //节点前项指针 13 | struct DlistNode *next; //节点后项指针 14 | int data; //数据 15 | }stDlistNode; 16 | 17 | typedef struct Dlisthead //定义链表总体 18 | { 19 | int size; //链表长度 20 | stDlistNode *head; //头指针 21 | stDlistNode *tail; //尾部指针 22 | }stDlistHead; 23 | 24 | -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/list_isPalindrome/LinkList.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/06_linkedlist/list_isPalindrome/LinkList.cpp -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/list_isPalindrome/LinkList.h: -------------------------------------------------------------------------------- 1 | #ifndef LINKLIST_H 2 | #define LINKLIST_H 3 | 4 | #include 5 | #include 6 | typedef char ElemType; 7 | typedef struct LNode 8 | { 9 | ElemType data; 10 | struct LNode*next; 11 | }LinkList; 12 | 13 | void CreateListHead(LinkList *&L,ElemType a[],int n); 14 | void CreateListTail(LinkList *&L,ElemType a[],int n); 15 | void InitList(LinkList *&L); 16 | void DestroyList(LinkList *&L); 17 | bool ListEmpty(LinkList *L); 18 | int ListLength(LinkList *L); 19 | void ShowList(LinkList *L); 20 | bool GetListElem(LinkList *L,int i,ElemType &e); 21 | int LocateElem(LinkList*L,ElemType e); 22 | bool ListInsert(LinkList *&L,int i,ElemType e); 23 | bool ListDelete(LinkList *&L,int i,ElemType &e); 24 | #endif 25 | -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/palindromeList/LinkedList.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: TripleZ 3 | * Date: 2018-10-10 4 | * Brief: Linked list class. 5 | */ 6 | 7 | #ifndef _LINKEDLIST_HPP_ 8 | #define _LINKEDLIST_HPP_ 9 | 10 | #include 11 | #include "ListNode.hpp" 12 | 13 | class LinkedList { 14 | public: 15 | int size; 16 | int length; 17 | ListNode *head; 18 | LinkedList(); 19 | LinkedList(int size); 20 | ~LinkedList(); 21 | ListNode* FindElem(int elemVal); 22 | bool DeleteElem(ListNode *elem); 23 | bool DeleteLastElem(); 24 | bool InsertElemAtFront(int elemVal); 25 | bool InsertElemAtBack(int elemVal); 26 | void PrintList(); 27 | }; 28 | 29 | LinkedList::LinkedList() { 30 | this -> head = new ListNode(); 31 | this -> head->next = nullptr; 32 | this -> head->val = -1; 33 | this -> size = 10; // default 34 | this -> length = 0; 35 | } 36 | 37 | LinkedList::LinkedList(int size) { 38 | this -> head = new ListNode(); 39 | this -> head->next = nullptr; 40 | this -> head->val = -1; 41 | 42 | this -> size = size; 43 | this -> length = 0; 44 | } 45 | 46 | LinkedList::~LinkedList() { 47 | ListNode *p, *q; 48 | p = this -> head; 49 | while(p -> next != nullptr) { 50 | q = p -> next; 51 | p -> next = p -> next -> next; 52 | delete q; 53 | } 54 | delete head; 55 | this -> head = nullptr; 56 | this -> length = 0; 57 | } 58 | 59 | ListNode* LinkedList::FindElem(int elemVal) { 60 | ListNode *p; 61 | for (p = this -> head -> next; p != nullptr; p = p -> next) { 62 | if (p -> val == elemVal) { 63 | return p; 64 | } 65 | } 66 | return nullptr; 67 | } 68 | 69 | bool LinkedList::DeleteElem(ListNode *elem) { 70 | ListNode *prev, *next; 71 | for (prev = this -> head; prev -> next != elem; prev = prev -> next); 72 | next = elem -> next; 73 | prev -> next = next; 74 | delete elem; 75 | this -> length --; 76 | return true; 77 | } 78 | 79 | bool LinkedList::DeleteLastElem() { 80 | ListNode *prev, *elem; 81 | for (prev = this -> head; prev -> next -> next != nullptr; prev = prev -> next) ; 82 | elem = prev -> next; 83 | prev -> next = nullptr; 84 | delete elem; 85 | this -> length --; 86 | return true; 87 | } 88 | 89 | bool LinkedList::InsertElemAtFront(int elemVal) { 90 | ListNode *newNode = new ListNode(); 91 | newNode -> val = elemVal; 92 | newNode -> next = this -> head -> next; 93 | this -> head -> next = newNode; 94 | this -> length ++; 95 | return true; 96 | } 97 | 98 | bool LinkedList::InsertElemAtBack(int elemVal) { 99 | ListNode *newNode = new ListNode(); 100 | newNode -> val = elemVal; 101 | ListNode *end; 102 | for (end = this -> head; end -> next != nullptr; end = end -> next); 103 | end -> next = newNode; 104 | newNode -> next = nullptr; 105 | this -> length ++; 106 | return true; 107 | } 108 | 109 | void LinkedList::PrintList() { 110 | ListNode *elem; 111 | printf("List: "); 112 | for (elem = this -> head -> next; elem -> next != nullptr; elem = elem -> next) { 113 | printf("%d - ", elem -> val); 114 | } 115 | printf("%d\n", elem -> val); 116 | } 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/palindromeList/ListNode.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: TripleZ 3 | * Date: 2018-10-10 4 | * Brief: ListNode class. 5 | */ 6 | 7 | #ifndef _LISTNODE_HPP_ 8 | #define _LISTNODE_HPP_ 9 | 10 | class ListNode { 11 | public: 12 | int val; 13 | ListNode *next; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/palindromeList/palindromeList.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: TripleZ 3 | * Date: 2018-10-10 4 | * Brief: Check a list whether is palindrome. 5 | */ 6 | 7 | #include 8 | #include "LinkedList.hpp" 9 | 10 | bool CheckPalindromeList(LinkedList *list) { 11 | // 使用快慢指针找链表中点 12 | ListNode *slow, *fast, *mid2; 13 | slow = list -> head; 14 | fast = list -> head; 15 | while (fast -> next != nullptr) { 16 | slow = slow -> next; 17 | fast = fast -> next; 18 | if (fast -> next != nullptr) { 19 | fast = fast -> next; 20 | mid2 = slow -> next; 21 | } else { 22 | mid2 = nullptr; 23 | } 24 | } 25 | 26 | // 从中点向后逆转链表(区分奇偶情况) 27 | ListNode *mid = slow; 28 | ListNode *elem, *prev, *save; 29 | if (mid2 == nullptr) { // odd 30 | elem = mid; 31 | prev = mid -> next; 32 | } else { // even 33 | elem = mid2; 34 | prev = mid2 -> next; 35 | mid2 -> next = nullptr; 36 | } 37 | save = prev -> next; 38 | mid -> next = nullptr; 39 | while (save != nullptr) { 40 | prev -> next = elem; 41 | elem = prev; 42 | prev = save; 43 | save = save -> next; 44 | } 45 | prev -> next = elem; 46 | 47 | ListNode *end = prev; 48 | ListNode *front = list -> head -> next; 49 | 50 | // 从头尾同时遍历比较,检测链表是否为回文 51 | bool palindrome = true; 52 | while (front != end) { 53 | // printf("%d, %d\n", front -> val, end -> val); 54 | if (front -> val != end -> val) { 55 | palindrome = false; 56 | break; 57 | } 58 | front = front -> next; 59 | end = end -> next; 60 | } 61 | 62 | palindrome ? printf("The list is palindrome~\n") : printf("The list is not palindrome!\n"); 63 | 64 | return palindrome; 65 | } 66 | 67 | int main(int argc, char const *argv[]) { 68 | 69 | int init[] = {1, 2, 3, 2, 1}; 70 | LinkedList *list = new LinkedList(5); 71 | for (int i = 0; i < 5; i++) { 72 | list -> InsertElemAtBack(init[i]); 73 | } 74 | list -> PrintList(); 75 | 76 | CheckPalindromeList(list); // true 77 | 78 | list -> InsertElemAtFront(5); 79 | CheckPalindromeList(list); // false 80 | 81 | 82 | int init2[] = {1, 2, 3, 3, 2, 1}; 83 | LinkedList *list2 = new LinkedList(10); 84 | for (int i = 0; i < 6; i++) list2 -> InsertElemAtBack(init2[i]); 85 | list2 -> PrintList(); 86 | CheckPalindromeList(list2); 87 | 88 | list2 -> InsertElemAtBack(4); 89 | CheckPalindromeList(list2); 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/single_list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct single_list { 5 | struct single_list *next; 6 | int val; 7 | }; 8 | 9 | struct single_list_head { 10 | struct single_list *head; 11 | }; 12 | 13 | bool is_empty(struct single_list_head *head) 14 | { 15 | return head->head == NULL; 16 | } 17 | 18 | void dump(struct single_list_head *head) 19 | { 20 | struct single_list *tmp = head->head; 21 | int idx = 0; 22 | 23 | while (tmp) { 24 | printf("[%02d]: %08d\n", idx++, tmp->val); 25 | tmp = tmp->next; 26 | } 27 | } 28 | 29 | void insert(struct single_list **prev, struct single_list *elem) 30 | { 31 | if (!prev) 32 | return; 33 | 34 | elem->next = *prev; 35 | *prev = elem; 36 | } 37 | 38 | void insert_head(struct single_list_head *head, struct single_list *elem) 39 | { 40 | insert(&head->head, elem); 41 | } 42 | 43 | struct single_list* del(struct single_list **prev) 44 | { 45 | struct single_list *tmp; 46 | 47 | if (!prev) 48 | return NULL; 49 | if (*prev == NULL) 50 | return NULL; 51 | tmp = *prev; 52 | *prev = (*prev)->next; 53 | tmp->next = NULL; 54 | 55 | return tmp; 56 | }; 57 | 58 | struct single_list* delete_head(struct single_list_head* head) 59 | { 60 | return del(&head->head); 61 | }; 62 | 63 | struct single_list** search(struct single_list_head* head, int target) 64 | { 65 | struct single_list **prev, *tmp; 66 | 67 | for (prev = &head->head, tmp = *prev; 68 | tmp && (tmp->val < target); 69 | prev = &tmp->next, tmp = *prev) 70 | ; 71 | 72 | return prev; 73 | }; 74 | 75 | void reverse(struct single_list_head* head) 76 | { 77 | struct single_list_head tmp = {NULL}; 78 | struct single_list *elem; 79 | 80 | while (!is_empty(head)) { 81 | elem = delete_head(head); 82 | insert_head(&tmp, elem); 83 | } 84 | 85 | head->head = tmp.head; 86 | } 87 | 88 | bool is_cyclic(struct single_list_head* head) 89 | { 90 | struct single_list *s1, *s2; 91 | 92 | s1 = s2 = head->head; 93 | 94 | while(s1 && s2) { 95 | s1 = s1->next; 96 | s2 = s2->next ? s2->next->next:s2->next; 97 | 98 | if (s1 == s2) 99 | return true; 100 | } 101 | return false; 102 | } 103 | 104 | struct single_list* middle(struct single_list_head* head) 105 | { 106 | struct single_list *s1, *s2; 107 | struct single_list pseudo_head; 108 | 109 | pseudo_head.next = head->head; 110 | s1 = s2 = &pseudo_head; 111 | 112 | while (true) { 113 | if (!s2 || !s2->next) 114 | return s1; 115 | s1 = s1->next; 116 | s2 = s2->next->next; 117 | } 118 | 119 | return NULL; 120 | }; 121 | 122 | int main() 123 | { 124 | struct single_list_head head = {NULL}; 125 | struct single_list lists[10]; 126 | struct single_list **prev; 127 | int idx; 128 | 129 | for (idx = 0; idx < 10; idx++) { 130 | lists[idx].val = idx; 131 | lists[idx].next = NULL; 132 | } 133 | 134 | insert_head(&head, &lists[6]); 135 | insert_head(&head, &lists[5]); 136 | insert_head(&head, &lists[4]); 137 | insert_head(&head, &lists[1]); 138 | insert_head(&head, &lists[0]); 139 | 140 | printf("=== insert 0, 1, 4, 5, 6\n"); 141 | dump(&head); 142 | 143 | prev = search(&head, 2); 144 | insert(prev, &lists[2]); 145 | printf("=== insert 2\n"); 146 | dump(&head); 147 | 148 | printf("middle elem is %d\n", middle(&head)->val); 149 | 150 | prev = search(&head, 2); 151 | if ((*prev) && ((*prev)->val == 2)) 152 | printf("The list contains 2\n"); 153 | else 154 | printf("The list not contains 2\n"); 155 | 156 | del(prev); 157 | prev = search(&head, 2); 158 | printf("After remove 2\n"); 159 | if ((*prev) && ((*prev)->val == 2)) 160 | printf("The list contains 2\n"); 161 | else 162 | printf("The list not contains 2\n"); 163 | dump(&head); 164 | 165 | printf("After reverse \n"); 166 | reverse(&head); 167 | dump(&head); 168 | 169 | printf("middle elem is %d\n", middle(&head)->val); 170 | 171 | lists[0].next = &lists[6]; 172 | printf("list is%s cyclic\n", is_cyclic(&head)?"":" not"); 173 | 174 | return 0; 175 | } 176 | -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/singlelist_gc/singleList.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/06_linkedlist/singlelist_gc/singleList.c -------------------------------------------------------------------------------- /c-cpp/06_linkedlist/singlelist_gc/singleList.h: -------------------------------------------------------------------------------- 1 | #ifndef __SINGLELIST_H__ 2 | #define __SINGLELIST_H__ 3 | 4 | #include 5 | #include 6 | 7 | typedef struct listNode 8 | { 9 | struct listNode *next; 10 | void *value; 11 | }listNode; 12 | 13 | typedef struct linkedList 14 | { 15 | listNode *head; 16 | size_t len; 17 | size_t typesize; 18 | 19 | void(*dup)(void*, void*); 20 | int(*match)(void*, void*); 21 | void(*free)(void*); 22 | }linkedList; 23 | 24 | #define listSetDupMethod(l,m) ((l)->dup = (m)) 25 | #define listSetFreeMethod(l,m) ((l)->free = (m)) 26 | #define listSetMatchMethod(l,m) ((l)->match = (m)) 27 | 28 | #define listGetDupMethod(l) ((l)->dup) 29 | #define listGetFree(l) ((l)->free) 30 | #define listGetMatchMethod(l) ((l)->match) 31 | 32 | linkedList *listCreate(); 33 | void listRelease(linkedList *list); 34 | void listEmpty(linkedList *list); 35 | linkedList *listAddNodeHead(linkedList *list, void *value); 36 | linkedList *listAddNodeTail(linkedList *list, void *value); 37 | linkedList *listInsertNode(linkedList *list, listNode *old_node, void *value, bool after); 38 | void listDelNode(linkedList *list, listNode *node); 39 | 40 | listNode *listSearchKey(linkedList *list, void *key); 41 | listNode *listIndex(linkedList *list, long index); 42 | linkedList* listRewind(linkedList *list); 43 | 44 | size_t listLength(linkedList *list); 45 | 46 | #endif // !__SINGLELIST_H__ 47 | -------------------------------------------------------------------------------- /c-cpp/07_linkedlist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/07_linkedlist/.gitkeep -------------------------------------------------------------------------------- /c-cpp/07_linkedlist/SingleList.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/07_linkedlist/SingleList.cpp -------------------------------------------------------------------------------- /c-cpp/07_linkedlist/linked_list.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 单链表 3 | * 4 | * Author: Liam Huang (Liam0205) 5 | */ 6 | 7 | #ifndef LINKEDLIST_LINKED_LIST_H_ 8 | #define LINKEDLIST_LINKED_LIST_H_ 9 | 10 | #include 11 | 12 | template 13 | struct Node { 14 | using ptr_t = std::shared_ptr>; 15 | T data; 16 | ptr_t next; 17 | 18 | Node(T data_) : data(data_), next(nullptr) {} 19 | Node() : next(nullptr) {} 20 | }; 21 | 22 | #endif // LINKEDLIST_LINKED_LIST_H_ 23 | -------------------------------------------------------------------------------- /c-cpp/07_linkedlist/linked_list_algo.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 0) 遍历单链表 3 | * 1) 单链表反转 4 | * 2) 链表中环的检测 5 | * 3) 两个有序的链表合并 6 | * 4) 删除链表倒数第n个结点 7 | * 5) 求链表的中间结点 8 | * 9 | * Author: Liam Huang (Liam0205) 10 | */ 11 | 12 | #ifndef LINKEDLIST_LINKED_LIST_ALGO_HPP_ 13 | #define LINKEDLIST_LINKED_LIST_ALGO_HPP_ 14 | 15 | #include 16 | 17 | #include "linked_list.h" 18 | 19 | template 20 | void traverse(typename Node::ptr_t head, UnaryFunc do_traverse) { 21 | auto sentry = std::make_shared>(); 22 | sentry->next = head; 23 | decltype(sentry) work = sentry; 24 | while (work = work->next) { 25 | do_traverse(work); 26 | } 27 | } 28 | 29 | template 30 | typename Node::ptr_t reverse(typename Node::ptr_t head) { 31 | if (nullptr == head or nullptr == head->next) { 32 | return head; 33 | } 34 | decltype(head) prev = nullptr, curr = head, next = head->next; 35 | while (nullptr != next) { 36 | curr->next = prev; 37 | prev = curr; 38 | curr = next; 39 | next = curr->next; 40 | } 41 | curr->next = prev; 42 | return curr; 43 | } 44 | 45 | template 46 | bool check_circle(typename Node::ptr_t head) { 47 | if (nullptr == head or nullptr == head->next) { 48 | return false; 49 | } 50 | decltype(head) slow = head, fast = head; 51 | while (nullptr != fast and nullptr != fast->next) { 52 | slow = slow->next; 53 | fast = fast->next->next; 54 | if (slow == fast) { 55 | return true; 56 | } 57 | } 58 | return false; 59 | } 60 | 61 | template 62 | typename Node::ptr_t merge_two_sorted_lists(typename Node::ptr_t lhs, 63 | typename Node::ptr_t rhs) { 64 | if (nullptr == lhs) { return rhs; } 65 | if (nullptr == rhs) { return lhs; } 66 | 67 | decltype(lhs) l = lhs, r = rhs, head = nullptr, work = nullptr; 68 | 69 | if (l->data < r->data) { 70 | head = l; 71 | l = l->next; 72 | } else { 73 | head = r; 74 | r = r->next; 75 | } 76 | work = head; 77 | 78 | while (nullptr != l and nullptr != r) { 79 | if (l->data < r->data) { 80 | work->next = l; 81 | l = l->next; 82 | } else { 83 | work->next = r; 84 | r = r->next; 85 | } 86 | work = work->next; 87 | } 88 | 89 | if (nullptr != l) { 90 | work->next = l; 91 | } else { 92 | work->next = r; 93 | } 94 | 95 | return head; 96 | } 97 | 98 | template 99 | typename Node::ptr_t deleth_last_Kth(typename Node::ptr_t head, 100 | size_t n) { 101 | decltype(head) sentry = std::make_shared>(); 102 | sentry->next = head; 103 | decltype(head) prev = sentry, curr = sentry->next, fast = sentry->next; 104 | for (size_t i = 0; i != n; ++i) { 105 | if (nullptr != fast) { 106 | fast = fast->next; 107 | } else { 108 | return sentry->next; 109 | } 110 | } 111 | while (nullptr != fast) { 112 | prev = curr; 113 | curr = curr->next; 114 | fast = fast->next; 115 | } 116 | prev->next = curr->next; 117 | return sentry->next; 118 | } 119 | 120 | template 121 | typename Node::ptr_t find_middle_node(typename Node::ptr_t head) { 122 | if (nullptr == head or nullptr == head->next) { 123 | return head; 124 | } 125 | decltype(head) slow = head, fast = head; 126 | while (nullptr != fast and nullptr != fast->next) { 127 | slow = slow->next; 128 | fast = fast->next->next; 129 | if (slow == fast) { 130 | return nullptr; 131 | } 132 | } 133 | return slow; 134 | } 135 | 136 | #endif // LINKEDLIST_LINKED_LIST_ALGO_HPP_ 137 | -------------------------------------------------------------------------------- /c-cpp/07_linkedlist/linklist_jinshaohui.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: lisklist.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-07 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | 10 | 11 | struct stlistNode 12 | { 13 | int val; 14 | struct listNode *next; 15 | }listNode; 16 | 17 | /*反转链表*/ 18 | listNode reverseList(listNode *head) 19 | { 20 | listNode *prev = NULL; 21 | listNode *next = NULL; 22 | 23 | while(head != NULL) 24 | { 25 | next = head->next; 26 | head->next = prev; 27 | prev = head; 28 | head = next; 29 | } 30 | 31 | return prev; 32 | } 33 | 34 | /*判断链表是否有环*/ 35 | int hasCycle(listNode *head) 36 | { 37 | listNode * fast = head; 38 | listNode * low = head; 39 | 40 | while(fast != NULL && fast->next != NULL) 41 | { 42 | low = low->next; 43 | fast = fast->next->next; 44 | if (low == fast) 45 | { 46 | return 1; 47 | } 48 | } 49 | 50 | return 0; 51 | } 52 | /*合并有序链表*/ 53 | listNode *mergeTwoLists(listNode *l1,listNode *l2) 54 | { 55 | listNode head = {0}; 56 | listNode *pRes = &head; 57 | 58 | while(1) 59 | { 60 | if(l1 == NULL) 61 | { 62 | pRes->next = l2; 63 | } 64 | 65 | if (l2 == NULL) 66 | { 67 | pRes->next = l1; 68 | } 69 | 70 | if(l1->val < l2->val) 71 | { 72 | pRes->next = l1; 73 | l1 = l1->next; 74 | } 75 | else 76 | { 77 | pRes->next = l2; 78 | l2 = l2->next; 79 | } 80 | pRes = pRes->next; 81 | } 82 | 83 | return head; 84 | } 85 | /* 86 | *删除链表倒数第n个节点,并返回链表头节点 */ 87 | 88 | listNode * removeNthFromEnd(listNode*headi,int n) 89 | { 90 | listNode *fast = head; 91 | listNode *prev = NULL; 92 | listNpde *next = head; 93 | int k = n; 94 | 95 | /*快指针往后移动k-1*/ 96 | while((k > 1) && (fast != NULL)) 97 | { 98 | fast = fast->next; 99 | k--; 100 | } 101 | 102 | /*说明链表数目不足n个*/ 103 | if (fast == NULL) 104 | { 105 | return head; 106 | } 107 | 108 | while (fast->next != NULL) 109 | { 110 | fast = fast->next; 111 | prev = next; 112 | next = next->next; 113 | } 114 | 115 | if(prev == NULL) 116 | { 117 | head = head->next; 118 | } 119 | else 120 | { 121 | prev->next = prev->next->next; 122 | } 123 | 124 | return head; 125 | } 126 | /*求链表的中间节点*/ 127 | listNode *middleNode(listNode *head) 128 | { 129 | listNode * fast = head; 130 | listNode * low = head; 131 | 132 | while(fast != NULL && fast->next != NULL) 133 | { 134 | low = low->next; 135 | fast = fast->next->next; 136 | } 137 | 138 | return low; 139 | } 140 | -------------------------------------------------------------------------------- /c-cpp/08_stack/StackBasedOnArray/StackBasedOnArray.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 1)顺序栈的操作:入栈和出栈; 3 | * 2)采用模板的方法实现存储任意类型的数据 4 | * 3)采用数组的栈,支持动态扩容,每次扩容1.5 倍,初始栈的大小是 10 。 5 | * 6 | * Author:caozx 7 | * time ;2018年10月11日 8 | */ 9 | 10 | #include 11 | #include "StackBasedOnArray.h" 12 | using namespace std; 13 | 14 | //构造函数,创建栈 15 | //类模板成员函数的写法 template 返回值类型 类名::成员函数名(参数列表){} 16 | template ArrayStack::ArrayStack() 17 | { 18 | this -> count = 10; 19 | this -> flag = 0; 20 | this -> array = new T[this -> count]; 21 | if (! this -> array){ 22 | cout << "array malloc memory failure" << endl; 23 | } 24 | } 25 | 26 | 27 | //有参构造函数,创建栈 28 | template ArrayStack::ArrayStack(int count) 29 | { 30 | this -> count = count; 31 | this -> flag = 0; 32 | this -> array = new T[this -> count]; 33 | if (! this -> array){ 34 | cout << "array malloc memory failure" << endl; 35 | } 36 | } 37 | 38 | //析构函数,销毁栈 39 | template ArrayStack::~ArrayStack(){ 40 | this -> count = 0; 41 | this -> flag = 0; 42 | if(this -> array){ 43 | delete [] this -> array; 44 | this -> array = NULL; 45 | } 46 | 47 | } 48 | 49 | // 入栈 50 | template void ArrayStack::push(T data){ 51 | if(this -> flag == this -> count){ 52 | cout << "The stack is full , so need to enlarge 1.5x! "<< endl; 53 | this -> count = int (1.5 * this -> count); 54 | T * temp = new T [this -> count]; 55 | for(int i = 0; i < this -> flag ; i++){ 56 | temp[i] = this -> array[i]; 57 | //cout << temp[i] < array; //释放原来的空间 60 | temp[this -> flag] = data; 61 | this -> flag ++; 62 | this -> array = temp; 63 | } 64 | else{ 65 | this -> array [this -> flag] = data; 66 | this -> flag ++ ; 67 | } 68 | } 69 | 70 | //出栈,并删除栈顶元素 71 | template T ArrayStack::pop(){ 72 | this -> flag --; 73 | T temp = this -> array[this -> flag]; 74 | return temp; 75 | } 76 | 77 | //出栈,不删除栈顶元素 78 | template T ArrayStack::peek(){ 79 | T temp = this -> array[this -> flag - 1]; 80 | return temp; 81 | } 82 | 83 | template int ArrayStack::stackSize(){ 84 | return this -> flag; 85 | } 86 | 87 | template int ArrayStack::stackMaxSize(){ 88 | return this -> count; 89 | } 90 | 91 | int main(int argc, char const *argv[]) 92 | { 93 | cout << " === test begin ===" << endl; 94 | ArrayStack arrstack(12); 95 | arrstack.push(10); 96 | arrstack.push(20); 97 | arrstack.push(30); 98 | arrstack.push(40); 99 | arrstack.push(50); 100 | arrstack.push(60); 101 | arrstack.push(70); 102 | arrstack.push(80); 103 | arrstack.push(90); 104 | arrstack.push(100); 105 | arrstack.push(110); 106 | arrstack.push(120); 107 | arrstack.push(130); 108 | arrstack.push(140); 109 | arrstack.push(150); 110 | 111 | cout << "peek , not delete " << arrstack.peek() << endl; 112 | cout << "pop , delete " << arrstack.pop()< class 类名{} 4 | template class ArrayStack 5 | { 6 | public: 7 | ArrayStack(); 8 | ArrayStack(int count); 9 | ~ArrayStack(); 10 | void push(T data); //入栈 11 | T pop(); //出栈,并删除栈顶元素 12 | T peek(); //返回栈顶元素,不删除栈顶元素,栈顶指针不变 13 | int stackSize(); 14 | int stackMaxSize(); 15 | 16 | private: 17 | int flag; //栈顶标签,指向栈顶 18 | int count ; //栈的容量 19 | T *array; //指针 20 | }; 21 | -------------------------------------------------------------------------------- /c-cpp/08_stack/StackBasedOnLinkedList/StackBasedOnLinkedList.h: -------------------------------------------------------------------------------- 1 | // 类模板的声明,关键字 class 也可以更换成 typename 2 | template class LinkedListStack 3 | { 4 | public: 5 | LinkedListStack(); 6 | ~LinkedListStack(); 7 | 8 | void push(const T & data); //入栈 9 | T peek(); //返回栈顶元素,即出栈,不删除栈顶元素 10 | T pop(); //出栈,删除栈顶元素 11 | int size() const; //返回栈的大小 12 | private: 13 | int count; //存放栈的大小,因为是单链表所以这里不规定栈的最大可承载量 14 | struct LinkedNode 15 | { 16 | T data; 17 | LinkedNode * next; 18 | }; 19 | LinkedNode * head; // 单链表的头指针,不带头节点 20 | }; 21 | -------------------------------------------------------------------------------- /c-cpp/08_stack/arrayStack/arrayStack.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: arrayStack.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-12 6 | > Desc: 数组实现顺序栈 7 | ************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | #include"./arrayStack.h" 12 | 13 | /*创建并初始化顺序栈*/ 14 | stArrayStack * arrayStack_create(int size) 15 | { 16 | stArrayStack *parrStack = NULL; 17 | 18 | parrStack = (stArrayStack *)malloc(sizeof(stArrayStack)); 19 | if (parrStack == NULL) 20 | { 21 | return NULL; 22 | } 23 | 24 | parrStack->size = size; 25 | parrStack->pos = -1; 26 | parrStack->array = (int *)malloc(sizeof(int)*size); 27 | if(parrStack->array == NULL) 28 | { 29 | free(parrStack); 30 | return NULL; 31 | } 32 | 33 | return parrStack; 34 | } 35 | /*销毁顺序栈*/ 36 | void arrayStack_destory(stArrayStack * parrStack) 37 | { 38 | if(parrStack == NULL) 39 | { 40 | return; 41 | } 42 | 43 | if (parrStack->array != NULL) 44 | { 45 | free(parrStack->array); 46 | } 47 | 48 | free(parrStack); 49 | return; 50 | } 51 | /*出栈*/ 52 | int arrayStack_pop(stArrayStack *parrStack) 53 | { 54 | int data = 0; 55 | 56 | if(arrayStack_is_empty(parrStack)) 57 | { 58 | return -1; 59 | } 60 | data = parrStack->array[parrStack->pos]; 61 | parrStack->pos--; 62 | 63 | return data; 64 | } 65 | /*入栈*/ 66 | int arrayStack_push(stArrayStack *parrStack,int data) 67 | { 68 | if(arrayStack_is_full(parrStack)) 69 | { 70 | return -1; 71 | } 72 | 73 | parrStack->pos++; 74 | parrStack->array[parrStack->pos] = data; 75 | 76 | return 0; 77 | } 78 | 79 | int arrayStack_push_new(stArrayStack*parrStack,int data) 80 | { 81 | int *ptmp = NULL; 82 | 83 | /*如果栈不满,直接插入*/ 84 | if(!arrayStack_is_full(parrStack)) 85 | { 86 | return arrayStack_push(parrStack,data); 87 | } 88 | 89 | /*如果栈已经满,申请内存*/ 90 | ptmp = (int *)malloc(2*parrStack->size*sizeof(int)); 91 | if (ptmp == NULL) 92 | { 93 | return -1; 94 | } 95 | 96 | memcpy(ptmp,parrStack->array,parrStack->size*sizeof(int)); 97 | 98 | free(parrStack->array); 99 | 100 | parrStack->array = ptmp; 101 | parrStack->size = 2*parrStack->size; 102 | parrStack->pos++; 103 | parrStack->array[parrStack->pos] = data; 104 | 105 | return ; 106 | } 107 | 108 | void arrayStack_dump(stArrayStack *parrStack) 109 | { 110 | int i = 0; 111 | 112 | if (arrayStack_is_empty(parrStack)) 113 | { 114 | printf("\r\n arrayStack is empty."); 115 | return; 116 | } 117 | printf("\r\narrayStack size = %d,pos= %d,", 118 | parrStack->size,parrStack->pos); 119 | for(i = 0; i <= parrStack->pos; i++) 120 | { 121 | printf("\r\narry[%d] = %d",i,parrStack->array[i]); 122 | } 123 | } 124 | 125 | int main() 126 | { 127 | int i = 0; 128 | int ret = 0; 129 | stArrayStack * parrStack = NULL; 130 | 131 | printf("\r\n create size = 4 arrayStack."); 132 | 133 | parrStack = arrayStack_create(4); 134 | if (parrStack == NULL) 135 | { 136 | printf("\r\n create size = 4 arrayStack faided."); 137 | return 0; 138 | } 139 | 140 | for (i = 0; i < 5; i++) 141 | { 142 | ret = arrayStack_push(parrStack,i); 143 | if(ret != 0) 144 | { 145 | printf("\r\n push size = %d arrayStack faided.",i); 146 | 147 | } 148 | } 149 | arrayStack_dump(parrStack); 150 | 151 | ret = arrayStack_push_new(parrStack,4); 152 | if(ret != 0) 153 | { 154 | printf("\r\n push size = %d arrayStack faided.",4); 155 | } 156 | arrayStack_dump(parrStack); 157 | 158 | arrayStack_destory(parrStack); 159 | 160 | return; 161 | } 162 | -------------------------------------------------------------------------------- /c-cpp/08_stack/arrayStack/arrayStack.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: arrayStack.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-12 6 | > Desc: 7 | ************************************************************************/ 8 | 9 | #ifndef ARRAY_STACJ_H 10 | #define ARRAY_STACJ_H 11 | 12 | typedef struct _array_stack 13 | { 14 | int size;/*栈的大小*/ 15 | int pos;/*当前存储元素的个数,即栈顶元素下表*/ 16 | int *array;/*数据存储区*/ 17 | }stArrayStack; 18 | 19 | #define arrayStack_size(arrayStack) (arrayStack->size) 20 | #define arrayStack_is_empty(arrayStack) (arrayStack->pos == -1) 21 | #define arrayStack_is_full(arrayStack) (arrayStack->pos == (arrayStack->size-1)) 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /c-cpp/08_stack/linkList/linklist_stack.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: linklist_stack.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-12 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | #include "./linklist_stack.h" 12 | 13 | linklist_stack * stack_create() 14 | { 15 | linklist_stack * stack = NULL; 16 | 17 | stack = (linklist_stack *)malloc(sizeof(linklist_stack)); 18 | if (stack == NULL) 19 | { 20 | return NULL; 21 | } 22 | 23 | stack->next = NULL; 24 | 25 | return stack; 26 | } 27 | 28 | void stack_destory(linklist_stack* stack) 29 | { 30 | linklist_stack * ptmp = NULL; 31 | 32 | while(!stack_is_empty(stack)) 33 | { 34 | ptmp = stack->next; 35 | stack->next = stack->next->next; 36 | 37 | free(ptmp); 38 | } 39 | 40 | free(stack); 41 | 42 | return; 43 | } 44 | 45 | int stack_push(linklist_stack *stack,int data) 46 | { 47 | linklist_stack * ptmp = NULL; 48 | 49 | ptmp = (linklist_stack *)malloc(sizeof(linklist_stack)); 50 | if (ptmp == NULL) 51 | { 52 | return -1; 53 | } 54 | 55 | ptmp->data = data; 56 | ptmp->next = stack->next; 57 | stack->next = ptmp; 58 | 59 | return 0; 60 | } 61 | 62 | int stack_pop(linklist_stack*stack,int *data) 63 | { 64 | linklist_stack *ptmp = NULL; 65 | if (data == NULL) 66 | { 67 | return -1; 68 | } 69 | if(stack_is_empty(stack)) 70 | { 71 | return -1; 72 | } 73 | *data = stack->next->data; 74 | ptmp = stack->next; 75 | stack->next = ptmp->next; 76 | free(ptmp); 77 | 78 | return 0; 79 | } 80 | 81 | 82 | void stack_dump(linklist_stack *stack) 83 | { 84 | linklist_stack * ptmp = stack->next; 85 | 86 | while(ptmp != NULL) 87 | { 88 | printf("\r\n data = %d",ptmp->data); 89 | ptmp = ptmp->next; 90 | } 91 | return; 92 | } 93 | 94 | int main() 95 | { 96 | int i = 0; 97 | int ret = 0; 98 | int data = 0; 99 | linklist_stack * stack = NULL; 100 | 101 | stack = stack_create(); 102 | if (stack == NULL) 103 | { 104 | printf("\r\n stack create falied."); 105 | return 0; 106 | } 107 | 108 | for (i = 0; i < 4; i++) 109 | { 110 | ret = stack_push(stack,i); 111 | if(ret != 0) 112 | { 113 | printf("\r\n stack push %d falied.",i); 114 | } 115 | } 116 | 117 | stack_dump(stack); 118 | 119 | for (i = 0; i < 5; i++) 120 | { 121 | ret = stack_pop(stack,&data); 122 | if(ret != 0) 123 | { 124 | printf("\r\n stack pop%d falied.", i); 125 | } 126 | else 127 | { 128 | printf("\r\n data = %d,",data); 129 | } 130 | } 131 | 132 | stack_destory(stack); 133 | 134 | return 0; 135 | 136 | } 137 | -------------------------------------------------------------------------------- /c-cpp/08_stack/linkList/linklist_stack.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: linklist_stack.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-12 6 | > Desc: 7 | ************************************************************************/ 8 | 9 | #ifndef STACK_LINK_LIST_H 10 | #define STACK_LINK_LIST_H 11 | 12 | typedef struct _linkliststack 13 | { 14 | int data; 15 | struct _linkliststack *next; 16 | }linklist_stack; 17 | 18 | 19 | #define stack_is_empty(liststack) (liststack->next == NULL) 20 | 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /c-cpp/08_stack/linked_list.h: -------------------------------------------------------------------------------- 1 | /** 2 | * C++ 版本单链表结点 3 | * 4 | * Author: Liam Huang (Liam0205) 5 | */ 6 | 7 | #ifndef STACK_LINKED_LIST_H_ 8 | #define STACK_LINKED_LIST_H_ 9 | 10 | #include 11 | 12 | template 13 | struct Node { 14 | using ptr_t = std::shared_ptr>; 15 | T data; 16 | ptr_t next; 17 | 18 | Node(T data_) : data(data_), next(nullptr) {} 19 | Node() : next(nullptr) {} 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /c-cpp/08_stack/stack_based_on_linked_list.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 基于链表实现的栈。 3 | * 4 | * Author: Liam Huang (Liam0205) 5 | */ 6 | 7 | #ifndef STACK_STACK_BASED_ON_LINKED_LIST_HPP_ 8 | #define STACK_STACK_BASED_ON_LINKED_LIST_HPP_ 9 | 10 | #include 11 | #include "linked_list.h" 12 | 13 | template 14 | class Stack { 15 | public: 16 | using value_type = T; 17 | using node_type = typename Node::ptr_t; 18 | 19 | private: 20 | node_type top_ = nullptr; 21 | 22 | public: 23 | bool empty(void) const { 24 | return nullptr == top_; 25 | } 26 | void push(const value_type& value) { 27 | auto node = std::make_shared(value); 28 | if (this->empty()) { 29 | top_ = node; 30 | } else { 31 | node->next = top_; 32 | top_ = node; 33 | } 34 | } 35 | value_type top(void) const { 36 | if (not this->empty()) { 37 | return top_->data; 38 | } else { 39 | throw "Fetch data from empty stack!"; 40 | } 41 | } 42 | void pop(void) { 43 | if (not this->empty()) { 44 | top_ = top_->next; 45 | return; 46 | } else { 47 | throw "Pop from empty stack!"; 48 | } 49 | } 50 | }; 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /c-cpp/09_queue/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/09_queue/.gitkeep -------------------------------------------------------------------------------- /c-cpp/09_queue/array_queue.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/10. 3 | */ 4 | 5 | #ifndef QUEUE_ARRAY_QUEUE_HPP_ 6 | #define QUEUE_ARRAY_QUEUE_HPP_ 7 | 8 | template 9 | class ArrayQueue { 10 | private: 11 | T* items_ = nullptr; 12 | size_t capacity_ = 0; 13 | size_t head_ = 0; 14 | size_t tail_ = 0; 15 | 16 | public: 17 | ArrayQueue() = delete; 18 | ArrayQueue(const size_t capacity) : capacity_(capacity) { 19 | items_ = new T[capacity_]; 20 | } 21 | ~ArrayQueue() { 22 | if (nullptr != items_) { 23 | delete[] items_; 24 | items_ = nullptr; 25 | } 26 | } 27 | ArrayQueue(const ArrayQueue& other) : capacity_(other.capacity_) { 28 | items_ = new T[capacity_]; 29 | for (size_t i = other.head_; i != other.tail_; ++i) { 30 | enqueue(other.items_[i]); 31 | } 32 | } 33 | ArrayQueue& operator=(const ArrayQueue& rhs) { 34 | delete[] items_; 35 | head_ = 0; 36 | tail_ = 0; 37 | capacity_ = rhs.capacity_; 38 | items_ = new T[capacity_]; 39 | for (size_t i = rhs.head_; i != rhs.tail_; ++i) { 40 | enqueue(rhs.items_[i]); 41 | } 42 | return *this; 43 | } 44 | ArrayQueue(ArrayQueue&& other) : items_(other.items_), 45 | capacity_(other.capacity_), 46 | head_(other.head_), 47 | tail_(other.tail_) { 48 | other.items_ = nullptr; 49 | other.capacity_ = 0; 50 | other.head_ = 0; 51 | other.tail_ = 0; 52 | } 53 | ArrayQueue& operator=(ArrayQueue&& rhs) { 54 | delete[] items_; 55 | items_ = rhs.items_; 56 | capacity_ = rhs.capacity_; 57 | head_ = rhs.head_; 58 | tail_ = rhs.tail_; 59 | rhs.items_ = nullptr; 60 | rhs.capacity_ = 0; 61 | rhs.head_ = 0; 62 | rhs.tail_ = 0; 63 | return *this; 64 | } 65 | 66 | public: 67 | void enqueue(T item) { 68 | if (capacity_ == tail_) { 69 | throw "Push data into a full queue!"; 70 | } 71 | items_[tail_++] = item; 72 | } 73 | T head() const { 74 | if (head_ != tail_) { 75 | return items_[head_]; 76 | } else { 77 | throw "Fetch data from an empty queue!"; 78 | } 79 | } 80 | void dequeue() { 81 | if (head_ != tail_) { 82 | ++head_; 83 | } else { 84 | throw "Pop data from an empty queue!"; 85 | } 86 | } 87 | 88 | public: 89 | template 90 | void traverse(UnaryFunc do_traverse) { 91 | for (size_t i = head_; i != tail_; ++i) { 92 | do_traverse(items_[i]); 93 | } 94 | } 95 | }; 96 | 97 | #endif // QUEUE_ARRAY_QUEUE_HPP_ 98 | -------------------------------------------------------------------------------- /c-cpp/09_queue/array_queue/array_queue.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: array_queue.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-12 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | #include"./array_queue.h" 12 | 13 | 14 | array_queue * array_queue_create(int size) 15 | { 16 | array_queue * queue = NULL; 17 | 18 | queue = (array_queue*)malloc(sizeof(array_queue)); 19 | if (queue == NULL) 20 | { 21 | return NULL; 22 | } 23 | queue->array = (int *)malloc(sizeof(int)*size); 24 | if (queue->array == NULL) 25 | { 26 | free(queue); 27 | return NULL; 28 | } 29 | queue->size = size; 30 | queue->num = 0; 31 | queue->head = 0; 32 | queue->tail = 0; 33 | 34 | return queue; 35 | } 36 | 37 | void array_queue_destory(array_queue *queue) 38 | { 39 | if (queue == NULL) 40 | { 41 | return; 42 | } 43 | 44 | if (queue->array != NULL) 45 | { 46 | free(queue->array); 47 | } 48 | 49 | free(queue); 50 | return; 51 | } 52 | 53 | /*入队列 */ 54 | int array_queue_enqueue(array_queue *queue,int data) 55 | { 56 | /*队列为空,或者队列满时,返回-1*/ 57 | if ((queue == NULL) || (array_queue_is_full(queue))) 58 | { 59 | return -1; 60 | } 61 | 62 | queue->num++; 63 | queue->array[queue->tail] = data; 64 | queue->tail = (queue->tail + 1) % queue->size; 65 | 66 | return 0; 67 | } 68 | 69 | /*出队列*/ 70 | int array_queue_dequeue(array_queue * queue,int *data) 71 | { 72 | /*队列为空,数据存储为空,队列为空时返回-1*/ 73 | if ((queue == NULL) || (data == NULL) || (array_queue_is_empty(queue))) 74 | { 75 | return -1; 76 | } 77 | *data = queue->array[queue->head]; 78 | queue->num--; 79 | queue->head = (queue->head + 1) % queue->size; 80 | 81 | return 0; 82 | } 83 | 84 | void array_queue_dump(array_queue *queue) 85 | { 86 | int i = 0; 87 | int pos = 0; 88 | 89 | if ((queue == NULL) || (array_queue_is_empty(queue))) 90 | { 91 | printf("\r\n queue is empty"); 92 | return; 93 | } 94 | 95 | printf("\r\n size:%d,num:%d,head:%d,tali:%d", 96 | queue->size,queue->num,queue->head,queue->tail); 97 | for (i = 0; i < queue->num; i ++) 98 | { 99 | pos = (queue->head + i) %queue->size; 100 | printf("\r\n array[%d] = %d",pos,queue->array[pos]); 101 | } 102 | return; 103 | } 104 | 105 | int main() 106 | { 107 | int i = 0; 108 | int ret = 0; 109 | int data = 0; 110 | array_queue * queue = NULL; 111 | 112 | queue = array_queue_create(4); 113 | if (queue == NULL) 114 | { 115 | printf("\r\n queue is create failed."); 116 | return 0; 117 | } 118 | /*队列时空时,出队返回错误*/ 119 | ret = array_queue_dequeue(queue, &data); 120 | if (ret != 0) 121 | { 122 | printf("\r\n queue %d dequeue failed.",ret); 123 | } 124 | 125 | /*队列大小是4,入队5个,最后一个报错*/ 126 | for (i = 0; i < 5; i++) 127 | { 128 | ret = array_queue_enqueue(queue,i); 129 | if (ret != 0) 130 | { 131 | printf("\r\n queue %d enqueue failed.",i); 132 | 133 | } 134 | } 135 | 136 | array_queue_dump(queue); 137 | 138 | ret = array_queue_dequeue(queue, &data); 139 | if (ret != 0) 140 | { 141 | printf("\r\n queue %d dequeue failed.",i); 142 | } 143 | printf("\r\n queue %d dequue.",data); 144 | array_queue_dump(queue); 145 | data = 5; 146 | printf("\r\n queue %d enqueue.",data); 147 | ret = array_queue_enqueue(queue,data); 148 | if (ret != 0) 149 | { 150 | printf("\r\n queue %d enqueue failed.",data); 151 | } 152 | array_queue_dump(queue); 153 | 154 | array_queue_destory(queue); 155 | return 0; 156 | 157 | } 158 | 159 | -------------------------------------------------------------------------------- /c-cpp/09_queue/array_queue/array_queue.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: array_queue.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-12 6 | > Desc: 7 | ************************************************************************/ 8 | #ifndef ARRAY_QUEUE_H 9 | #define ARRAY_QUEUE_H 10 | 11 | typedef struct _array_queue 12 | { 13 | int size;/*队列的大小*/ 14 | int num; /*当前存储数据的大小*/ 15 | int head;/*队列的头*/ 16 | int tail;/*队列的尾*/ 17 | int *array;/*数据存储区*/ 18 | }array_queue; 19 | 20 | #define array_queue_is_empty(array_queue) (array_queue->num == 0) 21 | #define array_queue_is_full(array_queue) ((array_queue->num) == (array_queue->size)) 22 | 23 | #endif 24 | 25 | -------------------------------------------------------------------------------- /c-cpp/09_queue/array_queue_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "array_queue.hpp" 3 | 4 | int main() { 5 | auto do_traverse = [&](auto item){ std::cout << item << ' '; }; 6 | 7 | ArrayQueue array_queue_1(3); 8 | array_queue_1.enqueue(1); 9 | array_queue_1.enqueue(2); 10 | array_queue_1.enqueue(3); 11 | // array_queue_1.enqueue(4); // throw 12 | array_queue_1.traverse(do_traverse); 13 | std::cout << std::endl; 14 | 15 | ArrayQueue array_queue_2(array_queue_1); // copy constructor 16 | array_queue_2.traverse(do_traverse); 17 | std::cout << std::endl; 18 | 19 | ArrayQueue array_queue_3(std::move(array_queue_2)); // move constructor 20 | array_queue_3.traverse(do_traverse); 21 | std::cout << std::endl; 22 | array_queue_2.traverse(do_traverse); 23 | std::cout << std::endl; 24 | 25 | std::cout << array_queue_3.head() << std::endl; 26 | array_queue_3.dequeue(); 27 | std::cout << array_queue_3.head() << std::endl; 28 | array_queue_3.dequeue(); 29 | std::cout << array_queue_3.head() << std::endl; 30 | array_queue_3.dequeue(); 31 | // std::cout << array_queue_3.head() << std::endl; // throw 32 | // array_queue_3.dequeue(); // throw 33 | 34 | ArrayQueue array_queue_4(1); 35 | array_queue_4 = array_queue_1; // copy assignment 36 | array_queue_4.traverse(do_traverse); 37 | std::cout << std::endl; 38 | 39 | ArrayQueue array_queue_5(100); 40 | array_queue_5 = std::move(array_queue_4); // move assignment 41 | array_queue_5.traverse(do_traverse); 42 | std::cout << std::endl; 43 | array_queue_4.traverse(do_traverse); 44 | std::cout << std::endl; 45 | 46 | std::cout << array_queue_5.head() << std::endl; 47 | array_queue_5.dequeue(); 48 | std::cout << array_queue_5.head() << std::endl; 49 | array_queue_5.dequeue(); 50 | std::cout << array_queue_5.head() << std::endl; 51 | array_queue_5.dequeue(); 52 | // std::cout << array_queue_5.head() << std::endl; // throw 53 | // array_queue_5.dequeue(); // throw 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /c-cpp/09_queue/block_queue.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/11. 3 | */ 4 | 5 | #ifndef QUEUE_BLOCK_QUEUE_HPP_ 6 | #define QUEUE_BLOCK_QUEUE_HPP_ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | template 13 | class BlockQueue { 14 | public: 15 | using value_type = T; 16 | using container_type = std::queue; 17 | using size_type = typename container_type::size_type; 18 | 19 | private: 20 | size_type capacity_ = 0; 21 | container_type container_; 22 | mutable std::mutex mutex_; 23 | mutable std::condition_variable not_empty_; 24 | mutable std::condition_variable not_full_; 25 | 26 | public: 27 | BlockQueue() = delete; 28 | BlockQueue(const size_type capacity) : capacity_(capacity) {} 29 | BlockQueue(const BlockQueue&) = default; 30 | BlockQueue(BlockQueue&&) = default; 31 | BlockQueue& operator=(const BlockQueue&) = default; 32 | BlockQueue& operator=(BlockQueue&&) = default; 33 | 34 | private: 35 | bool empty() const { return container_.empty(); } 36 | bool full() const { return not(container_.size() < capacity_); } 37 | 38 | public: 39 | void put(const value_type& item) { 40 | std::unqiue_lock lock(mutex_); 41 | while (full()) { 42 | not_full_.wait(lock); 43 | } 44 | container_.push(item); 45 | not_empty_.notify_one(); 46 | } 47 | void take(value_type& out) { 48 | std::unique_lock lock(mutex_); 49 | while (empty()) { 50 | not_empty_.wait(lock); 51 | } 52 | out = container_.front(); 53 | container_.pop(); 54 | not_full_.notify_one(); 55 | } 56 | template 57 | bool put_for(const value_type& item, const Duration& d) { 58 | std::unqiue_lock lock(mutex_); 59 | if (not_full_.wait_for(lock, d, [&](){ return not full(); })) { 60 | container_.push(item); 61 | not_empty_.notify_one(); 62 | return true; 63 | } else { 64 | return false; 65 | } 66 | } 67 | template 68 | bool take_for(const Duration& d, value_type& out) { 69 | std::unique_lock lock(mutex_); 70 | if (not_empty_.wait_for(lock, d, [&](){ return not empty(); })) { 71 | out = container_.front(); 72 | container_.pop(); 73 | not_full_.notify_one(); 74 | return true; 75 | } else { 76 | return false; 77 | } 78 | } 79 | }; 80 | 81 | #endif // QUEUE_BLOCK_QUEUE_HPP_ 82 | 83 | -------------------------------------------------------------------------------- /c-cpp/09_queue/circular_queue.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/10. 3 | */ 4 | 5 | #ifndef QUEUE_CIRCULAR_QUEUE_HPP_ 6 | #define QUEUE_CIRCULAR_QUEUE_HPP_ 7 | 8 | template 9 | class CircularQueue { 10 | private: 11 | T* items_ = nullptr; 12 | size_t capacity_ = 0; 13 | size_t head_ = 0; 14 | size_t tail_ = 0; 15 | 16 | public: 17 | CircularQueue() = delete; 18 | CircularQueue(const size_t capacity) : capacity_(capacity) { 19 | items_ = new T[capacity_]; 20 | } 21 | ~CircularQueue() { 22 | if (nullptr != items_) { 23 | delete[] items_; 24 | items_ = nullptr; 25 | } 26 | } 27 | CircularQueue(const CircularQueue& other) : capacity_(other.capacity_) { 28 | items_ = new T[capacity_]; 29 | for (size_t i = other.head_; i != other.tail_; ++i) { 30 | enqueue(other.items_[i]); 31 | } 32 | } 33 | CircularQueue& operator=(const CircularQueue& rhs) { 34 | delete[] items_; 35 | head_ = 0; 36 | tail_ = 0; 37 | capacity_ = rhs.capacity_; 38 | items_ = new T[capacity_]; 39 | for (size_t i = rhs.head_; i != rhs.tail_; ++i) { 40 | enqueue(rhs.items_[i]); 41 | } 42 | return *this; 43 | } 44 | CircularQueue(CircularQueue&& other) : items_(other.items_), 45 | capacity_(other.capacity_), 46 | head_(other.head_), 47 | tail_(other.tail_) { 48 | other.items_ = nullptr; 49 | other.capacity_ = 0; 50 | other.head_ = 0; 51 | other.tail_ = 0; 52 | } 53 | CircularQueue& operator=(CircularQueue&& rhs) { 54 | delete[] items_; 55 | items_ = rhs.items_; 56 | capacity_ = rhs.capacity_; 57 | head_ = rhs.head_; 58 | tail_ = rhs.tail_; 59 | rhs.items_ = nullptr; 60 | rhs.capacity_ = 0; 61 | rhs.head_ = 0; 62 | rhs.tail_ = 0; 63 | return *this; 64 | } 65 | 66 | public: 67 | void enqueue(T item) { 68 | if ((tail_ + 1) % capacity_ == head_) { 69 | throw "Push data into a full queue!"; 70 | } 71 | items_[tail_] = item; 72 | tail_ = (tail_ + 1) % capacity_; 73 | } 74 | T head() const { 75 | if (head_ != tail_) { 76 | return items_[head_]; 77 | } else { 78 | throw "Fetch data from an empty queue!"; 79 | } 80 | } 81 | void dequeue() { 82 | if (head_ != tail_) { 83 | head_ = (head_ + 1) % capacity_; 84 | } else { 85 | throw "Pop data from an empty queue!"; 86 | } 87 | } 88 | 89 | public: 90 | template 91 | void traverse(UnaryFunc do_traverse) { 92 | if (0 == capacity_) return; 93 | for (size_t i = head_; i % capacity_ != tail_; ++i) { 94 | do_traverse(items_[i % capacity_]); 95 | } 96 | } 97 | }; 98 | 99 | #endif // QUEUE_CIRCULAR_QUEUE_HPP_ 100 | -------------------------------------------------------------------------------- /c-cpp/09_queue/circular_queue_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "circular_queue.hpp" 3 | 4 | int main() { 5 | auto do_traverse = [&](auto item){ std::cout << item << ' '; }; 6 | 7 | CircularQueue circular_queue_1(4); 8 | circular_queue_1.enqueue(1); 9 | circular_queue_1.enqueue(2); 10 | circular_queue_1.enqueue(3); 11 | // circular_queue_1.enqueue(4); // throw 12 | circular_queue_1.traverse(do_traverse); 13 | std::cout << std::endl; 14 | 15 | CircularQueue circular_queue_2(circular_queue_1); // copy constructor 16 | circular_queue_2.traverse(do_traverse); 17 | std::cout << std::endl; 18 | 19 | CircularQueue circular_queue_3(std::move(circular_queue_2)); // move constructor 20 | circular_queue_3.traverse(do_traverse); 21 | std::cout << std::endl; 22 | circular_queue_2.traverse(do_traverse); 23 | std::cout << std::endl; 24 | 25 | std::cout << circular_queue_3.head() << std::endl; 26 | circular_queue_3.dequeue(); 27 | std::cout << circular_queue_3.head() << std::endl; 28 | circular_queue_3.dequeue(); 29 | std::cout << circular_queue_3.head() << std::endl; 30 | circular_queue_3.dequeue(); 31 | // std::cout << circular_queue_3.head() << std::endl; // throw 32 | // circular_queue_3.dequeue(); // throw 33 | 34 | CircularQueue circular_queue_4(1); 35 | circular_queue_4 = circular_queue_1; // copy assignment 36 | circular_queue_4.traverse(do_traverse); 37 | std::cout << std::endl; 38 | 39 | CircularQueue circular_queue_5(100); 40 | circular_queue_5 = std::move(circular_queue_4); // move assignment 41 | circular_queue_5.traverse(do_traverse); 42 | std::cout << std::endl; 43 | circular_queue_4.traverse(do_traverse); 44 | std::cout << std::endl; 45 | 46 | std::cout << circular_queue_5.head() << std::endl; 47 | circular_queue_5.dequeue(); 48 | std::cout << circular_queue_5.head() << std::endl; 49 | circular_queue_5.dequeue(); 50 | std::cout << circular_queue_5.head() << std::endl; 51 | circular_queue_5.dequeue(); 52 | // std::cout << circular_queue_5.head() << std::endl; // throw 53 | // circular_queue_5.dequeue(); // throw 54 | 55 | for (size_t i = 0; i != 4; ++i) { 56 | circular_queue_1.dequeue(); 57 | circular_queue_1.enqueue(i + 4); 58 | circular_queue_1.traverse(do_traverse); 59 | std::cout << std::endl; 60 | } 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /c-cpp/09_queue/concurrency_queue.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/11. 3 | */ 4 | 5 | #ifndef QUEUE_CONCURRENCY_QUEUE_HPP_ 6 | #define QUEUE_CONCURRENCY_QUEUE_HPP_ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | template 14 | class ConcurrencyQueue { 15 | public: 16 | using value_type = T; 17 | using container_type = std::queue; 18 | using size_type = typename container_type::size_type; 19 | 20 | private: 21 | container_type container_; 22 | mutable std::mutex mutex_; 23 | std::condition_variable container_cond_; 24 | 25 | public: 26 | ConcurrencyQueue() = default; 27 | ConcurrencyQueue(const ConcurrencyQueue&) = default; 28 | ConcurrencyQueue(ConcurrencyQueue&&) = default; 29 | ConcurrencyQueue& operator=(const ConcurrencyQueue&) = default; 30 | ConcurrencyQueue& operator=(ConcurrencyQueue&&) = default; 31 | 32 | private: 33 | bool empty_() const { return container_.empty(); } 34 | 35 | public: 36 | bool empty() const { 37 | std::lock_guard lg(mutex_); 38 | return container_.empty(); 39 | } 40 | void push(value_type item) { 41 | std::lock_guard lg(mutex_); 42 | container_.push(std::move(item)); 43 | container_cond_.notify_one(); 44 | } 45 | void wait_and_pop(value_type& out) { 46 | std::unique_lock lk(mutex_); 47 | while (empty_()) { 48 | container_cond_.wait(lk) 49 | } 50 | out = std::move(container_.front()); 51 | container_.pop(); 52 | } 53 | std::shared_ptr wait_and_pop() { 54 | std::unique_lock lk(mutex_); 55 | while (empty_()) { 56 | container_cond_.wait(lk) 57 | } 58 | auto res = std::make_shared(std::move(container_.front())); 59 | container_.pop(); 60 | return res; 61 | } 62 | bool try_pop(value_type& out) { 63 | std::lock_guard lg(mutex_); 64 | if (empty_()) { 65 | return false; 66 | } else { 67 | out = std::move(container_.front()); 68 | container_.pop(); 69 | return true; 70 | } 71 | } 72 | std::shared_ptr try_pop() { 73 | std::lock_guard lg(mutex_); 74 | if (empty_()) { 75 | return nullptr; 76 | } else { 77 | auto res = std::make_shared(std::move(container_.front())); 78 | container_.pop(); 79 | return res; 80 | } 81 | } 82 | }; 83 | 84 | #endif // QUEUE_CONCURRENCY_QUEUE_HPP_ 85 | 86 | -------------------------------------------------------------------------------- /c-cpp/09_queue/dynamic_array_queue.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/10. 3 | */ 4 | 5 | #ifndef QUEUE_DYNAMIC_ARRAY_QUEUE_HPP_ 6 | #define QUEUE_DYNAMIC_ARRAY_QUEUE_HPP_ 7 | 8 | template 9 | class DynamicArrayQueue { 10 | private: 11 | T* items_ = nullptr; 12 | size_t capacity_ = 0; 13 | size_t head_ = 0; 14 | size_t tail_ = 0; 15 | 16 | public: 17 | DynamicArrayQueue() = delete; 18 | DynamicArrayQueue(const size_t capacity) : capacity_(capacity) { 19 | items_ = new T[capacity_]; 20 | } 21 | ~DynamicArrayQueue() { 22 | if (nullptr != items_) { 23 | delete[] items_; 24 | items_ = nullptr; 25 | } 26 | } 27 | DynamicArrayQueue(const DynamicArrayQueue& other) : capacity_(other.capacity_) { 28 | items_ = new T[capacity_]; 29 | for (size_t i = other.head_; i != other.tail_; ++i) { 30 | enqueue(other.items_[i]); 31 | } 32 | } 33 | DynamicArrayQueue& operator=(const DynamicArrayQueue& rhs) { 34 | delete[] items_; 35 | head_ = 0; 36 | tail_ = 0; 37 | capacity_ = rhs.capacity_; 38 | items_ = new T[capacity_]; 39 | for (size_t i = rhs.head_; i != rhs.tail_; ++i) { 40 | enqueue(rhs.items_[i]); 41 | } 42 | return *this; 43 | } 44 | DynamicArrayQueue(DynamicArrayQueue&& other) : items_(other.items_), 45 | capacity_(other.capacity_), 46 | head_(other.head_), 47 | tail_(other.tail_) { 48 | other.items_ = nullptr; 49 | other.capacity_ = 0; 50 | other.head_ = 0; 51 | other.tail_ = 0; 52 | } 53 | DynamicArrayQueue& operator=(DynamicArrayQueue&& rhs) { 54 | delete[] items_; 55 | items_ = rhs.items_; 56 | capacity_ = rhs.capacity_; 57 | head_ = rhs.head_; 58 | tail_ = rhs.tail_; 59 | rhs.items_ = nullptr; 60 | rhs.capacity_ = 0; 61 | rhs.head_ = 0; 62 | rhs.tail_ = 0; 63 | return *this; 64 | } 65 | 66 | public: 67 | void enqueue(T item) { 68 | if (capacity_ == tail_ - head_) { 69 | throw "Push data into a full queue!"; 70 | } 71 | if (capacity_ == tail_) { 72 | // item transport 73 | for (size_t i = head_; i != tail_; ++i) { 74 | items_[i - head_] = items_[i]; 75 | } 76 | tail_ = tail_ - head_; 77 | head_ = 0; 78 | } 79 | items_[tail_++] = item; 80 | } 81 | T head() const { 82 | if (head_ != tail_) { 83 | return items_[head_]; 84 | } else { 85 | throw "Fetch data from an empty queue!"; 86 | } 87 | } 88 | void dequeue() { 89 | if (head_ != tail_) { 90 | ++head_; 91 | } else { 92 | throw "Pop data from an empty queue!"; 93 | } 94 | } 95 | 96 | public: 97 | template 98 | void traverse(UnaryFunc do_traverse) { 99 | for (size_t i = head_; i != tail_; ++i) { 100 | do_traverse(items_[i]); 101 | } 102 | } 103 | }; 104 | 105 | #endif // QUEUE_DYNAMIC_ARRAY_QUEUE_HPP_ 106 | -------------------------------------------------------------------------------- /c-cpp/09_queue/dynamic_array_queue_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dynamic_array_queue.hpp" 3 | 4 | int main() { 5 | auto do_traverse = [&](auto item){ std::cout << item << ' '; }; 6 | 7 | DynamicArrayQueue dynamic_array_queue_1(3); 8 | dynamic_array_queue_1.enqueue(1); 9 | dynamic_array_queue_1.enqueue(2); 10 | dynamic_array_queue_1.enqueue(3); 11 | // dynamic_array_queue_1.enqueue(4); // throw 12 | dynamic_array_queue_1.traverse(do_traverse); 13 | std::cout << std::endl; 14 | 15 | DynamicArrayQueue dynamic_array_queue_2(dynamic_array_queue_1); // copy constructor 16 | dynamic_array_queue_2.traverse(do_traverse); 17 | std::cout << std::endl; 18 | 19 | DynamicArrayQueue dynamic_array_queue_3(std::move(dynamic_array_queue_2)); // move constructor 20 | dynamic_array_queue_3.traverse(do_traverse); 21 | std::cout << std::endl; 22 | dynamic_array_queue_2.traverse(do_traverse); 23 | std::cout << std::endl; 24 | 25 | std::cout << dynamic_array_queue_3.head() << std::endl; 26 | dynamic_array_queue_3.dequeue(); 27 | std::cout << dynamic_array_queue_3.head() << std::endl; 28 | dynamic_array_queue_3.dequeue(); 29 | std::cout << dynamic_array_queue_3.head() << std::endl; 30 | dynamic_array_queue_3.dequeue(); 31 | // std::cout << dynamic_array_queue_3.head() << std::endl; // throw 32 | // dynamic_array_queue_3.dequeue(); // throw 33 | 34 | DynamicArrayQueue dynamic_array_queue_4(1); 35 | dynamic_array_queue_4 = dynamic_array_queue_1; // copy assignment 36 | dynamic_array_queue_4.traverse(do_traverse); 37 | std::cout << std::endl; 38 | 39 | DynamicArrayQueue dynamic_array_queue_5(100); 40 | dynamic_array_queue_5 = std::move(dynamic_array_queue_4); // move assignment 41 | dynamic_array_queue_5.traverse(do_traverse); 42 | std::cout << std::endl; 43 | dynamic_array_queue_4.traverse(do_traverse); 44 | std::cout << std::endl; 45 | 46 | std::cout << dynamic_array_queue_5.head() << std::endl; 47 | dynamic_array_queue_5.dequeue(); 48 | std::cout << dynamic_array_queue_5.head() << std::endl; 49 | dynamic_array_queue_5.dequeue(); 50 | std::cout << dynamic_array_queue_5.head() << std::endl; 51 | dynamic_array_queue_5.dequeue(); 52 | // std::cout << dynamic_array_queue_5.head() << std::endl; // throw 53 | // dynamic_array_queue_5.dequeue(); // throw 54 | 55 | for (size_t i = 0; i != 3; ++i) { 56 | dynamic_array_queue_1.dequeue(); 57 | dynamic_array_queue_1.enqueue(i + 4); 58 | dynamic_array_queue_1.traverse(do_traverse); 59 | std::cout << std::endl; 60 | } 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /c-cpp/09_queue/linked_queue.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/10. 3 | */ 4 | 5 | #ifndef QUEUE_LINKED_QUEUE_HPP_ 6 | #define QUEUE_LINKED_QUEUE_HPP_ 7 | 8 | #include 9 | 10 | template 11 | struct Node { 12 | using ptr_t = std::shared_ptr>; 13 | T data; 14 | ptr_t next; 15 | 16 | Node(T data_) : data(data_), next(nullptr) {} 17 | Node() : next(nullptr) {} 18 | }; 19 | 20 | template 21 | class LinkedQueue { 22 | public: 23 | using node_type = Node; 24 | using node_ptr_t = typename node_type::ptr_t; 25 | 26 | private: 27 | node_ptr_t head_ = nullptr; 28 | node_ptr_t before_tail_ = nullptr; 29 | 30 | public: 31 | LinkedQueue() = default; 32 | ~LinkedQueue() = default; 33 | LinkedQueue(const LinkedQueue& other) = default; 34 | LinkedQueue& operator=(const LinkedQueue& rhs) = default; 35 | LinkedQueue(LinkedQueue&& other) = default; 36 | LinkedQueue& operator=(LinkedQueue&& rhs) = default; 37 | 38 | public: 39 | void enqueue(T item) { 40 | if (nullptr == head_) { 41 | head_ = std::make_shared(item); 42 | before_tail_ = head_; 43 | } else { 44 | before_tail_->next = std::make_shared(item); 45 | before_tail_ = before_tail_->next; 46 | } 47 | } 48 | T head() const { 49 | if (nullptr != head_) { 50 | return head_->data; 51 | } else { 52 | throw "Fetch data from an empty queue!"; 53 | } 54 | } 55 | void dequeue() { 56 | if (nullptr != head_) { 57 | head_ = head_->next; 58 | if (nullptr == head_) { 59 | before_tail_ = nullptr; 60 | } 61 | } else { 62 | throw "Pop data from an empty queue!"; 63 | } 64 | } 65 | 66 | public: 67 | template 68 | void traverse(UnaryFunc do_traverse) { 69 | for (node_ptr_t work = head_; nullptr != work; work = work->next) { 70 | do_traverse(work->data); 71 | } 72 | } 73 | }; 74 | 75 | #endif // QUEUE_LINKED_QUEUE_HPP_ 76 | -------------------------------------------------------------------------------- /c-cpp/09_queue/linked_queue_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "linked_queue.hpp" 3 | 4 | int main() { 5 | auto do_traverse = [&](auto item){ std::cout << item << ' '; }; 6 | 7 | LinkedQueue linked_queue_1; 8 | linked_queue_1.enqueue(1); 9 | linked_queue_1.enqueue(2); 10 | linked_queue_1.enqueue(3); 11 | linked_queue_1.traverse(do_traverse); 12 | std::cout << std::endl; 13 | 14 | LinkedQueue linked_queue_2(linked_queue_1); // copy constructor 15 | linked_queue_2.traverse(do_traverse); 16 | std::cout << std::endl; 17 | 18 | LinkedQueue linked_queue_3(std::move(linked_queue_2)); // move constructor 19 | linked_queue_3.traverse(do_traverse); 20 | std::cout << std::endl; 21 | linked_queue_2.traverse(do_traverse); 22 | std::cout << std::endl; 23 | 24 | std::cout << linked_queue_3.head() << std::endl; 25 | linked_queue_3.dequeue(); 26 | std::cout << linked_queue_3.head() << std::endl; 27 | linked_queue_3.dequeue(); 28 | std::cout << linked_queue_3.head() << std::endl; 29 | linked_queue_3.dequeue(); 30 | // std::cout << linked_queue_3.head() << std::endl; // throw 31 | // linked_queue_3.dequeue(); // throw 32 | 33 | LinkedQueue linked_queue_4; 34 | linked_queue_4 = linked_queue_1; // copy assignment 35 | linked_queue_4.traverse(do_traverse); 36 | std::cout << std::endl; 37 | 38 | LinkedQueue linked_queue_5; 39 | linked_queue_5 = std::move(linked_queue_4); // move assignment 40 | linked_queue_5.traverse(do_traverse); 41 | std::cout << std::endl; 42 | linked_queue_4.traverse(do_traverse); 43 | std::cout << std::endl; 44 | 45 | std::cout << linked_queue_5.head() << std::endl; 46 | linked_queue_5.dequeue(); 47 | std::cout << linked_queue_5.head() << std::endl; 48 | linked_queue_5.dequeue(); 49 | std::cout << linked_queue_5.head() << std::endl; 50 | linked_queue_5.dequeue(); 51 | // std::cout << linked_queue_5.head() << std::endl; // throw 52 | // linked_queue_5.dequeue(); // throw 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /c-cpp/09_queue/list_queue/list_queue.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: list_queue.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-13 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | #include"./list_queue.h" 12 | 13 | /*创建队列头*/ 14 | list_queue *list_queue_create() 15 | { 16 | list_queue * queue = NULL; 17 | 18 | queue = (list_queue *)malloc(sizeof(list_queue)); 19 | if(queue == NULL) 20 | { 21 | return NULL; 22 | } 23 | 24 | queue->num = 0; 25 | queue->head = NULL; 26 | queue->tail = NULL; 27 | 28 | return queue; 29 | } 30 | void list_queue_destroy(list_queue*queue) 31 | { 32 | int i = 0; 33 | int data = 0; 34 | 35 | if ((queue == NULL) || (list_queue_is_empty(queue))) 36 | { 37 | return ; 38 | } 39 | 40 | while(!list_queue_is_empty(queue)) 41 | { 42 | (void)list_queue_dequeue(queue,&data); 43 | } 44 | 45 | free(queue); 46 | return; 47 | } 48 | int list_queue_enqueue(list_queue *queue,int data) 49 | { 50 | queue_node *ptmp = NULL; 51 | 52 | if(queue == NULL) 53 | { 54 | return -1; 55 | } 56 | 57 | ptmp = (queue_node *)malloc(sizeof(queue_node)); 58 | if (ptmp == NULL) 59 | { 60 | return -1; 61 | } 62 | 63 | ptmp->data = data; 64 | ptmp->next = NULL; 65 | if (queue->head == NULL) 66 | { 67 | queue->head = ptmp; 68 | } 69 | else 70 | { 71 | queue->tail->next = ptmp; 72 | 73 | } 74 | queue->tail = ptmp; 75 | queue->num++; 76 | 77 | return 0; 78 | } 79 | 80 | /*出队*/ 81 | int list_queue_dequeue(list_queue *queue,int *data) 82 | { 83 | queue_node * ptmp = NULL; 84 | 85 | if ((queue == NULL) || (data == NULL) || list_queue_is_empty(queue)) 86 | { 87 | return -1; 88 | } 89 | 90 | *data = queue->head->data; 91 | ptmp = queue->head; 92 | queue->head = queue->head->next; 93 | queue->num--; 94 | 95 | if (queue->head == NULL) 96 | { 97 | queue->tail = NULL; 98 | } 99 | 100 | 101 | free(ptmp); 102 | return 0; 103 | } 104 | void list_queue_dump(list_queue*queue) 105 | { 106 | int i = 0; 107 | queue_node *ptmp = NULL; 108 | 109 | if ((queue == NULL) || (list_queue_is_empty(queue))) 110 | { 111 | return; 112 | } 113 | 114 | ptmp = queue->head; 115 | 116 | printf("\r\n----dump queue num = %d--------",queue->num); 117 | while(ptmp != NULL) 118 | { 119 | printf("\r\nnode[%d] = %d",i,ptmp->data); 120 | i++; 121 | ptmp = ptmp->next; 122 | } 123 | printf("\r\n---------------------------------\r\n"); 124 | 125 | return; 126 | } 127 | 128 | int main() 129 | { 130 | int i = 0; 131 | int data = 0; 132 | int ret = 0; 133 | list_queue * queue; 134 | 135 | queue = list_queue_create(); 136 | if (queue == NULL) 137 | { 138 | printf("\r\nlist queue create falied.."); 139 | return 0; 140 | } 141 | 142 | for (i = 0; i < 5; i++) 143 | { 144 | (void)list_queue_enqueue(queue,i); 145 | } 146 | list_queue_dump(queue); 147 | 148 | ret = list_queue_dequeue(queue,&data); 149 | if(ret != 0) 150 | { 151 | printf("\r\nlist queue dequeue %d falied.",data); 152 | } 153 | printf("\r\nlist queue dequeue %d",data); 154 | list_queue_dump(queue); 155 | 156 | 157 | ret = list_queue_dequeue(queue,&data); 158 | if(ret != 0) 159 | { 160 | printf("\r\nlist queue dequeue %d failed.",data); 161 | } 162 | printf("\r\nlist queue dequeue %d",data); 163 | list_queue_dump(queue); 164 | 165 | printf("\r\nlist queue enqueue %d",data); 166 | (void)list_queue_enqueue(queue,data); 167 | list_queue_dump(queue); 168 | 169 | list_queue_destroy(queue); 170 | return 0; 171 | } 172 | -------------------------------------------------------------------------------- /c-cpp/09_queue/list_queue/list_queue.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: list_queue.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-13 6 | > Desc: 7 | ************************************************************************/ 8 | 9 | #ifndef LINK_LIST_QUEUE_H 10 | #define LINK_LIST_QUEUE_H 11 | 12 | typedef struct _list_queue_node 13 | { 14 | int data; 15 | struct _list_queue_node *next; 16 | }queue_node; 17 | 18 | typedef struct _list_queue 19 | { 20 | int num; 21 | queue_node *head; 22 | queue_node *tail; 23 | }list_queue; 24 | 25 | #define list_queue_is_empty(queue) ((queue->num) == 0) 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /c-cpp/09_queue/lock_free_queue.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/11. 3 | */ 4 | 5 | #ifndef QUEUE_LOCK_FREE_QUEUE_HPP_ 6 | #define QUEUE_LOCK_FREE_QUEUE_HPP_ 7 | 8 | #include 9 | #include 10 | 11 | template 12 | class LockFreeQueue { 13 | public: 14 | using value_type = T; 15 | 16 | private: 17 | struct node { 18 | std::shared data = nullptr; 19 | node* next = nullptr; 20 | }; 21 | std::atomic head = nullptr; 22 | std::atomic tail = nullptr; 23 | 24 | public: 25 | LockFreeQueue() head(new node), tail(head.load()) {} 26 | LockFreeQueue(const LockFreeQueue&) = delete; 27 | LockFreeQueue(LockFreeQueue&& other) : head(other.head.load()), tail(other.tail.load()) { 28 | other.head.store(nullptr); 29 | other.tail.store(nullptr); 30 | } 31 | LockFreeQueue& operator=(const LockFreeQueue&) = delete; 32 | LockFreeQueue& operator=(LockFreeQueue&& rhs) { 33 | while (node* const old_head = head.load()) { 34 | head.store(old_head->next); 35 | delete old_head; 36 | } 37 | head.store(rhs.head.load()); 38 | tail.store(rhs.tail.load()); 39 | rhs.head.store(nullptr); 40 | rhs.tail.store(nullptr); 41 | } 42 | ~LockFreeQueue() { 43 | while (node* const old_head = head.load()) { 44 | head.store(old_head->next); 45 | delete old_head; 46 | } 47 | } 48 | 49 | private: 50 | node* pop_head() { 51 | node* const res = head.load(); 52 | if (res == tail.load()) { 53 | return nullptr; 54 | } 55 | head.store(res->next); 56 | return res; 57 | } 58 | 59 | public: 60 | bool empty() const { 61 | return head.load() == tail.load(); 62 | } 63 | std::shared_ptr pop() { 64 | node* old_head = pop_head(); 65 | if (nullptr == old_head) { 66 | return nullptr; 67 | } else { 68 | auto res = old_head->data; 69 | delete old_head; 70 | return res; 71 | } 72 | } 73 | void push(value_type new_value) { 74 | auto new_data = std::make_shared(new_value); 75 | node* p = new node; 76 | node* old_tail = tail.load(); 77 | old_tail->data.swap(new_data); 78 | old_tail->next = p; 79 | tail_.store(p); 80 | } 81 | }; 82 | 83 | #endif // QUEUE_LOCK_FREE_QUEUE_HPP_ 84 | 85 | -------------------------------------------------------------------------------- /c-cpp/09_queue/ring_queue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct ring_queue { 7 | int cap; 8 | int head, tail; 9 | int *_q; 10 | }; 11 | 12 | int alloc_queue(struct ring_queue* queue, int cap) 13 | { 14 | if (!queue || cap < 0) 15 | return -1; 16 | if (queue->_q) 17 | return -1; 18 | 19 | queue->_q = (int *)malloc(cap * sizeof(int)); 20 | if (!queue->_q) 21 | return -1; 22 | 23 | queue->head = queue->tail = 0; 24 | queue->cap = cap; 25 | return 0; 26 | } 27 | 28 | void free_queue(struct ring_queue *queue) 29 | { 30 | queue->cap = 0; 31 | queue->head = queue->tail = 0; 32 | free(queue->_q); 33 | } 34 | 35 | int _valid_index(int curr, int step, int cap) 36 | { 37 | return (curr + step) % cap; 38 | } 39 | 40 | int _next(int curr, int cap) 41 | { 42 | return _valid_index(curr, 1, cap); 43 | } 44 | 45 | bool is_empty(struct ring_queue *queue) 46 | { 47 | return (queue->head == queue->tail); 48 | } 49 | 50 | bool is_full(struct ring_queue *queue) 51 | { 52 | int next_tail = _next(queue->tail, queue->cap); 53 | return (next_tail == queue->head); 54 | } 55 | 56 | int enqueue(struct ring_queue* queue, int elem) 57 | { 58 | if (is_full(queue)) 59 | return -1; 60 | 61 | queue->_q[queue->tail] = elem; 62 | queue->tail = _next(queue->tail, queue->cap); 63 | return 0; 64 | } 65 | 66 | int dequeue(struct ring_queue* queue, int *elem) 67 | { 68 | if (is_empty(queue)) 69 | return -1; 70 | 71 | if (elem) 72 | *elem = queue->_q[queue->head]; 73 | queue->head = _next(queue->head, queue->cap); 74 | return 0; 75 | } 76 | 77 | int size(struct ring_queue* queue) 78 | { 79 | int size = queue->tail - queue->head; 80 | 81 | if (size < 0) 82 | size += queue->cap; 83 | return size; 84 | } 85 | 86 | void dump(struct ring_queue* queue) 87 | { 88 | int i, idx; 89 | 90 | printf("Queue has %d elements with %d capacity\n", 91 | size(queue), queue->cap); 92 | for (i = 0; i < size(queue); i++) { 93 | idx = _valid_index(queue->head, i, queue->cap); 94 | printf("[%02d]: %08d\n", idx, queue->_q[idx]); 95 | } 96 | } 97 | 98 | int main() 99 | { 100 | struct ring_queue queue = {0, 0, 0, NULL}; 101 | int i; 102 | 103 | if (alloc_queue(&queue, 8)) { 104 | printf("Failed to allocate a queue\n"); 105 | return -1; 106 | } 107 | 108 | printf("A new queue is %s\n", is_empty(&queue)?"empty":"not empty"); 109 | 110 | enqueue(&queue, 1); 111 | printf("After enqueue 1 element, queue is %s\n", is_empty(&queue)?"empty":"not empty"); 112 | dequeue(&queue, NULL); 113 | printf("After dequeue 1 element, queue is %s\n", is_empty(&queue)?"empty":"not empty"); 114 | 115 | for (i = 0; i < 7; i++) 116 | enqueue(&queue, i); 117 | printf("After enqueue 7 element, queue is %s\n", is_full(&queue)?"full":"not full"); 118 | 119 | for (i = 0; i < 4; i++) { 120 | dequeue(&queue, NULL); 121 | enqueue(&queue, i); 122 | } 123 | printf("After enqueue/dequeue 4 element, queue is %s\n", 124 | is_full(&queue)?"full":"not full"); 125 | printf("Head is %d, Tail is %d\n", queue.head, queue.tail); 126 | 127 | dump(&queue); 128 | free_queue(&queue); 129 | return 0; 130 | } 131 | -------------------------------------------------------------------------------- /c-cpp/10_recursive/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/10_recursive/.gitkeep -------------------------------------------------------------------------------- /c-cpp/10_recursive/one_two_step.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: one_two_step.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-19 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | 12 | /*爬楼梯的问题,解决重复计算,采用数据保存方法*/ 13 | 14 | int helper(int n ,int *vlaue) 15 | { 16 | 17 | if(vlaue[n] != 0) 18 | { 19 | return vlaue[n]; 20 | } 21 | 22 | vlaue[n] = helper(n - 1,vlaue) + helper(n - 2,vlaue); 23 | 24 | return vlaue[n]; 25 | } 26 | 27 | int climbStaris(int n) 28 | { 29 | int *vlaue = NULL; 30 | int res = 0; 31 | 32 | vlaue = (int *)malloc(sizeof(int)*(n+1)); 33 | if(vlaue == NULL) 34 | { 35 | return -1; 36 | } 37 | 38 | memset(vlaue,0,sizeof(int)*(n + 1)); 39 | vlaue[0] = 0; 40 | vlaue[1] = 1; 41 | vlaue[2] = 2; 42 | res = helper(n,vlaue); 43 | free(vlaue); 44 | 45 | return res; 46 | } 47 | 48 | int main() 49 | { 50 | 51 | printf("\r\nnum%d ,%d",5,climbStaris(5)); 52 | printf("\r\nnum%d ,%d",6,climbStaris(6)); 53 | printf("\r\nnum%d ,%d",7,climbStaris(7)); 54 | return 0; 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /c-cpp/10_recursive/one_two_step.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class SolutionOFOneTwoStep { 5 | private: 6 | static std::unordered_map result_; 7 | 8 | public: 9 | enum class POLICY { 10 | RECURSIVE, 11 | NONRECURSIVE 12 | }; 13 | 14 | private: 15 | size_t recursive(size_t steps) { 16 | auto iter = result_.find(steps); 17 | if (result_.end() != iter) { // found. 18 | return iter->second; 19 | } else { 20 | size_t res = operator()(steps - 1) + operator()(steps - 2); 21 | result_.insert({steps, res}); 22 | return res; 23 | } 24 | } 25 | size_t nonrecursive(size_t steps) { 26 | auto iter = result_.find(steps); 27 | if (result_.end() != iter) { // found. 28 | return iter->second; 29 | } else { 30 | size_t start; 31 | for (start = steps; start != 2 and result_.end() == result_.find(start); --start) {} 32 | for (size_t i = start; i != steps; ++i) { 33 | result_.insert({i + 1, result_[i - 1] + result_[i]}); 34 | } 35 | return result_[steps]; 36 | } 37 | } 38 | 39 | public: 40 | size_t operator()(size_t steps, const POLICY policy = POLICY::RECURSIVE) { 41 | if (policy == POLICY::RECURSIVE) { 42 | return recursive(steps); 43 | } else if (policy == POLICY::NONRECURSIVE) { 44 | return nonrecursive(steps); 45 | } 46 | } 47 | static void debug() { 48 | for (auto kv : result_) { 49 | std::cout << kv.first << ' ' << kv.second << std::endl; 50 | } 51 | std::cout << std::endl; 52 | } 53 | }; 54 | 55 | std::unordered_map SolutionOFOneTwoStep::result_ = {{1, 1}, {2, 2}}; 56 | 57 | int main() { 58 | SolutionOFOneTwoStep::debug(); 59 | 60 | std::cout << SolutionOFOneTwoStep()(5, SolutionOFOneTwoStep::POLICY::RECURSIVE) << std::endl; 61 | SolutionOFOneTwoStep::debug(); 62 | 63 | std::cout << SolutionOFOneTwoStep()(10, SolutionOFOneTwoStep::POLICY::NONRECURSIVE) << std::endl; 64 | SolutionOFOneTwoStep::debug(); 65 | 66 | std::cout << SolutionOFOneTwoStep()(20, SolutionOFOneTwoStep::POLICY::RECURSIVE) << std::endl; 67 | SolutionOFOneTwoStep::debug(); 68 | 69 | return 0; 70 | } 71 | 72 | -------------------------------------------------------------------------------- /c-cpp/11_sorts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/11_sorts/.gitkeep -------------------------------------------------------------------------------- /c-cpp/11_sorts/sorts.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct array { 6 | int size; 7 | int used; 8 | int *arr; 9 | }; 10 | 11 | void dump(struct array *array) 12 | { 13 | int idx; 14 | 15 | for (idx = 0; idx < array->used; idx++) 16 | printf("[%02d]: %08d\n", idx, array->arr[idx]); 17 | } 18 | 19 | void alloc(struct array *array) 20 | { 21 | array->arr = (int *)malloc(array->size * sizeof(int)); 22 | } 23 | 24 | void bubble_sort(struct array *array) 25 | { 26 | int i, j; 27 | 28 | if (array->used <= 1) 29 | return; 30 | 31 | for (i = 0; i < array->used; i++) { 32 | bool has_swap = false; 33 | for (j = 0; j < array->used - i - 1; j++) { 34 | if (array->arr[j] > array->arr[j+1]) { 35 | int tmp; 36 | tmp = array->arr[j]; 37 | array->arr[j] = array->arr[j+1]; 38 | array->arr[j+1] = tmp; 39 | has_swap = true; 40 | } 41 | 42 | } 43 | if (!has_swap) 44 | break; 45 | } 46 | } 47 | 48 | void bubble_sort_test() 49 | { 50 | int idx; 51 | struct array ten_int = {10, 0, NULL}; 52 | 53 | alloc(&ten_int); 54 | for (idx = 0; idx < 10; idx++) 55 | ten_int.arr[idx] = 30 - idx; 56 | ten_int.used = 10; 57 | dump(&ten_int); 58 | bubble_sort(&ten_int); 59 | dump(&ten_int); 60 | } 61 | 62 | void insertion_sort(struct array *array) 63 | { 64 | int i, j; 65 | 66 | if (array->used <= 1) 67 | return; 68 | 69 | for (i = 1; i < array->used; i++) { 70 | int val = array->arr[i]; 71 | 72 | for (j = i - 1; j >= 0; j--) { 73 | if (val < array->arr[j]) 74 | array->arr[j+1] = array->arr[j]; 75 | else 76 | break; 77 | } 78 | array->arr[j+1] = val; 79 | } 80 | } 81 | 82 | void insertion_sort_test() 83 | { 84 | int idx; 85 | struct array ten_int = {10, 0, NULL}; 86 | 87 | alloc(&ten_int); 88 | for (idx = 0; idx < 10; idx++) 89 | ten_int.arr[idx] = 30 - idx; 90 | ten_int.used = 10; 91 | dump(&ten_int); 92 | insertion_sort(&ten_int); 93 | dump(&ten_int); 94 | } 95 | 96 | void selection_sort(struct array *array) 97 | { 98 | int i, j; 99 | 100 | if (array->used <= 1) 101 | return; 102 | 103 | for (i = 0; i < array->used - 1; i++) { 104 | int tmp, idx = i; 105 | 106 | for (j = i + 1; j < array->used; j++) 107 | if (array->arr[j] < array->arr[idx]) 108 | idx = j; 109 | 110 | if (idx == i) 111 | continue; 112 | 113 | tmp = array->arr[i]; 114 | array->arr[i] = array->arr[idx]; 115 | array->arr[idx] = tmp; 116 | } 117 | } 118 | 119 | void selection_sort_test() 120 | { 121 | int idx; 122 | struct array ten_int = {10, 0, NULL}; 123 | 124 | alloc(&ten_int); 125 | for (idx = 0; idx < 10; idx++) 126 | ten_int.arr[idx] = 30 - idx; 127 | ten_int.used = 10; 128 | dump(&ten_int); 129 | selection_sort(&ten_int); 130 | dump(&ten_int); 131 | } 132 | 133 | int main() 134 | { 135 | //bubble_sort_test(); 136 | //selection_sort_test(); 137 | insertion_sort_test(); 138 | return 0; 139 | } 140 | -------------------------------------------------------------------------------- /c-cpp/11_sorts/sorts.cpp: -------------------------------------------------------------------------------- 1 | // C program for implementation of selection sort 2 | #include 3 | 4 | void swap(int *xp, int *yp) 5 | { 6 | int temp = *xp; 7 | *xp = *yp; 8 | *yp = temp; 9 | } 10 | 11 | void selectionSort(int arr[], int n) 12 | { 13 | int i, j, min_idx; 14 | 15 | // One by one move boundary of unsorted subarray 16 | for (i = 0; i < n-1; i++) 17 | { 18 | // Find the minimum element in unsorted array 19 | min_idx = i; 20 | for (j = i+1; j < n; j++) 21 | if (arr[j] < arr[min_idx]) 22 | min_idx = j; 23 | 24 | // Swap the found minimum element with the first element 25 | swap(&arr[min_idx], &arr[i]); 26 | } 27 | } 28 | 29 | /* Function to print an array */ 30 | void printArray(int arr[], int size) 31 | { 32 | int i; 33 | for (i=0; i < size; i++) 34 | printf("%d ", arr[i]); 35 | printf("\n"); 36 | } 37 | 38 | // Driver program to test above functions 39 | int main() 40 | { 41 | int arr[] = {64, 25, 12, 22, 11}; 42 | int n = sizeof(arr)/sizeof(arr[0]); 43 | selectionSort(arr, n); 44 | printf("Sorted array: \n"); 45 | printArray(arr, n); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /c-cpp/11_sorts/sorts.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/16. 3 | */ 4 | 5 | #ifndef SORTS_SORTS_HPP_ 6 | #define SORTS_SORTS_HPP_ 7 | 8 | #include 9 | #include 10 | 11 | template ::value_type>> 13 | void bubble_sort(BidirIt first, BidirIt last, BinaryPred comp = BinaryPred()) { 14 | if (std::distance(first, last) <= 1) { return; } 15 | bool flag = true; 16 | for (auto it = first; flag and it != last; ++it) { 17 | flag = false; 18 | for (auto itt = first; itt != last - std::distance(first, it) - 1; ++itt) { 19 | if (comp(*(itt + 1), *itt)) { 20 | std::swap(*itt, *(itt + 1)); 21 | flag = true; 22 | } 23 | } 24 | } 25 | } 26 | 27 | template ::value_type>> 29 | void insertion_sort(BidirIt first, BidirIt last, BinaryPred comp = BinaryPred()) { 30 | if (std::distance(first, last) <= 1) { return; } 31 | for (auto it = first + 1; it != last; ++it) { 32 | const auto target = *it; 33 | auto itt = it; 34 | for (; std::distance(first, itt) > 0 and comp(target, *(itt - 1)); --itt) { 35 | *itt = *(itt - 1); 36 | } 37 | *itt = target; 38 | } 39 | } 40 | 41 | template ::value_type>> 43 | void selection_sort(BidirIt first, BidirIt last, BinaryPred comp = BinaryPred()) { 44 | if (std::distance(first, last) <= 1) { return; } 45 | for (auto it = first; it != last - 1; ++it) { 46 | auto tag = it; 47 | for (auto itt = it + 1; itt != last; ++itt) { 48 | if (comp(*itt, *tag)) { 49 | tag = itt; 50 | } 51 | } 52 | if (tag != it) { 53 | std::swap(*it, *tag); 54 | } 55 | } 56 | } 57 | 58 | template ::value_type>> 60 | void bubble_down_sort(FrwdIt first, FrwdIt last, BinaryPred comp = BinaryPred()) { 61 | if (std::distance(first, last) <= 1) { return; } 62 | for (auto it = first; it != last; ++it) { 63 | for (auto itt = it + 1; itt != last; ++itt) { 64 | if (comp(*itt, *it)) { 65 | std::swap(*it, *itt); 66 | } 67 | } 68 | } 69 | } 70 | 71 | template ::value_type>> 73 | void shell_sort(BidirIt first, BidirIt last, BinaryPred comp = BinaryPred()) { 74 | const size_t len = std::distance(first, last); 75 | if (len <= 1) { return; } 76 | for (size_t step = len / 2; step >= 1; step /= 2) { 77 | for (auto it = first + step; it != last; ++it) { 78 | auto target = *it; 79 | auto itt = it - step; 80 | for (; std::distance(first, itt) >= 0 and comp(target, *itt); itt -= step) { 81 | *(itt + step) = *itt; 82 | } 83 | *(itt + step) = target; 84 | } 85 | } 86 | } 87 | 88 | #endif // SORTS_SORTS_HPP_ 89 | 90 | -------------------------------------------------------------------------------- /c-cpp/11_sorts/sorts_jinshaohui.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: sorts_jinshaohui.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-19 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | 12 | #define SWAP(a,b) \ 13 | do{\ 14 | (a) ^= (b);\ 15 | (b) ^= (a);\ 16 | (a) ^= (b);\ 17 | }while(0) 18 | 19 | /*冒泡排序*/ 20 | void bubble_sort(int a[],int size) 21 | { 22 | int i = 0; 23 | int j = 0; 24 | int swap_flg = 0; 25 | 26 | if (size < 1) 27 | { 28 | return; 29 | } 30 | 31 | for (i = size - 1; i > 0; i--)/*排序的趟数*/ 32 | { 33 | swap_flg = 0;/*每次设置交换标识为0*/ 34 | for (j = 0; j < i; j++)/*本趟排序的遍历元素个数*/ 35 | { 36 | if (a[j] > a[j + 1]) 37 | { 38 | SWAP(a[j],a[j+1]); 39 | swap_flg = 1; 40 | } 41 | } 42 | /*本趟数,无数据交换的话,说明已经有序,直接退出*/ 43 | if (swap_flg == 0) 44 | { 45 | break; 46 | } 47 | } 48 | return; 49 | } 50 | 51 | /*插入排序*/ 52 | void insert_sort(int a[],int size) 53 | { 54 | int i = 0; 55 | int j = 0; 56 | int key = 0; 57 | 58 | for (i = 1; i < size; i ++)/*需要插入的元素个数*/ 59 | { 60 | key = a[i];/*保存插入的元素数据*/ 61 | j = i - 1; 62 | /* i 之前的元素都是有序的,找到比key小的插入到他后面, 63 | * 比key大的,需要往后挪一个位置*/ 64 | while((j >= 0) && (a[j] > key)) 65 | { 66 | a[j + 1] = a[j]; 67 | j--; 68 | } 69 | a[j + 1] = key; 70 | } 71 | 72 | return; 73 | } 74 | /*选择排序*/ 75 | void select_sort(int a[],int size) 76 | { 77 | int i = 0; 78 | int j = 0; 79 | int min = 0; 80 | 81 | for (i = 0; i < size - 1; i++) 82 | { 83 | min = i; 84 | for (j = i + 1; j < size; j++) 85 | { 86 | if (a[j] < a[min]) 87 | { 88 | min = j; 89 | } 90 | } 91 | 92 | if (min != i) 93 | { 94 | SWAP(a[i],a[min]); 95 | } 96 | } 97 | return; 98 | } 99 | 100 | void dump(int a[],int size) 101 | { 102 | int i = 0; 103 | 104 | printf("\r\n"); 105 | for (i = 0; i < size; i++ ) 106 | { 107 | printf("%d ",a[i]); 108 | } 109 | printf("\r\n"); 110 | return; 111 | } 112 | 113 | int main() 114 | { 115 | int a[10] = {9,11,4,15,16,3,20,44,5,10}; 116 | 117 | //bubble_sort(a,sizeof(a)/sizeof(int)); 118 | //insert_sort(a,sizeof(a)/sizeof(int)); 119 | select_sort(a,sizeof(a)/sizeof(int)); 120 | 121 | dump(a,sizeof(a)/sizeof(int)); 122 | 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /c-cpp/11_sorts/sorts_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "sorts.hpp" 5 | 6 | int main() { 7 | const std::vector test_data{1, 2, 3, 0}; 8 | 9 | std::vector a(test_data.begin(), test_data.end()); 10 | bubble_sort(a.begin(), a.end()); 11 | for (auto i : a) { 12 | std::cout << i << ' '; 13 | } 14 | std::cout << '\n'; 15 | 16 | std::vector b(test_data.begin(), test_data.end()); 17 | insertion_sort(b.begin(), b.end()); 18 | for (auto i : b) { 19 | std::cout << i << ' '; 20 | } 21 | std::cout << '\n'; 22 | 23 | std::vector c(test_data.begin(), test_data.end()); 24 | selection_sort(c.begin(), c.end()); 25 | for (auto i : c) { 26 | std::cout << i << ' '; 27 | } 28 | std::cout << '\n'; 29 | 30 | std::vector d(test_data.begin(), test_data.end()); 31 | bubble_down_sort(d.begin(), d.end()); 32 | for (auto i : d) { 33 | std::cout << i << ' '; 34 | } 35 | std::cout << '\n'; 36 | 37 | std::vector e(test_data.begin(), test_data.end()); 38 | shell_sort(e.begin(), e.end()); 39 | for (auto i : e) { 40 | std::cout << i << ' '; 41 | } 42 | std::cout << '\n'; 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /c-cpp/12_sorts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/12_sorts/.gitkeep -------------------------------------------------------------------------------- /c-cpp/12_sorts/merge_sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void dump(int *arr, int size) 7 | { 8 | int idx; 9 | 10 | for (idx = 0; idx < size; idx++) 11 | printf("%08d\n", arr[idx]); 12 | } 13 | 14 | void __merge(int *arr, int p, int q, int r) 15 | { 16 | int *tmp; 17 | int i, j, k; 18 | 19 | tmp = (int*)malloc((r - p + 1) * sizeof(int)); 20 | 21 | if (!tmp) 22 | abort(); 23 | 24 | for (i = p, j = q + 1, k = 0; i <= q && j <= r;) { 25 | if (arr[i] <= arr[j]) 26 | tmp[k++] = arr[i++]; 27 | else 28 | tmp[k++] = arr[j++]; 29 | } 30 | 31 | if (i == q + 1) { 32 | for (; j <= r;) 33 | tmp[k++] = arr[j++]; 34 | } else { 35 | for (; i <= q;) 36 | tmp[k++] = arr[i++]; 37 | } 38 | 39 | memcpy(arr + p, tmp, (r - p + 1) * sizeof(int)); 40 | free(tmp); 41 | } 42 | 43 | void __merge_sort(int *arr, int p, int r) 44 | { 45 | int q; 46 | 47 | if (p >= r) 48 | return; 49 | 50 | q = (p + r) / 2; 51 | __merge_sort(arr, p, q); 52 | __merge_sort(arr, q + 1, r); 53 | __merge(arr, p, q, r); 54 | } 55 | 56 | void merge_sort(int *arr, int size) 57 | { 58 | __merge_sort(arr, 0, size - 1); 59 | } 60 | 61 | void merge_verify() 62 | { 63 | int test[10] = {5, 8, 9, 23, 67, 1, 3, 7, 31, 56}; 64 | 65 | __merge(test, 0, 4, 9); 66 | 67 | dump(test, 10); 68 | } 69 | 70 | void merge_sort_test() 71 | { 72 | int test[10] = {5, 8, 9, 23, 67, 1, 3, 7, 31, 56}; 73 | 74 | merge_sort(test, 10); 75 | 76 | dump(test, 10); 77 | } 78 | 79 | int main() 80 | { 81 | //merge_verify(); 82 | merge_sort_test(); 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /c-cpp/12_sorts/merge_sort.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/17. 3 | */ 4 | 5 | #ifndef SORTS_MERGE_SORT_HPP_ 6 | #define SORTS_MERGE_SORT_HPP_ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace detail { 14 | template ::value_type>> 16 | OutputIt merge(InputIt1 first1, InputIt1 last1, 17 | InputIt2 first2, InputIt2 last2, 18 | OutputIt d_first, 19 | BinaryPred comp = BinaryPred()) { 20 | for (; first1 != last1; ++d_first) { 21 | if (first2 == last2) { 22 | return std::copy(first1, last1, d_first); 23 | } 24 | if (comp(*first2, *first1)) { 25 | *d_first = *first2; 26 | ++first2; 27 | } else { 28 | *d_first = *first1; 29 | ++first1; 30 | } 31 | } 32 | return std::copy(first2, last2, d_first); 33 | } 34 | } // namespace detail 35 | 36 | template ::value_type>> 38 | void merge_sort(FrwdIt first, FrwdIt last, BinaryPred comp = BinaryPred()) { 39 | const auto len = std::distance(first, last); 40 | if (len <= 1) { return; } 41 | auto cut = first + len / 2; 42 | merge_sort(first, cut, comp); 43 | merge_sort(cut, last, comp); 44 | std::vector::value_type> tmp; 45 | tmp.reserve(len); 46 | detail::merge(first, cut, cut, last, std::back_inserter(tmp), comp); 47 | std::copy(tmp.begin(), tmp.end(), first); 48 | } 49 | 50 | template ::value_type>> 52 | void inplace_merge_sort(BidirIt first, BidirIt last, BinaryPred comp = BinaryPred()) { 53 | const auto len = std::distance(first, last); 54 | if (len <= 1) { return; } 55 | auto cut = first + len / 2; 56 | inplace_merge_sort(first, cut, comp); 57 | inplace_merge_sort(cut, last, comp); 58 | std::inplace_merge(first, cut, last, comp); 59 | } 60 | 61 | #endif // SORTS_MERGE_SORT_HPP_ 62 | 63 | -------------------------------------------------------------------------------- /c-cpp/12_sorts/merge_sort_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/17. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "merge_sort.hpp" 8 | 9 | int main() { 10 | const std::vector test_data{0, -1, 3, 190, -500}; 11 | 12 | std::vector a{test_data}; 13 | merge_sort(a.begin(), a.end()); 14 | for (auto i : a) { 15 | std::cout << i << ' '; 16 | } 17 | std::cout << std::endl; 18 | 19 | std::vector b{test_data}; 20 | inplace_merge_sort(b.begin(), b.end()); 21 | for (auto i : b) { 22 | std::cout << i << ' '; 23 | } 24 | std::cout << std::endl; 25 | 26 | return 0; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /c-cpp/12_sorts/my12_sorts/merge_sort.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: merge_sort.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-19 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define SORT_MAX (1000000) 14 | 15 | void dump(int a[],int size); 16 | void merge_sentry(int a[],int middle,int left,int right) 17 | { 18 | int *pleft = NULL; 19 | int *pright = NULL; 20 | int i = 0; 21 | int j = 0; 22 | int k = 0; 23 | int left_size = middle - left + 1; 24 | int right_size = right - middle; 25 | 26 | 27 | pleft = (int *)malloc(sizeof(int)*(left_size + 1)); 28 | assert(pleft != NULL); 29 | pright = (int *)malloc(sizeof(int)*(right_size + 1)); 30 | assert(pright != NULL); 31 | 32 | for(i = 0; i < left_size; i ++) 33 | { 34 | pleft[i] = a[left + i]; 35 | } 36 | pleft[left_size] = SORT_MAX; 37 | for(i = 0; i < right_size; i ++) 38 | { 39 | pright[i] = a[middle + 1 + i]; 40 | } 41 | pright[right_size] = SORT_MAX; 42 | 43 | for (k = left,i = 0,j = 0; k <= right; k++) 44 | { 45 | if (pleft[i] <= pright[j]) 46 | { 47 | a[k] = pleft[i++]; 48 | } 49 | else 50 | { 51 | a[k] = pright[j++]; 52 | } 53 | } 54 | 55 | free(pleft); 56 | free(pright); 57 | 58 | return; 59 | } 60 | 61 | /*两个有序数组合并*/ 62 | void merge(int a[],int middle,int left,int right) 63 | { 64 | int *tmp = NULL; 65 | int i = 0; 66 | int j = 0; 67 | int k = 0; 68 | 69 | tmp = (int*)malloc((right - left + 1)*sizeof(int)); 70 | assert(tmp != NULL); 71 | 72 | i = left; 73 | j = middle + 1; 74 | 75 | while(1) 76 | { 77 | if((i > middle) || (j > right)) 78 | { 79 | break; 80 | } 81 | 82 | if (a[i] > a[j]) 83 | { 84 | tmp[k++] = a[j++]; 85 | } 86 | else 87 | { 88 | tmp[k++] = a[i++]; 89 | } 90 | } 91 | 92 | if (i > middle) 93 | { 94 | while(j <= right) 95 | { 96 | tmp[k++] = a[j++]; 97 | } 98 | } 99 | else 100 | { 101 | while(i <= middle) 102 | { 103 | tmp[k++] = a[i++]; 104 | } 105 | } 106 | 107 | memcpy((a + left),tmp,(right - left + 1)*sizeof(int)); 108 | 109 | free(tmp); 110 | 111 | return ; 112 | } 113 | 114 | void merge_sort(int a[],int left,int right) 115 | { 116 | int middle = 0; 117 | 118 | if(left >= right) 119 | { 120 | return; 121 | } 122 | 123 | middle = (left + right)/2; 124 | 125 | merge_sort(a,left,middle); 126 | merge_sort(a,middle + 1,right); 127 | 128 | merge_sentry(a,middle,left,right); 129 | 130 | return; 131 | } 132 | 133 | void dump(int a[],int size) 134 | { 135 | int i = 0; 136 | 137 | if(size == 0) 138 | { 139 | return; 140 | } 141 | 142 | printf("\r\n"); 143 | for (i = 0; i < size; i++ ) 144 | { 145 | printf("%d ",a[i]); 146 | } 147 | printf("\r\n"); 148 | return; 149 | } 150 | int main() 151 | { 152 | int a[10] = {30,20,10,15,4,8,40,80,20,9}; 153 | 154 | merge_sort(a,0,9); 155 | 156 | dump(a,10); 157 | 158 | return 0; 159 | } 160 | 161 | -------------------------------------------------------------------------------- /c-cpp/12_sorts/my12_sorts/quick_sort.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: quick_sort.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-19 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /* SWAP 使用必须主要,不能是同一个数据进行交换*/ 14 | #define SWAP(a,b) \ 15 | do{\ 16 | (a) ^= (b);\ 17 | (b) ^= (a);\ 18 | (a) ^= (b);\ 19 | }while(0) 20 | 21 | int partition2(int a[],int left,int right) 22 | { 23 | int i = left; 24 | int j = left; 25 | 26 | for(; j < right;j++) 27 | { 28 | if (a[j] < a[right]) 29 | { 30 | if(i != j) 31 | { 32 | SWAP(a[i],a[j]); 33 | } 34 | i++; 35 | } 36 | } 37 | 38 | if(i != right) 39 | { 40 | SWAP(a[i],a[right]); 41 | } 42 | 43 | return i; 44 | } 45 | 46 | int partition(int a[],int left,int right) 47 | { 48 | int i = left; 49 | int j = right; 50 | int key = a[left]; 51 | 52 | while(i < j) 53 | { 54 | while((i < j)&& (a[j] >= key)) 55 | { 56 | j--; 57 | } 58 | if (i < j) 59 | { 60 | a[i] = a[j]; 61 | } 62 | while((i < j) && a[i] <= key) 63 | { 64 | i++; 65 | } 66 | 67 | if (i= right) 82 | { 83 | return; 84 | } 85 | 86 | q = partition2(a,left,right); 87 | quick_sort(a,left,(q - 1)); 88 | quick_sort(a,(q + 1),right); 89 | return; 90 | } 91 | 92 | void dump(int a[],int size) 93 | { 94 | int i = 0; 95 | 96 | printf("\r\n"); 97 | for (i = 0; i < size; i++ ) 98 | { 99 | printf("%d ",a[i]); 100 | } 101 | printf("\r\n"); 102 | return; 103 | } 104 | 105 | int helper(int a[],int left,int right,int k) 106 | { 107 | int q = 0; 108 | 109 | q = partition(a,left,right); 110 | 111 | if (q > (k - 1)) 112 | { 113 | return helper(a,left,q-1,k); 114 | } 115 | else if (q < (k - 1)) 116 | { 117 | return helper(a,q+1,right,k); 118 | } 119 | 120 | return a[q]; 121 | } 122 | 123 | /*求无序数组中从小到大第K个元素的数值*/ 124 | int findKthlagest(int a[],int size,int k) 125 | { 126 | return helper(a,0,size-1,k); 127 | } 128 | 129 | 130 | int main() 131 | { 132 | int a[10] = {30,20,10,15,4,8,40,80,20,9}; 133 | int k; 134 | 135 | scanf("%d",&k); 136 | 137 | printf("\r\n从小到大排序,第%d个元素数值是%d",k,findKthlagest(a,10,k)); 138 | 139 | quick_sort(a,0,9); 140 | 141 | dump(a,10); 142 | 143 | return 0; 144 | } 145 | 146 | -------------------------------------------------------------------------------- /c-cpp/12_sorts/quick_sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void dump(int *arr, int size) 7 | { 8 | int idx; 9 | 10 | for (idx = 0; idx < size; idx++) 11 | printf("%08d\n", arr[idx]); 12 | } 13 | 14 | void swap(int *a, int *b) 15 | { 16 | int tmp = *a; 17 | *a = *b; 18 | *b = tmp; 19 | } 20 | 21 | int partition(int *arr, int p, int r) 22 | { 23 | //int pivot = arr[r]; 24 | int i, j; 25 | 26 | i = j = p; 27 | 28 | for (; j < r; j++) { 29 | if (arr[j] < arr[r]) { 30 | if(i != j) 31 | { 32 | swap(arr + i, arr + j); 33 | 34 | } 35 | i++; 36 | } 37 | } 38 | 39 | swap(arr + i, arr + r); 40 | return i; 41 | } 42 | 43 | void __quick_sort(int *arr, int p, int r) 44 | { 45 | int q; 46 | 47 | if (p >= r) 48 | return; 49 | 50 | q = partition(arr, p, r); 51 | __quick_sort(arr, p, q-1); 52 | __quick_sort(arr, q+1, r); 53 | } 54 | 55 | void quick_sort(int *arr, int size) 56 | { 57 | __quick_sort(arr, 0, size - 1); 58 | } 59 | 60 | void quick_sort_test() 61 | { 62 | int test[10] = {5, 8, 9, 23, 67, 1, 3, 7, 31, 56}; 63 | 64 | quick_sort(test, 10); 65 | 66 | dump(test, 10); 67 | } 68 | 69 | int main() 70 | { 71 | quick_sort_test(); 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /c-cpp/12_sorts/quick_sort.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/17. 3 | */ 4 | 5 | #ifndef SORTS_QUICK_SORT_HPP_ 6 | #define SORTS_QUICK_SORT_HPP_ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace detail { 14 | template > 15 | const T& median(const T& a, const T& b, const T& c, Compare comp = Compare()) { 16 | if (comp(a, b) and comp(b, c) or comp(c, b) and comp(b, a)) { 17 | return b; 18 | } else if (comp(b, c) and comp(c, a) or comp(a, c) and comp(c, b)) { 19 | return c; 20 | } else { 21 | return a; 22 | } 23 | } 24 | 25 | template ::value_type, 27 | typename Compare = std::less> 28 | const T& iter_median(Iter a, Iter b, Iter c, Compare comp = Compare()) { 29 | return median(*a, *b, *c, comp); 30 | } 31 | 32 | template ::value_type, 34 | typename Compare = std::less> 35 | std::pair inplace_partition(BidirIt first, 36 | BidirIt last, 37 | const T& pivot, 38 | Compare comp = Compare()) { 39 | BidirIt last_less, last_greater, first_equal, last_equal; 40 | for (last_less = first, last_greater = first, first_equal = last; 41 | last_greater != first_equal; ) { 42 | if (comp(*last_greater, pivot)) { 43 | std::iter_swap(last_greater++, last_less++); 44 | } else if (comp(pivot, *last_greater)) { 45 | ++last_greater; 46 | } else { // pivot == *last_greater 47 | std::iter_swap(last_greater, --first_equal); 48 | } 49 | } 50 | const auto cnt = std::distance(first_equal, last); 51 | std::swap_ranges(first_equal, last, last_less); 52 | first_equal = last_less; 53 | last_equal = first_equal + cnt; 54 | return {first_equal, last_equal}; 55 | } 56 | } // namespace detail 57 | 58 | template ::value_type, 60 | typename Compare = std::less> 61 | void quick_sort(BidirIt first, BidirIt last, Compare comp = Compare()) { 62 | for (auto size = std::distance(first, last); size > 1; size = std::distance(first, last)) { 63 | const T pivot = detail::iter_median(first, last - 1, first + size / 2, comp); 64 | const auto eq = detail::inplace_partition(first, last, pivot, comp); 65 | quick_sort(first, eq.first, comp); 66 | first = eq.second; // Liam Huang: economize half of recursive calling. 67 | } 68 | } 69 | 70 | #endif // SORTS_QUICK_SORT_HPP_ 71 | 72 | -------------------------------------------------------------------------------- /c-cpp/12_sorts/quick_sort_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/17. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "quick_sort.hpp" 10 | 11 | void test_quick_sort(std::vector test_data) { 12 | quick_sort(test_data.begin(), test_data.end()); 13 | std::transform(test_data.begin(), test_data.end(), 14 | std::ostream_iterator(std::cout, " "), [](int i){ return i; }); 15 | std::cout << '\n'; 16 | } 17 | 18 | int main() { 19 | test_quick_sort({-3, -1, 1, -2, -3, 0, -3, 100, 1, 1, -100}); 20 | test_quick_sort({1, 1, 1}); 21 | test_quick_sort({1, 0, -1}); 22 | test_quick_sort({1}); 23 | return 0; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /c-cpp/13_sorts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/13_sorts/.gitkeep -------------------------------------------------------------------------------- /c-cpp/13_sorts/bucket_sort.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/26. 3 | */ 4 | 5 | #ifndef SORTS_BUCKET_SORT_HPP_ 6 | #define SORTS_BUCKET_SORT_HPP_ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | template ::value_type, 16 | typename Compare = std::less> 17 | void bucket_sort(IterT first, IterT last, Compare comp = Compare()) { 18 | const T min = *std::min_element(first, last), max = *std::max_element(first, last); 19 | const T range = max + 1 - min; 20 | const size_t bucket_num = (range - 1) / BucketSize + 1; 21 | 22 | std::vector> buckets(bucket_num); 23 | for (auto b : buckets) { 24 | b.reserve(2 * BucketSize); 25 | } 26 | 27 | for (IterT i = first; i != last; ++i) { 28 | size_t idx = (*i - min) / BucketSize; 29 | buckets[idx].emplace_back(*i); 30 | } 31 | 32 | IterT dest = first; 33 | for (auto b : buckets) { 34 | std::sort(b.begin(), b.end(), comp); 35 | std::copy(b.begin(), b.end(), dest); 36 | dest += b.size(); 37 | } 38 | 39 | return; 40 | } 41 | 42 | #endif // SORTS_BUCKET_SORT_HPP_ 43 | 44 | -------------------------------------------------------------------------------- /c-cpp/13_sorts/bucket_sort_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/26. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "bucket_sort.hpp" 10 | 11 | template > 15 | void test_bucket_sort(Container cont, Compare comp = Compare()) { 16 | bucket_sort(cont.begin(), cont.end(), comp); 17 | std::transform(cont.begin(), cont.end(), std::ostream_iterator(std::cout, " "), 18 | [](T i){ return i; }); 19 | std::cout << std::endl; 20 | } 21 | 22 | int main() { 23 | std::vector test{3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9}; 24 | 25 | test_bucket_sort<2>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9 26 | test_bucket_sort<3>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9 27 | test_bucket_sort<4>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9 28 | test_bucket_sort<5>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9 29 | test_bucket_sort<6>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9 30 | 31 | return 0; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /c-cpp/13_sorts/counting_sort.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/26. 3 | */ 4 | 5 | #ifndef SORTS_COUNTING_SORT_HPP_ 6 | #define SORTS_COUNTING_SORT_HPP_ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | template ::value_type> 15 | void counting_sort(IterT first, IterT last) { 16 | const auto len = std::distance(first, last); 17 | if (len < 2) { return; } 18 | 19 | const T max = *std::max_element(first, last); 20 | if (max == 0) { return; } 21 | 22 | std::vector counter(max + 1); 23 | for (IterT i = first; i != last; ++i) { 24 | ++counter[*i]; 25 | } 26 | for (size_t i = 1; i != max + 1; ++i) { 27 | const size_t j = max - i; 28 | counter[j] += counter[j + 1]; // Liam Huang: count of numbers that is not less than j. 29 | } 30 | 31 | std::vector temp(len); 32 | for (IterT i = first; i != last; ++i) { 33 | temp[len - counter[*i]] = *i; 34 | --counter[*i]; // Liam Huang: stable for relative position. 35 | } 36 | std::copy(temp.begin(), temp.end(), first); 37 | } 38 | 39 | #endif // SORTS_COUNTING_SORT_HPP_ 40 | 41 | -------------------------------------------------------------------------------- /c-cpp/13_sorts/counting_sort_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/26. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "counting_sort.hpp" 10 | 11 | template 13 | void test_counting_sort(Container cont) { 14 | counting_sort(cont.begin(), cont.end()); 15 | std::transform(cont.begin(), cont.end(), std::ostream_iterator(std::cout, " "), 16 | [](T i){ return i; }); 17 | std::cout << std::endl; 18 | } 19 | 20 | int main() { 21 | // Liam Huang: pi for test 22 | const std::vector test1{3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3}; 23 | const std::vector test2{2, 3, 8, 4, 6, 2, 6, 4, 3, 3, 8, 3, 2, 7, 9}; 24 | const std::vector test3{5, 0, 2, 8, 8, 4, 1, 9, 7, 1, 6, 9, 3, 9, 9}; 25 | const std::vector test4{3, 7, 5, 1, 0, 5, 8, 2, 0, 9, 7, 4, 9, 4, 4}; 26 | const std::vector test5{5, 9, 2, 3, 0, 7, 8, 1, 6, 4, 0, 6, 2, 8, 6}; 27 | 28 | test_counting_sort(test1); // 1 1 2 3 3 3 4 5 5 5 6 7 8 9 9 9 29 | test_counting_sort(test2); // 2 2 2 3 3 3 3 4 4 6 6 7 8 8 9 30 | test_counting_sort(test3); // 0 1 1 2 3 4 5 6 7 8 8 9 9 9 9 31 | test_counting_sort(test4); // 0 0 1 2 3 4 4 4 5 5 7 7 8 9 9 32 | test_counting_sort(test5); // 0 0 1 2 2 3 4 5 6 6 6 7 8 8 9 33 | 34 | return 0; 35 | } 36 | 37 | -------------------------------------------------------------------------------- /c-cpp/14_sorts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/14_sorts/.gitkeep -------------------------------------------------------------------------------- /c-cpp/14_sorts/analytics_of_std_sort.md: -------------------------------------------------------------------------------- 1 | # C++ STL 中的 std::sort 分析 2 | 3 | 参见 [Liam Huang 的博客](https://liam.page/)中的 3 篇文章: 4 | 5 | * [谈谈基于比较的排序算法的复杂度下界](https://liam.page/2018/08/28/lower-bound-of-comparation-based-sort-algorithm/) 6 | * [谈谈内省式排序算法](https://liam.page/2018/08/29/introspective-sort/) 7 | * [谈谈 STL 中的 std::sort](https://liam.page/2018/09/18/std-sort-in-STL/) 8 | 9 | -------------------------------------------------------------------------------- /c-cpp/14_sorts/counting_sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void dump(int *arr, int size) 7 | { 8 | int i; 9 | 10 | for (i = 0; i < size; i++) 11 | printf("%08d\n", arr[i]); 12 | } 13 | 14 | // content in arr must be positive integer 15 | void counting_sort(int *arr, int size) 16 | { 17 | int max, i; 18 | int *count, *tmp; 19 | 20 | if (size <= 1) 21 | return; 22 | 23 | max = 0; 24 | // find the biggest integer 25 | for (i = 0; i < size; i++) { 26 | if (max < arr[i]) 27 | max = arr[i]; 28 | } 29 | 30 | // init count to 0 31 | count = (int*)malloc((max+1) * sizeof(int)); 32 | tmp = (int*)malloc(size * sizeof(int)); 33 | if (!count || !tmp) 34 | return; 35 | memset(count, 0, (max + 1) * sizeof(int)); 36 | 37 | // counting 38 | for (i = 0; i < size; i++) 39 | count[arr[i]]++; 40 | for (i = 1; i < max + 1; i++) 41 | count[i] = count[i-1] + count[i]; 42 | 43 | // iterate arr and put it to the correct index in tmp 44 | for (i = 0; i < size; i++){ 45 | int index = count[arr[i]] - 1; 46 | tmp[index] = arr[i]; 47 | count[arr[i]]--; 48 | } 49 | 50 | // move back to arr 51 | memcpy(arr, tmp, size * sizeof(int)); 52 | } 53 | 54 | void counting_sort_test() 55 | { 56 | int test_data[10] = {3, 23, 98, 1, 27, 36, 52, 89, 76, 44}; 57 | 58 | counting_sort(test_data, 10); 59 | dump(test_data, 10); 60 | } 61 | 62 | int main() 63 | { 64 | counting_sort_test(); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /c-cpp/15_bsearch/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/15_bsearch/.gitkeep -------------------------------------------------------------------------------- /c-cpp/15_bsearch/binary_search.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | typedef int(*bs)(int *arr, int size, int val); 7 | 8 | int binary_search_r(int *arr, int size, int val) 9 | { 10 | int mid = size / 2; 11 | int idx; 12 | 13 | if (arr[mid] == val) 14 | return mid; 15 | 16 | // mid == 0 means size == 1 17 | // so the only element in array doesn't equal to val 18 | if (!mid) 19 | return -1; 20 | 21 | if (arr[mid] < val) { 22 | idx = binary_search_r(arr + mid + 1, size - mid - 1, val); 23 | if (idx != -1) 24 | idx += mid + 1; 25 | } else { 26 | idx = binary_search_r(arr, mid, val); 27 | } 28 | 29 | return idx; 30 | } 31 | 32 | int binary_search_i(int *arr, int size, int val) 33 | { 34 | int low = 0, high = size - 1, mid; 35 | 36 | while (low <= high) { 37 | mid = (low + high) / 2; 38 | if (arr[mid] == val) 39 | return mid; 40 | 41 | if (arr[mid] < val) 42 | low = mid + 1; 43 | else 44 | high = mid - 1; 45 | } 46 | 47 | return -1; 48 | } 49 | 50 | void iteratioin_test(bs binary_search) 51 | { 52 | int arr[10] = {1, 4, 5, 9, 12, 19, 21, 28, 31, 36}; 53 | int idx; 54 | 55 | idx = binary_search(arr, 10, 12); 56 | if (idx != -1) 57 | printf("find 12 at %d\n", idx); 58 | else 59 | printf("12 not in arr \n"); 60 | 61 | idx = binary_search(arr, 10, 13); 62 | if (idx != -1) 63 | printf("find 13 at %d\n", idx); 64 | else 65 | printf("13 not in arr \n"); 66 | 67 | idx = binary_search(arr, 10, 1); 68 | if (idx != -1) 69 | printf("find 1 at %d\n", idx); 70 | else 71 | printf("1 not in arr \n"); 72 | 73 | idx = binary_search(arr, 10, 36); 74 | if (idx != -1) 75 | printf("find 36 at %d\n", idx); 76 | else 77 | printf("36 not in arr \n"); 78 | 79 | idx = binary_search(arr, 10, 31); 80 | if (idx != -1) 81 | printf("find 31 at %d\n", idx); 82 | else 83 | printf("31 not in arr \n"); 84 | 85 | } 86 | 87 | int main() 88 | { 89 | printf("=== Test iteration version:\n"); 90 | iteratioin_test(binary_search_i); 91 | 92 | printf("=== Test recursive version:\n"); 93 | iteratioin_test(binary_search_r); 94 | 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /c-cpp/15_bsearch/bsearch.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/24. 3 | */ 4 | 5 | #ifndef BSEARCH_BSEARCH_HPP_ 6 | #define BSEARCH_BSEARCH_HPP_ 7 | 8 | #include 9 | #include 10 | 11 | // Liam Huang: The algorithm works right with iterators that meet the ForwardIterator requirement, 12 | // but with a bad time complexity. For better performance, iterators should meet 13 | // the RandomAccessIterator requirement. 14 | template ::value_type, 16 | typename Compare = std::less> 17 | IterT bsearch(IterT first, 18 | IterT last, 19 | ValueT target, 20 | Compare comp = Compare()) { 21 | IterT result = last; 22 | while (std::distance(first, last) > 0) { 23 | IterT mid = first + std::distance(first, last) / 2; 24 | if (comp(*mid, target)) { 25 | first = mid + 1; 26 | } else if (comp(target, *mid)) { 27 | last = mid; 28 | } else { // equal 29 | result = mid; 30 | break; 31 | } 32 | } 33 | return result; 34 | } 35 | 36 | #endif // BSEARCH_BSEARCH_HPP_ 37 | 38 | -------------------------------------------------------------------------------- /c-cpp/15_bsearch/bsearch_c/bsearch.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: bsearch.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-21 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | int mybsearch(int a[],int size,int value) 14 | { 15 | int mid = 0; 16 | int left = 0; 17 | int right = size - 1; 18 | 19 | while(left <= right) 20 | { 21 | /*防止size数量太大是,(left + right)数据翻转,导致问题*/ 22 | mid = left + ((right - left)>>1); 23 | 24 | if (a[mid] == value) 25 | { 26 | return mid; 27 | } 28 | else if (a[mid] < value) 29 | { 30 | left = mid + 1; 31 | } 32 | else 33 | { 34 | right = mid - 1; 35 | } 36 | } 37 | 38 | return -1; 39 | } 40 | 41 | int helper(int a[], int left,int right,int value) 42 | { 43 | int mid = 0; 44 | 45 | if (left > right) 46 | { 47 | return -1; 48 | } 49 | /*防止size数量太大是,(left + right)数据翻转,导致问题*/ 50 | mid = left + ((right - left)>>1); 51 | if (a[mid] == value) 52 | { 53 | return mid; 54 | } 55 | else if (a[mid] < value) 56 | { 57 | return helper(a,mid + 1,right,value); 58 | } 59 | else 60 | { 61 | return helper(a,left,mid - 1,value); 62 | } 63 | return -1; 64 | } 65 | /*递归实现*/ 66 | int mybsearch_2(int a[],int size,int value) 67 | { 68 | 69 | return helper(a,0,size-1,value); 70 | } 71 | 72 | int main() 73 | { 74 | int a[10] = {5,6,8,9,10,11,23,42,53,123}; 75 | int data = 0; 76 | int res = 0; 77 | 78 | printf("\r\n输入一个整数"); 79 | scanf("%d",&data); 80 | res = mybsearch(a,10,data); 81 | printf("data[%d] %s 在数据中,下标是%d",data,(res != -1)?"":"不",res); 82 | 83 | printf("\r\n输入一个整数"); 84 | scanf("%d",&data); 85 | res = mybsearch_2(a,10,data); 86 | printf("data[%d] %s 在数据中,下标是%d",data,(res != -1)?"":"不",res); 87 | return; 88 | } 89 | -------------------------------------------------------------------------------- /c-cpp/15_bsearch/bsearch_c/sqrt.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: sqrt.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-31 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | /*求解精度设置*/ 15 | #define E 0.000001 16 | double mybsearch(double num) 17 | { 18 | double start = 1.0; 19 | double end = num; 20 | double mid = 0.0; 21 | while(1) 22 | { 23 | mid = (start + end)/2; 24 | if(((mid*mid - num) <= E) && ((mid*mid - num) >= -E)) 25 | { 26 | return mid; 27 | } 28 | 29 | if ((mid*mid - num) > E) 30 | { 31 | end = mid; 32 | } 33 | else 34 | { 35 | start = mid; 36 | } 37 | } 38 | 39 | return 0; 40 | } 41 | 42 | 43 | int main() 44 | { 45 | double num = 0.0; 46 | 47 | /*这里需要注意:double的输入方式*/ 48 | scanf("%lf",&num); 49 | printf("\r\n num %lf的平方根是%lf",num,mybsearch(num)); 50 | 51 | return 0; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /c-cpp/15_bsearch/bsearch_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/24. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #include "bsearch.hpp" 9 | 10 | template 11 | void test_bsearch(const VecT& test, T target) { 12 | auto it = bsearch(test.begin(), test.end(), target); 13 | std::cout << std::distance(test.begin(), it) << std::endl; 14 | } 15 | 16 | int main() { 17 | std::vector test{0, 0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 5, 6, 7}; // std::less() 18 | 19 | test_bsearch(test, 8); // 14 20 | test_bsearch(test, -1); // 14 21 | test_bsearch(test, 0); // 0, 1 22 | test_bsearch(test, 4); // 5, 6 23 | test_bsearch(test, 5); // 7, 8, 9, 10, 11 24 | test_bsearch(test, 7); // 13 25 | 26 | return 0; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /c-cpp/16_bsearch/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/16_bsearch/.gitkeep -------------------------------------------------------------------------------- /c-cpp/16_bsearch/bsearch_varients.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/26. 3 | */ 4 | 5 | #ifndef BSEARCH_BSEARCH_VARIENTS_HPP_ 6 | #define BSEARCH_BSEARCH_VARIENTS_HPP_ 7 | 8 | #include 9 | #include 10 | 11 | enum class BsearchPolicy { UNSPECIFIED, FIRST, LAST, FIRST_NOT_LESS, LAST_NOT_GREATER }; 12 | 13 | // Liam Huang: The algorithm works right with iterators that meet the ForwardIterator requirement, 14 | // but with a bad time complexity. For better performance, iterators should meet 15 | // the RandomAccessIterator requirement. 16 | template ::value_type, 18 | typename Compare> 19 | IterT bsearch(IterT first, 20 | IterT last, 21 | ValueT target, 22 | Compare comp, 23 | BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) { 24 | IterT result = last; 25 | while (std::distance(first, last) > 0) { 26 | IterT mid = first + std::distance(first, last) / 2; 27 | if (policy == BsearchPolicy::FIRST_NOT_LESS) { 28 | if (!comp(*mid, target)) { 29 | if (mid == first or comp(*(mid - 1), target)) { 30 | result = mid; 31 | break; 32 | } else { 33 | last = mid; 34 | } 35 | } else { 36 | first = mid + 1; 37 | } 38 | } else if (policy == BsearchPolicy::LAST_NOT_GREATER) { 39 | if (comp(target, *mid)) { 40 | last = mid; 41 | } else { 42 | if (std::distance(mid, last) == 1 or comp(target, *(mid + 1))) { 43 | result = mid; 44 | break; 45 | } else { 46 | first = mid + 1; 47 | } 48 | } 49 | } else { // policy == UNSPECIFIED or FIRST or LAST 50 | if (comp(*mid, target)) { 51 | first = mid + 1; 52 | } else if (comp(target, *mid)) { 53 | last = mid; 54 | } else { // equal 55 | if (policy == BsearchPolicy::FIRST) { 56 | if (mid == first or comp(*(mid - 1), *mid)) { 57 | result = mid; 58 | break; 59 | } else { 60 | last = mid; 61 | } 62 | } else if (policy == BsearchPolicy::LAST) { 63 | if (std::distance(mid, last) == 1 or comp(*mid, *(mid + 1))) { 64 | result = mid; 65 | break; 66 | } else { 67 | first = mid + 1; 68 | } 69 | } else { 70 | result = mid; 71 | break; 72 | } 73 | } 74 | } 75 | } 76 | return result; 77 | } 78 | 79 | template ::value_type, 81 | typename Compare = std::less> 82 | IterT bsearch(IterT first, 83 | IterT last, 84 | ValueT target, 85 | BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) { 86 | return bsearch(first, last, target, Compare(), policy); 87 | } 88 | 89 | #endif // BSEARCH_BSEARCH_VARIENTS_HPP_ 90 | 91 | -------------------------------------------------------------------------------- /c-cpp/16_bsearch/bsearch_varients_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/26. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #include "bsearch_varients.hpp" 9 | 10 | template 11 | void test_bsearch(const VecT& test, 12 | T target, 13 | BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) { 14 | auto it = bsearch(test.begin(), test.end(), target, policy); 15 | std::cout << std::distance(test.begin(), it) << std::endl; 16 | } 17 | 18 | int main() { 19 | std::vector test{0, 0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 5, 6, 8}; // std::less() 20 | 21 | test_bsearch(test, 8); // 14 22 | test_bsearch(test, -1); // 14 23 | test_bsearch(test, 0); // 0, 1 24 | test_bsearch(test, 0, BsearchPolicy::FIRST); // 0 25 | test_bsearch(test, 0, BsearchPolicy::LAST); // 1 26 | test_bsearch(test, 4); // 5, 6 27 | test_bsearch(test, 4, BsearchPolicy::FIRST); // 5 28 | test_bsearch(test, 4, BsearchPolicy::LAST); // 6 29 | test_bsearch(test, 5); // 7, 8, 9, 10, 11 30 | test_bsearch(test, 5, BsearchPolicy::FIRST); // 7 31 | test_bsearch(test, 5, BsearchPolicy::LAST); // 11 32 | test_bsearch(test, 7, BsearchPolicy::FIRST_NOT_LESS); // 13 33 | test_bsearch(test, 7, BsearchPolicy::LAST_NOT_GREATER); // 12 34 | test_bsearch(test, 7, BsearchPolicy::FIRST); // 14 35 | test_bsearch(test, 8); // 13 36 | test_bsearch(test, 8, BsearchPolicy::FIRST); // 13 37 | test_bsearch(test, 8, BsearchPolicy::LAST); // 13 38 | 39 | return 0; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /c-cpp/17_skiplist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/17_skiplist/.gitkeep -------------------------------------------------------------------------------- /c-cpp/17_skiplist/SkipList.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/17_skiplist/SkipList.cpp -------------------------------------------------------------------------------- /c-cpp/17_skiplist/skiplist_c/skiplist.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: skiplist.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-31 6 | > Desc: 7 | ************************************************************************/ 8 | #ifndef __SKIP_LIST_H__ 9 | #define __SKIP_LIST_H__ 10 | 11 | 12 | typedef struct _node 13 | { 14 | int key; /*key是唯一的*/ 15 | int value; /*存储的内容*/ 16 | int max_level; /*当前节点最大层数*/ 17 | struct _node *next[0];/*level层链表结构*/ 18 | }node; 19 | 20 | typedef struct _skiplist 21 | { 22 | int level; 23 | int count; 24 | node *head; 25 | }skiplist; 26 | 27 | /*根据当前结构体元素的地址,获取到结构体首地址*/ 28 | #define offsetof(TYPE,MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 29 | #define container(ptr,type,member) ({\ 30 | const typeof( ((type *)0)->member) *__mptr = (ptr);\ 31 | (type *) ( (char *)__mptr - offsetof(type,member));}) 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /c-cpp/17_skiplist/skiplist_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/30. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #include "skiplist.hpp" 9 | 10 | int main() { 11 | // 1. Initialize a skip list for test 12 | // * default constructor 13 | // * constructor with initializer list 14 | // * insert 15 | skiplist ss{"1", "2", "3", "4", "5"}; 16 | 17 | // 1a. show 18 | // * print 19 | ss.print(std::cout); 20 | std::cout << std::endl; 21 | 22 | // 2. move construction 23 | // * move constructor 24 | skiplist s(std::move(ss)); 25 | 26 | // 2a. show 27 | // * print 28 | s.print(std::cout); 29 | std::cout << std::endl; 30 | 31 | // 3.a find something doesn't exist. 32 | // * find 33 | auto f = s.find("0"); 34 | if (!f.empty()) { 35 | std::cout << "Node found!\nvalue: " << f << '\n'; 36 | } else { 37 | std::cout << "Node NOT found!\n"; 38 | } 39 | 40 | // 3.b find something does exist. 41 | // * find 42 | auto ff = s.find("1"); 43 | if (!ff.empty()) { 44 | std::cout << "Node found!\tvalue: " << ff << '\n'; 45 | } else { 46 | std::cout << "Node NOT found!\n"; 47 | } 48 | 49 | // 4. insert() - reassign 50 | s.insert("TEST"); 51 | 52 | // 4a. print() 53 | s.print(std::cout); 54 | std::cout << std::endl; 55 | 56 | // 5. erase() 57 | s.erase("TEST"); 58 | 59 | // 5a. print(); 60 | s.print(std::cout); 61 | std::cout << std::endl; 62 | 63 | std::cout << "\nDone!\n"; 64 | 65 | return 0; 66 | // 6. destructor 67 | } 68 | -------------------------------------------------------------------------------- /c-cpp/17_skiplist/skiplist_tr_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/10/30. 3 | */ 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "skiplist_tr.hpp" 11 | 12 | int main() { 13 | // 1. UT for skiplist_detail::random_level 14 | skiplist_detail::random_level rl(5, 0.5); 15 | std::map hist; 16 | for (size_t i = 0; i != 10000; ++i) { 17 | ++hist[rl()]; 18 | } 19 | for (auto p : hist) { 20 | std::cout << p.first << ' ' << std::string(p.second / 100, '*') << '\n'; 21 | } 22 | 23 | // 2. UT for skiplist(), init_internally(), size(), empty() 24 | skiplist sl_default; 25 | assert(sl_default.empty()); 26 | // 2.1. UT for grow with abandon 27 | sl_default.grow(1); 28 | assert(sl_default.capability() == 4); 29 | // 2.2. UT for grow 30 | sl_default.grow(10); 31 | assert(sl_default.capability() == 1024); 32 | 33 | // 3. UT for constructor of initializer_list and InputIt, init_internally(), insert(), 34 | // find_predecessors() 35 | skiplist sl{"hello", "world", "!"}; 36 | assert(not sl.empty()); 37 | assert(3 == sl.size()); 38 | 39 | // 4. UT for find() find_helper() 40 | auto search = sl_default.find("nonexist"); 41 | assert(search == sl_default.cend()); 42 | assert(search == sl_default.end()); 43 | search = sl.find("hello"); 44 | assert(search != sl.cend()); 45 | assert(search != sl.end()); 46 | search = sl.find("nonexist"); 47 | assert(search == sl.cend()); 48 | assert(search == sl.end()); 49 | 50 | // 5. UT for insert(), find_predecessors() 51 | // 5.1. UT for insert a already-exist item 52 | sl.insert("hello"); 53 | search = sl.find("hello"); 54 | assert(search != sl.cend()); 55 | assert(search != sl.end()); 56 | // 5.2. UT for insert a new incoming item 57 | search = sl.find("now exist"); 58 | assert(search == sl.cend()); 59 | assert(search == sl.end()); 60 | sl.insert("now exist"); 61 | search = sl.find("now exist"); 62 | assert(search != sl.cend()); 63 | assert(search != sl.end()); 64 | 65 | // 6. UT for erase(), find_predecessors() 66 | sl.insert("hello"); 67 | sl.insert("hello"); 68 | sl.insert("hello"); 69 | sl.insert("hello"); 70 | // 6.1. UT for erase single item 71 | sl.erase("hello", erase_policy::SINGLE); 72 | search = sl.find("hello"); 73 | assert(search != sl.cend()); 74 | assert(search != sl.end()); 75 | // 6.2. UT for erase all items 76 | sl.erase("hello", erase_policy::ALL); 77 | search = sl.find("hello"); 78 | assert(search == sl.cend()); 79 | assert(search == sl.end()); 80 | // 6.3 UT for erase non-exist item 81 | sl.erase("nonexist"); 82 | 83 | // 7. UT for insert() behind erase() 84 | // 7.1. different word 85 | sl.insert("world"); 86 | search = sl.find("world"); 87 | assert(search != sl.cend()); 88 | assert(search != sl.end()); 89 | assert(search->values.count("world") == 2); 90 | // 7.1. same word, also UT for grow() 91 | search = sl.find("hello"); 92 | assert(search == sl.cend()); 93 | assert(search == sl.end()); 94 | sl.insert("hello"); 95 | sl.insert("hello"); 96 | sl.insert("hello"); 97 | sl.insert("hello"); 98 | sl.insert("hello"); 99 | search = sl.find("hello"); 100 | assert(search != sl.cend()); 101 | assert(search != sl.end()); 102 | assert(search->values.count("hello") == 5); 103 | 104 | return 0; 105 | // 8. UT for ~skiplist() 106 | } 107 | 108 | -------------------------------------------------------------------------------- /c-cpp/18_hashtable/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/c-cpp/18_hashtable/.gitkeep -------------------------------------------------------------------------------- /c-cpp/18_hashtable/hash_map.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Liam Huang (Liam0205) on 2018/08/14. 3 | * This is an old test file for hash_map, created by Liam. 4 | * Just for showing the inner logic for hash_map class template. 5 | * Original posted on: 6 | * https://github.com/Liam0205/leetcode/tree/master/met/hash_map.cc 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | template > 16 | class hash_map { 17 | public: 18 | using key_type = Key; 19 | using mapped_type = T; 20 | using value_type = std::pair; 21 | using size_type = size_t; 22 | using hasher = std::hash; 23 | 24 | private: // helper 25 | using wrapper = std::shared_ptr; 26 | 27 | public: // constructor 28 | hash_map() { 29 | container_.resize(primes_[size_level_]); 30 | } 31 | 32 | public: // capacity 33 | bool empty() const { return empty_; } 34 | size_type size() const { return size_; } 35 | size_type max_size() const { return primes_[size_level_]; } 36 | 37 | public: // find and modify 38 | mapped_type& operator[](const key_type& key) { 39 | auto hashed = find_hash(key); 40 | if (not(container_[hashed]) and construct_new_on_position(hashed, key) and 41 | load_factor() > max_load_factor()) { 42 | expand(); 43 | } 44 | return container_[hashed]->second; 45 | } 46 | 47 | public: // hash policy 48 | double load_factor() const { return static_cast(size()) / max_size(); } 49 | double max_load_factor() const { return max_load_factor_; } 50 | void expand() const { 51 | ++size_level_; 52 | std::vector temp; 53 | temp.resize(primes_[size_level_]); 54 | for (auto w : container_) { 55 | if (nullptr != w) { 56 | auto hashed = find_hash(w->first); 57 | temp[hashed] = w; 58 | } 59 | } 60 | container_ = std::move(temp); 61 | } 62 | 63 | private: // helper functions 64 | size_type find_hash(const key_type& key) const { 65 | const size_t csz = container_.size(); 66 | size_t count = 0; 67 | size_t hashed = hasher_(key) % csz; 68 | while (nullptr != container_[hashed] and container_[hashed]->first != key) { 69 | hashed = (hashed + ++count) % csz; 70 | } 71 | return hashed; 72 | } 73 | bool construct_new_on_position(const size_type pos, const key_type& key) { 74 | empty_ = false; 75 | ++size_; 76 | container_[pos] = std::make_shared(std::make_pair(key, mapped_type())); 77 | return true; 78 | } 79 | 80 | private: 81 | const hasher hasher_ = hasher(); 82 | mutable size_t size_level_ = 0; 83 | mutable std::vector container_; 84 | static const size_t primes_[]; 85 | bool empty_ = true; 86 | size_type size_ = 0; 87 | double max_load_factor_ = 0.75; 88 | }; 89 | template 90 | const size_t hash_map::primes_[] = {7, 17, 29, 53, 101, 211, 401, 809, 1601, 3203}; // ... 91 | 92 | int main() { 93 | hash_map test; 94 | test[1]; 95 | test[2] = 2; 96 | std::cout << test[1] << ' ' << test[2] << std::endl; 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /c-cpp/18_hashtable/listhash/listhash.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: listhash.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-11-06 6 | > Desc: 根据linux内核模块hashtab编写用户层hashtab接口 7 | linux-4.19.1\security\selinux\ss\hashtab.c 8 | linux-4.19.1\security\selinux\ss\hashtab.h 9 | ************************************************************************/ 10 | 11 | 12 | #ifndef __HASHTAB_H__ 13 | #define __HASHTAB_H__ 14 | 15 | 16 | typedef struct _hashtab_node 17 | { 18 | void * key; 19 | void * data; 20 | struct _hashtab_node *next; 21 | }hashtab_node; 22 | 23 | typedef struct _hashtab 24 | { 25 | hashtab_node **htables; /*哈希桶*/ 26 | int size; /*哈希桶的最大数量*/ 27 | int nel; /*哈希桶中元素的个数*/ 28 | int (*hash_value)(struct _hashtab *h,const void *key); /*哈希函数*/ 29 | int (*keycmp)(struct _hashtab *h,const void *key1,const void *key2);/*哈希key比较函数,当哈希数值一致时使用*/ 30 | void (*hash_node_free)(hashtab_node *node); 31 | }hashtab; 32 | 33 | 34 | #define HASHTAB_MAX_NODES (0xffffffff) 35 | 36 | typedef int (*hash_key_func)(struct _hashtab *h,const void *key); /*哈希函数*/ 37 | typedef int (*keycmp_func)(struct _hashtab *h,const void *key1,const void *key2);/*哈希key比较函数,当哈希数值一致时使用*/ 38 | typedef void (*hash_node_free_func)(hashtab_node *node); 39 | /*根据当前结构体元素的地址,获取到结构体首地址*/ 40 | #define offsetof(TYPE,MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 41 | #define container(ptr,type,member) ({\ 42 | const typeof( ((type *)0)->member) *__mptr = (ptr);\ 43 | (type *) ( (char *)__mptr - offsetof(type,member));}) 44 | 45 | 46 | hashtab * hashtab_create(int size,hash_key_func hash_value, 47 | keycmp_func keycmp,hash_node_free_func hash_node_free); 48 | void hashtab_destory(hashtab *h); 49 | int hashtab_insert(hashtab * h,void *key,void *data); 50 | hashtab_node *hashtab_delete(hashtab *h, void *key); 51 | void *hashtab_search(hashtab*h,void *key); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /c-cpp/19_Dlisthash/Dlist.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: Dlist.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-11-08 6 | > Desc: linux内核源码双向链表实现include/linux/list.h 7 | ************************************************************************/ 8 | #ifndef _LIST_HEAD_H 9 | #define _LIST_HEAD_H 10 | 11 | // 双向链表节点 12 | struct list_head { 13 | struct list_head *next, *prev; 14 | }; 15 | 16 | // 初始化节点:设置name节点的前继节点和后继节点都是指向name本身。 17 | #define LIST_HEAD_INIT(name) { &(name), &(name) } 18 | 19 | // 定义表头(节点):新建双向链表表头name,并设置name的前继节点和后继节点都是指向name本身。 20 | #define LIST_HEAD(name) \ 21 | struct list_head name = LIST_HEAD_INIT(name) 22 | 23 | // 初始化节点:将list节点的前继节点和后继节点都是指向list本身。 24 | static inline void INIT_LIST_HEAD(struct list_head *list) 25 | { 26 | list->next = list; 27 | list->prev = list; 28 | } 29 | 30 | // 添加节点:将new插入到prev和next之间。 31 | static inline void __list_add(struct list_head *new, 32 | struct list_head *prev, 33 | struct list_head *next) 34 | { 35 | next->prev = new; 36 | new->next = next; 37 | new->prev = prev; 38 | prev->next = new; 39 | } 40 | 41 | // 添加new节点:将new添加到head之后,是new称为head的后继节点。 42 | static inline void list_add(struct list_head *new, struct list_head *head) 43 | { 44 | __list_add(new, head, head->next); 45 | } 46 | 47 | // 添加new节点:将new添加到head之前,即将new添加到双链表的末尾。 48 | static inline void list_add_tail(struct list_head *new, struct list_head *head) 49 | { 50 | __list_add(new, head->prev, head); 51 | } 52 | 53 | // 从双链表中删除entry节点。 54 | static inline void __list_del(struct list_head * prev, struct list_head * next) 55 | { 56 | next->prev = prev; 57 | prev->next = next; 58 | } 59 | 60 | // 从双链表中删除entry节点。 61 | static inline void list_del(struct list_head *entry) 62 | { 63 | __list_del(entry->prev, entry->next); 64 | } 65 | 66 | // 从双链表中删除entry节点。 67 | static inline void __list_del_entry(struct list_head *entry) 68 | { 69 | __list_del(entry->prev, entry->next); 70 | } 71 | 72 | // 从双链表中删除entry节点,并将entry节点的前继节点和后继节点都指向entry本身。 73 | static inline void list_del_init(struct list_head *entry) 74 | { 75 | __list_del_entry(entry); 76 | INIT_LIST_HEAD(entry); 77 | } 78 | 79 | // 用new节点取代old节点 80 | static inline void list_replace(struct list_head *old, 81 | struct list_head *new) 82 | { 83 | new->next = old->next; 84 | new->next->prev = new; 85 | new->prev = old->prev; 86 | new->prev->next = new; 87 | } 88 | 89 | // 双链表是否为空 90 | static inline int list_empty(const struct list_head *head) 91 | { 92 | return head->next == head; 93 | } 94 | 95 | // 获取"MEMBER成员"在"结构体TYPE"中的位置偏移 96 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 97 | 98 | // 根据"结构体(type)变量"中的"域成员变量(member)的指针(ptr)"来获取指向整个结构体变量的指针 99 | #define container_of(ptr, type, member) ({ \ 100 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 101 | (type *)( (char *)__mptr - offsetof(type,member) );}) 102 | 103 | // 遍历双向链表 104 | #define list_for_each(pos, head) \ 105 | for (pos = (head)->next; pos != (head); pos = pos->next) 106 | 107 | #define list_for_each_safe(pos, n, head) \ 108 | for (pos = (head)->next, n = pos->next; pos != (head); \ 109 | pos = n, n = pos->next) 110 | 111 | #define list_entry(ptr, type, member) \ 112 | container_of(ptr, type, member) 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /c-cpp/19_Dlisthash/LinkedHashMap.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: LinkedHashMap.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-11-08 6 | > Desc: 7 | ************************************************************************/ 8 | 9 | 10 | #ifndef __LINKED_HASH_MAP__ 11 | #define __LINKED_HASH_MAP__ 12 | 13 | /*数据存放节点*/ 14 | typedef struct _lisked_hash_map_node 15 | { 16 | void *key; /*键*/ 17 | void *data; /*数据*/ZZ 18 | struct _lisked_hash_map_node *next; /*哈希冲突时,用来挂接后续节点*/ 19 | struct list_head Dlist_node;/*用来挂接双向链表*/ 20 | }LiskedHashMapNode; 21 | 22 | typedef struct _lisked_hash_map 23 | { 24 | LiskedHashMapNode **hTabs;/*哈希桶*/ 25 | struct list_head header;/*双向循环链表头*/ 26 | int size; /**/ 27 | int nel_max; /*支持最大节点数*/ 28 | int nel; /*当前节点数*/ 29 | int (*hash_value)(struct _lisked_hash_map *h,const void *key); /*哈希函数*/ 30 | int (*keycmp)(struct _lisked_hash_map *h,const void *key1,const void *key2);/*哈希key比较函数,当哈希数值一致时使用*/ 31 | void (*hash_node_free)(LiskedHashMapNode *node,int flg);/*用来释放节点内存*/ 32 | 33 | }LinkedHashMap; 34 | 35 | typedef int (*hash_value_func)(struct _lisked_hash_map *h,const void *key); /*哈希函数*/ 36 | typedef int (*keycmp_func)(struct _lisked_hash_map *h,const void *key1,const void *key2);/*哈希key比较函数,当哈希数值一致时使用*/ 37 | typedef void (*hash_node_free_func)(LiskedHashMapNode *node,int flg); 38 | 39 | LiskedHashMapNode * LinkedHashMap_delete(LinkedHashMap *h,void *key); 40 | #endif 41 | -------------------------------------------------------------------------------- /c-cpp/23_binarytree/binarytree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* Implement binary tree in array */ 8 | 9 | #define MAX_TREE_NODES (1 << 8) 10 | 11 | struct node { 12 | int data; 13 | }; 14 | 15 | struct binary_tree { 16 | union { 17 | unsigned long nodes; 18 | struct node *n[MAX_TREE_NODES]; 19 | }; 20 | }; 21 | 22 | void init_binary_tree(struct binary_tree *tree) 23 | { 24 | int i; 25 | 26 | for(i = 0; i < MAX_TREE_NODES; i++) { 27 | tree->n[i] = NULL; 28 | } 29 | } 30 | 31 | struct node* create_node(int data) 32 | { 33 | struct node* n; 34 | 35 | n = malloc(sizeof(struct node)); 36 | 37 | if (n) 38 | n->data = data; 39 | 40 | return n; 41 | } 42 | 43 | void fake_a_tree(struct binary_tree* tree) 44 | { 45 | /* data is in ordered */ 46 | int i, data[10] = {7, 4, 9, 2, 6, 8, 10, 1, 3, 5}; 47 | 48 | init_binary_tree(tree); 49 | 50 | /* root start at 1 */ 51 | for (i = 0; i < 10; i++) 52 | tree->n[i+1] = create_node(data[i]); 53 | 54 | tree->nodes = 10; 55 | } 56 | 57 | void _in_order(struct binary_tree* tree, int index) 58 | { 59 | if (!tree->n[index]) 60 | return; 61 | 62 | /* left child at (index << 1) */ 63 | _in_order(tree, index << 1); 64 | 65 | printf("[%2d]: %4d\n", index, tree->n[index]->data); 66 | 67 | /* right child at (index << 1) + 1 */ 68 | _in_order(tree, (index << 1) + 1); 69 | } 70 | 71 | void in_order(struct binary_tree* tree) 72 | { 73 | _in_order(tree, 1); 74 | } 75 | 76 | int main() 77 | { 78 | struct binary_tree tree; 79 | 80 | fake_a_tree(&tree); 81 | in_order(&tree); 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /c-cpp/23_binarytree/tree/list_queue.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: list_queue.c 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-13 6 | > Desc: 7 | ************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | #include"./list_queue.h" 12 | 13 | /*创建队列头*/ 14 | list_queue *list_queue_create() 15 | { 16 | list_queue * queue = NULL; 17 | 18 | queue = (list_queue *)malloc(sizeof(list_queue)); 19 | if(queue == NULL) 20 | { 21 | return NULL; 22 | } 23 | 24 | queue->num = 0; 25 | queue->head = NULL; 26 | queue->tail = NULL; 27 | 28 | return queue; 29 | } 30 | int list_queue_enqueue(list_queue *queue,void *data) 31 | { 32 | queue_node *ptmp = NULL; 33 | 34 | if(queue == NULL) 35 | { 36 | return -1; 37 | } 38 | 39 | ptmp = (queue_node *)malloc(sizeof(queue_node)); 40 | if (ptmp == NULL) 41 | { 42 | return -1; 43 | } 44 | 45 | ptmp->data = data; 46 | ptmp->next = NULL; 47 | if (queue->head == NULL) 48 | { 49 | queue->head = ptmp; 50 | } 51 | else 52 | { 53 | queue->tail->next = ptmp; 54 | 55 | } 56 | queue->tail = ptmp; 57 | queue->num++; 58 | 59 | return 0; 60 | } 61 | 62 | /*出队*/ 63 | int list_queue_dequeue(list_queue *queue,void **data) 64 | { 65 | queue_node * ptmp = NULL; 66 | 67 | if ((queue == NULL) || (data == NULL) || list_queue_is_empty(queue)) 68 | { 69 | return -1; 70 | } 71 | 72 | *data = queue->head->data; 73 | ptmp = queue->head; 74 | queue->head = queue->head->next; 75 | queue->num--; 76 | 77 | if (queue->head == NULL) 78 | { 79 | queue->tail = NULL; 80 | } 81 | 82 | 83 | free(ptmp); 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /c-cpp/23_binarytree/tree/list_queue.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: list_queue.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-10-13 6 | > Desc: 7 | ************************************************************************/ 8 | 9 | #ifndef LINK_LIST_QUEUE_H 10 | #define LINK_LIST_QUEUE_H 11 | 12 | typedef struct _list_queue_node 13 | { 14 | void *data; 15 | struct _list_queue_node *next; 16 | }queue_node; 17 | 18 | typedef struct _list_queue 19 | { 20 | int num; 21 | queue_node *head; 22 | queue_node *tail; 23 | }list_queue; 24 | 25 | #define list_queue_is_empty(queue) ((queue->num) == 0) 26 | list_queue *list_queue_create(); 27 | int list_queue_enqueue(list_queue *queue,void *data); 28 | int list_queue_dequeue(list_queue *queue,void **data); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /c-cpp/24_binarysearchtree/binarysearchtree.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: binarysearchtree.h 3 | > Author: jinshaohui 4 | > Mail: jinshaohui789@163.com 5 | > Time: 18-11-12 6 | > Desc: 7 | ************************************************************************/ 8 | #ifndef __BINARY_SEARCH_TREE__ 9 | #define __BINARY_SEARCH_TREE__ 10 | typedef int mytype; 11 | 12 | typedef struct _bstree_node 13 | { 14 | mytype data; 15 | struct _bstree_node *lchild; 16 | struct _bstree_node *rchild; 17 | }bstree_node; 18 | 19 | typedef struct _bstree 20 | { 21 | int size; 22 | int (*compare)(mytype key1,mytype key2); 23 | int (*destory)(mytype data); 24 | bstree_node *root; 25 | }bstree; 26 | 27 | typedef int (*compare_fuc)(mytype key1,mytype key2); 28 | typedef int (*destory_fuc)(mytype data); 29 | 30 | #define bstree_is_empty(tree) (tree->size == 0) 31 | 32 | bstree *bstree_create(compare_fuc compare,destory_fuc destory); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /c-cpp/24_binarysearchtree/bst.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | enum child_dir { 8 | left_child, 9 | right_child, 10 | root, 11 | }; 12 | 13 | struct node { 14 | unsigned long data; 15 | struct node *left; 16 | struct node *right; 17 | }; 18 | 19 | struct root { 20 | struct node *r; 21 | }; 22 | 23 | void dump(struct node *node, int level, enum child_dir dir) 24 | { 25 | if (!node) 26 | return; 27 | 28 | dump(node->right, level + 1, right_child); 29 | 30 | if (dir == left_child) 31 | printf("%*s\n", level*3, "|"); 32 | 33 | printf("%*s - %05lu\n", level*3, " ", node->data); 34 | 35 | if (dir == right_child) 36 | printf("%*s\n", level*3, "|"); 37 | 38 | dump(node->left, level + 1, left_child); 39 | } 40 | 41 | struct node* find(struct root *root, unsigned long data) 42 | { 43 | struct node* n = root->r; 44 | 45 | while (n) { 46 | if (n->data == data) 47 | return n; 48 | if (data < n->data) 49 | n = n->left; 50 | else 51 | n = n->right; 52 | } 53 | 54 | return NULL; 55 | } 56 | 57 | struct node* new_node(unsigned long data) 58 | { 59 | struct node *n; 60 | 61 | n = malloc(sizeof(struct node)); 62 | 63 | n->data = data; 64 | n->left = n->right = NULL; 65 | return n; 66 | } 67 | 68 | void insert(struct root *root, struct node *new) 69 | { 70 | struct node *parent; 71 | 72 | if (!root->r) { 73 | root->r = new; 74 | return; 75 | } 76 | 77 | parent = root->r; 78 | 79 | while (true) { 80 | /* Don't support duplicate data */ 81 | if (new->data == parent->data) 82 | break; 83 | 84 | if (new->data < parent->data) { 85 | if (!parent->left) { 86 | parent->left = new; 87 | break; 88 | } 89 | parent = parent->left; 90 | } else { 91 | if (!parent->right) { 92 | parent->right = new; 93 | break; 94 | } 95 | parent = parent->right; 96 | } 97 | } 98 | } 99 | 100 | struct node* delete(struct root *root, unsigned long data) 101 | { 102 | struct node *n = root->r, **p = &root->r; 103 | struct node *child; 104 | 105 | while (n && n->data != data) { 106 | if (data < n->data) { 107 | p = &n->left; 108 | n = n->left; 109 | } else { 110 | p = &n->right; 111 | n = n->right; 112 | } 113 | } 114 | 115 | if (!n) 116 | return NULL; 117 | 118 | if (n->left && n->right) { 119 | struct node *rn = n->right, **rp = &n->right; 120 | 121 | while (rn->left) { 122 | rp = &rn->left; 123 | rn = rn->left; 124 | } 125 | 126 | n->data = rn->data; 127 | n = rn; 128 | p = rp; 129 | } 130 | 131 | child = n->left ? n->left : n->right; 132 | *p = child; 133 | 134 | return NULL; 135 | } 136 | 137 | void insert_test() 138 | { 139 | struct root tree; 140 | struct node* n; 141 | 142 | tree.r = NULL; 143 | 144 | insert(&tree, new_node(9)); 145 | 146 | insert(&tree, new_node(5)); 147 | insert(&tree, new_node(2)); 148 | insert(&tree, new_node(8)); 149 | 150 | insert(&tree, new_node(18)); 151 | insert(&tree, new_node(13)); 152 | insert(&tree, new_node(21)); 153 | insert(&tree, new_node(20)); 154 | 155 | dump(tree.r, 0, root); 156 | 157 | n = find(&tree, 18); 158 | if (n && n->data == 18) 159 | printf("Get 18\n"); 160 | 161 | } 162 | 163 | void delete_test() 164 | { 165 | struct root tree; 166 | struct node* n; 167 | 168 | tree.r = NULL; 169 | 170 | insert(&tree, new_node(9)); 171 | 172 | insert(&tree, new_node(5)); 173 | insert(&tree, new_node(2)); 174 | insert(&tree, new_node(8)); 175 | 176 | insert(&tree, new_node(18)); 177 | insert(&tree, new_node(13)); 178 | insert(&tree, new_node(21)); 179 | insert(&tree, new_node(20)); 180 | 181 | dump(tree.r, 0, root); 182 | 183 | delete(&tree, 20); 184 | printf("Delete 20\n"); 185 | dump(tree.r, 0, root); 186 | 187 | delete(&tree, 9); 188 | printf("Delete 9\n"); 189 | dump(tree.r, 0, root); 190 | } 191 | 192 | int main() 193 | { 194 | //insert_test(); 195 | delete_test(); 196 | return 0; 197 | } 198 | -------------------------------------------------------------------------------- /c-cpp/24_tree/Trie.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > Author: Liu Zhang 3 | > Mail: lz-850610@163.com 4 | > Time: 2019-05-10 5 | > Desc: 字典树实现 6 | ************************************************************************/ 7 | #include 8 | #include 9 | #include 10 | 11 | #define OK 1 12 | #define ERROR 0 13 | #define TRUE 1 14 | #define FALSE 0 15 | 16 | typedef int Status; 17 | 18 | typedef struct Node { 19 | char data; 20 | struct Node *children[26]; 21 | Status end; 22 | } Trie, *TriePtr; 23 | 24 | void Init(TriePtr *T) 25 | { 26 | (*T) = (TriePtr)malloc(sizeof(Trie)); 27 | (*T)->data = '/'; 28 | (*T)->end = FALSE; 29 | } 30 | 31 | void Insert(TriePtr T, char *str) { 32 | 33 | int index; 34 | char c; 35 | 36 | while(c = *str++) 37 | { 38 | index = c - 'a'; 39 | if (T->children[index] == NULL) 40 | { 41 | TriePtr Node; 42 | Node = (TriePtr)malloc(sizeof(Trie)); 43 | Node->data = c; 44 | Node->end = FALSE; 45 | T->children[index] = Node; 46 | } 47 | 48 | T = T->children[index]; 49 | } 50 | 51 | T->end = TRUE; 52 | } 53 | 54 | 55 | Status Search(TriePtr T, char *str) { 56 | 57 | int index; 58 | char c; 59 | 60 | while(c = *str++) 61 | { 62 | index = c - 'a'; 63 | if (T->children[index] == NULL) 64 | { 65 | return FALSE; 66 | } 67 | 68 | T = T->children[index]; 69 | } 70 | 71 | if (T->end) { 72 | return TRUE; 73 | } else { 74 | return FALSE; 75 | } 76 | } 77 | 78 | 79 | int main(int argc, char const *argv[]) 80 | { 81 | TriePtr T; 82 | Init(&T); 83 | char *str = "hello"; 84 | char *str2 = "hi"; 85 | 86 | Insert(T, str); 87 | 88 | printf("str is search %d\n", Search(T, str)); 89 | printf("str2 is search %d\n", Search(T, str2)); 90 | return 0; 91 | } -------------------------------------------------------------------------------- /c-cpp/28_heap/heap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* Implement heap */ 8 | 9 | #define MAX_HEAP_SIZE (1 << 8) 10 | 11 | struct element { 12 | int data; 13 | }; 14 | 15 | struct heap { 16 | union { 17 | unsigned long elements; 18 | struct element *elem[MAX_HEAP_SIZE]; 19 | }; 20 | }; 21 | 22 | void init_heap(struct heap *heap) 23 | { 24 | int i; 25 | 26 | for(i = 0; i < MAX_HEAP_SIZE; i++) { 27 | heap->elem[i] = NULL; 28 | } 29 | } 30 | 31 | void dump_heap(struct heap *heap, int index) 32 | { 33 | struct element *elem; 34 | int level; 35 | 36 | if (index > heap->elements) 37 | return; 38 | 39 | elem = heap->elem[index]; 40 | level = fls(index); 41 | 42 | dump_heap(heap, index * 2 + 1); 43 | 44 | if (!(index % 2) && index != 1) 45 | printf("%*s\n", level*3, "|"); 46 | 47 | printf("%*s - %05d\n", level*3, " ", elem->data); 48 | 49 | if (index % 2 && index != 1) 50 | printf("%*s\n", level*3, "|"); 51 | 52 | dump_heap(heap, index * 2); 53 | } 54 | 55 | void dump(struct heap *heap, int elements) 56 | { 57 | int i; 58 | 59 | for (i = 1; i <= elements; i++) 60 | printf("[%02d]: %4d\n", i, heap->elem[i]->data); 61 | 62 | } 63 | 64 | struct element* create_element(int data) 65 | { 66 | struct element *elem; 67 | 68 | elem = malloc(sizeof(struct element)); 69 | 70 | if (elem) 71 | elem->data = data; 72 | 73 | return elem; 74 | } 75 | 76 | void fake_a_heap(struct heap *heap) 77 | { 78 | /* data is in ordered */ 79 | int i, data[10] = {7, 4, 9, 2, 6, 8, 10, 1, 3, 5}; 80 | 81 | init_heap(heap); 82 | 83 | /* root start at 1 */ 84 | for (i = 0; i < 10; i++) 85 | heap->elem[i+1] = create_element(data[i]); 86 | 87 | heap->elements = 10; 88 | } 89 | 90 | void swap(struct heap *heap, int i, int j) 91 | { 92 | struct element *tmp; 93 | 94 | tmp = heap->elem[j]; 95 | heap->elem[j] = heap->elem[i]; 96 | heap->elem[i] = tmp; 97 | } 98 | 99 | void heapify(struct heap *heap, int parent) 100 | { 101 | struct element **elem = heap->elem; 102 | int elements = heap->elements; 103 | int left, right, max; 104 | 105 | while (true) { 106 | left = parent * 2; 107 | right = left + 1; 108 | 109 | max = parent; 110 | if (left <= elements && elem[max]->data < elem[left]->data) 111 | max = left; 112 | if (right <= elements && elem[max]->data < elem[right]->data) 113 | max = right; 114 | 115 | if (max == parent) 116 | break; 117 | 118 | swap(heap, max, parent); 119 | parent = max; 120 | } 121 | } 122 | 123 | void build_heap(struct heap *heap) 124 | { 125 | int i; 126 | 127 | for (i = heap->elements / 2; i >= 1; i--) 128 | heapify(heap, i); 129 | } 130 | 131 | int heap_sort(struct heap *heap) 132 | { 133 | int elements = heap->elements; 134 | 135 | while (heap->elements) { 136 | swap(heap, 1, heap->elements); 137 | heap->elements--; 138 | heapify(heap, 1); 139 | } 140 | 141 | return elements; 142 | } 143 | 144 | int main() 145 | { 146 | struct heap heap; 147 | int elements; 148 | 149 | fake_a_heap(&heap); 150 | dump_heap(&heap, 1); 151 | 152 | printf("After Heapify:\n"); 153 | build_heap(&heap); 154 | dump_heap(&heap, 1); 155 | 156 | printf("After Heap sort:\n"); 157 | elements = heap_sort(&heap); 158 | dump(&heap, elements); 159 | return 0; 160 | } 161 | -------------------------------------------------------------------------------- /c-cpp/30_Graph/graph.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | struct vertex; 8 | struct vertex_adjs { 9 | struct vertex *v; 10 | struct vertex_adjs *next; 11 | }; 12 | 13 | struct vertex { 14 | int data; 15 | struct vertex_adjs *adj; 16 | }; 17 | 18 | #define MAX_GRAPH_VERTEX (1 << 8) 19 | struct graph { 20 | struct vertex *vxs[MAX_GRAPH_VERTEX]; 21 | }; 22 | 23 | void init_graph(struct graph *graph) 24 | { 25 | int i; 26 | 27 | for (i = 0; i < MAX_GRAPH_VERTEX; i++) 28 | graph->vxs[i] = NULL; 29 | } 30 | 31 | struct vertex *create_vertex(int data) 32 | { 33 | struct vertex *v; 34 | 35 | v = malloc(sizeof(struct vertex)); 36 | 37 | if (v) { 38 | v->data = data; 39 | v->adj = NULL; 40 | } 41 | 42 | return v; 43 | } 44 | 45 | struct vertex_adjs *create_vertex_adj(struct vertex *v) 46 | { 47 | struct vertex_adjs *v_adj; 48 | 49 | v_adj = malloc(sizeof(struct vertex_adjs)); 50 | 51 | if (!v_adj) 52 | return NULL; 53 | 54 | v_adj->v = v; 55 | v_adj->next = NULL; 56 | return v_adj; 57 | } 58 | 59 | void insert_adj(struct vertex *v, struct vertex *adj) 60 | { 61 | struct vertex_adjs **v_adj; 62 | 63 | v_adj = &v->adj; 64 | 65 | while (*v_adj) 66 | v_adj = &(*v_adj)->next; 67 | 68 | *v_adj = create_vertex_adj(adj); 69 | } 70 | 71 | void dump_raw(struct graph *graph) 72 | { 73 | int i; 74 | 75 | for (i = 0; i < MAX_GRAPH_VERTEX; i++) { 76 | struct vertex *v = graph->vxs[i]; 77 | struct vertex_adjs *adj; 78 | if (v == NULL) 79 | continue; 80 | 81 | printf("Vertex[%02d]: %8d ->", i, v->data); 82 | 83 | adj = v->adj; 84 | while (adj) { 85 | printf(" %8d,", adj->v->data); 86 | adj = adj->next; 87 | } 88 | printf("\n"); 89 | } 90 | } 91 | 92 | /* 93 | 1 ----- 2 ----- 3 94 | | / | / 95 | | / | / 96 | | / | / 97 | | / | / 98 | | / | / 99 | 4 ----- 5 100 | */ 101 | void fake_a_graph(struct graph *graph) 102 | { 103 | int i; 104 | 105 | init_graph(graph); 106 | 107 | for (i = 0; i < 5; i++) 108 | graph->vxs[i] = create_vertex(i+1); 109 | 110 | /* connect 1 -> 2, 1 -> 4 */ 111 | insert_adj(graph->vxs[0], graph->vxs[1]); 112 | insert_adj(graph->vxs[0], graph->vxs[3]); 113 | /* connect 2 -> 1, 2 -> 3, 2 -> 5, 2 -> 4 */ 114 | insert_adj(graph->vxs[1], graph->vxs[0]); 115 | insert_adj(graph->vxs[1], graph->vxs[2]); 116 | insert_adj(graph->vxs[1], graph->vxs[4]); 117 | insert_adj(graph->vxs[1], graph->vxs[3]); 118 | /* connect 3 -> 2, 3 -> 5 */ 119 | insert_adj(graph->vxs[2], graph->vxs[1]); 120 | insert_adj(graph->vxs[2], graph->vxs[4]); 121 | /* connect 4 -> 1, 4 -> 2, 4 -> 5 */ 122 | insert_adj(graph->vxs[3], graph->vxs[0]); 123 | insert_adj(graph->vxs[3], graph->vxs[1]); 124 | insert_adj(graph->vxs[3], graph->vxs[4]); 125 | /* connect 5 -> 4, 5 -> 2, 5 -> 3 */ 126 | insert_adj(graph->vxs[4], graph->vxs[3]); 127 | insert_adj(graph->vxs[4], graph->vxs[1]); 128 | insert_adj(graph->vxs[4], graph->vxs[3]); 129 | } 130 | 131 | int main() 132 | { 133 | struct graph g; 134 | 135 | fake_a_graph(&g); 136 | dump_raw(&g); 137 | return 0; 138 | } 139 | -------------------------------------------------------------------------------- /c-cpp/bst.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | enum child_dir { 8 | left_child, 9 | right_child, 10 | root, 11 | }; 12 | 13 | struct node { 14 | unsigned long data; 15 | struct node *left; 16 | struct node *right; 17 | }; 18 | 19 | struct root { 20 | struct node *r; 21 | }; 22 | 23 | void dump(struct node *node, int level, enum child_dir dir) 24 | { 25 | if (!node) 26 | return; 27 | 28 | dump(node->right, level + 1, right_child); 29 | 30 | if (dir == left_child) 31 | printf("%*s\n", level*3, "|"); 32 | 33 | printf("%*s - %05lu\n", level*3, " ", node->data); 34 | 35 | if (dir == right_child) 36 | printf("%*s\n", level*3, "|"); 37 | 38 | dump(node->left, level + 1, left_child); 39 | } 40 | 41 | struct node* find(struct root *root, unsigned long data) 42 | { 43 | struct node* n = root->r; 44 | 45 | while (n) { 46 | if (n->data == data) 47 | return n; 48 | if (data < n->data) 49 | n = n->left; 50 | else 51 | n = n->right; 52 | } 53 | 54 | return NULL; 55 | } 56 | 57 | struct node* new_node(unsigned long data) 58 | { 59 | struct node *n; 60 | 61 | n = malloc(sizeof(struct node)); 62 | 63 | n->data = data; 64 | n->left = n->right = NULL; 65 | return n; 66 | } 67 | 68 | void insert(struct root *root, struct node *new) 69 | { 70 | struct node *parent; 71 | 72 | if (!root->r) { 73 | root->r = new; 74 | return; 75 | } 76 | 77 | parent = root->r; 78 | 79 | while (true) { 80 | /* Don't support duplicate data */ 81 | if (new->data == parent->data) 82 | break; 83 | 84 | if (new->data < parent->data) { 85 | if (!parent->left) { 86 | parent->left = new; 87 | break; 88 | } 89 | parent = parent->left; 90 | } else { 91 | if (!parent->right) { 92 | parent->right = new; 93 | break; 94 | } 95 | parent = parent->right; 96 | } 97 | } 98 | } 99 | 100 | struct node* delete(struct root *root, unsigned long data) 101 | { 102 | struct node *n = root->r, **p = &root->r; 103 | struct node *child; 104 | 105 | while (n && n->data != data) { 106 | if (data < n->data) { 107 | p = &n->left; 108 | n = n->left; 109 | } else { 110 | p = &n->right; 111 | n = n->right; 112 | } 113 | } 114 | 115 | if (!n) 116 | return NULL; 117 | 118 | if (n->left && n->right) { 119 | struct node *rn = n->right, **rp = &n->right; 120 | 121 | while (rn->left) { 122 | rp = &rn->left; 123 | rn = rn->left; 124 | } 125 | 126 | n->data = rn->data; 127 | n = rn; 128 | p = rp; 129 | } 130 | 131 | child = n->left ? n->left : n->right; 132 | *p = child; 133 | 134 | return NULL; 135 | } 136 | 137 | void insert_test() 138 | { 139 | struct root tree; 140 | struct node* n; 141 | 142 | tree.r = NULL; 143 | 144 | insert(&tree, new_node(9)); 145 | 146 | insert(&tree, new_node(5)); 147 | insert(&tree, new_node(2)); 148 | insert(&tree, new_node(8)); 149 | 150 | insert(&tree, new_node(18)); 151 | insert(&tree, new_node(13)); 152 | insert(&tree, new_node(21)); 153 | insert(&tree, new_node(20)); 154 | 155 | dump(tree.r, 0, root); 156 | 157 | n = find(&tree, 18); 158 | if (n && n->data == 18) 159 | printf("Get 18\n"); 160 | 161 | } 162 | 163 | void delete_test() 164 | { 165 | struct root tree; 166 | struct node* n; 167 | 168 | tree.r = NULL; 169 | 170 | insert(&tree, new_node(9)); 171 | 172 | insert(&tree, new_node(5)); 173 | insert(&tree, new_node(2)); 174 | insert(&tree, new_node(8)); 175 | 176 | insert(&tree, new_node(18)); 177 | insert(&tree, new_node(13)); 178 | insert(&tree, new_node(21)); 179 | insert(&tree, new_node(20)); 180 | 181 | dump(tree.r, 0, root); 182 | 183 | delete(&tree, 20); 184 | printf("Delete 20\n"); 185 | dump(tree.r, 0, root); 186 | 187 | delete(&tree, 9); 188 | printf("Delete 9\n"); 189 | dump(tree.r, 0, root); 190 | } 191 | 192 | int main() 193 | { 194 | //insert_test(); 195 | delete_test(); 196 | return 0; 197 | } 198 | -------------------------------------------------------------------------------- /object-c/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/object-c/.DS_Store -------------------------------------------------------------------------------- /object-c/Array/MyArray.h: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.h 3 | // demodemo 4 | // 5 | // Created by 李贺 on 2020/4/28. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MyArray : NSObject 14 | 15 | - (instancetype)initWithCapacity:(NSUInteger)capacity; 16 | - (id)objectAtIndexedSubscript:(NSUInteger)index; 17 | - (void)removeObjectAtIndex:(NSUInteger)index; 18 | - (void)insertObject:(id)anObject atIndex:(NSUInteger)index; 19 | - (void)addObject:(id)anObject; 20 | - (void)printAll; 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /object-c/Array/MyArray.m: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.m 3 | // demodemo 4 | // 5 | // Created by 李贺 on 2020/4/28. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | 9 | #import "MyArray.h" 10 | 11 | @implementation MyArray 12 | { 13 | @private 14 | NSMutableArray *_data; 15 | NSUInteger _capacity; 16 | NSUInteger _count; 17 | } 18 | 19 | - (instancetype)initWithCapacity:(NSUInteger)capacity { 20 | self = [super init]; 21 | if (self) { 22 | _data = [NSMutableArray arrayWithCapacity:capacity]; 23 | _capacity = capacity; 24 | _count = 0; 25 | } 26 | return self; 27 | } 28 | 29 | - (id)objectAtIndexedSubscript:(NSUInteger)index { 30 | if (index >= _count) return nil; 31 | return _data[index]; 32 | } 33 | 34 | - (void)removeObjectAtIndex:(NSUInteger)index { 35 | if (index >= _count) { 36 | [NSException raise:NSRangeException format:@"Index out of range."]; 37 | } 38 | for (NSUInteger i = index + 1; i < _data.count; i++) { 39 | _data[i-1] = _data[i]; 40 | } 41 | _count--; 42 | } 43 | 44 | - (void)insertObject:(nonnull id)anObject atIndex:(NSUInteger)index { 45 | if (index >= _count || _count == _capacity) { 46 | [NSException raise:NSRangeException format:@"Index out of range."]; 47 | } 48 | for (NSUInteger i = _count - 1; i >= index; i--) { 49 | _data[i+1] = _data[i]; 50 | } 51 | _data[index] = anObject; 52 | _count++; 53 | } 54 | 55 | // insertToTail 56 | - (void)addObject:(nonnull id)anObject { 57 | if (_count == _capacity) { 58 | [NSException raise:NSRangeException format:@"Array is full."]; 59 | } 60 | [_data addObject:anObject]; 61 | _count++; 62 | } 63 | 64 | - (void)printAll { 65 | for (id obj in _data) { 66 | NSLog(@"%@", obj); 67 | } 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /object-c/Linklist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/object-c/Linklist/.gitkeep -------------------------------------------------------------------------------- /object-c/Linklist/ListNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.h 3 | // demodemo 4 | // 5 | // Created by 李贺 on 2020/4/28. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ListNode : NSObject 12 | 13 | @property int value; 14 | @property ListNode *next; 15 | 16 | - (instancetype)initWithValue:(int)value; 17 | + (instancetype)nodeWithValue:(int)value; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /object-c/Linklist/ListNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.h 3 | // demodemo 4 | // 5 | // Created by 李贺 on 2020/4/28. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | 9 | #import "ListNode.h" 10 | 11 | @implementation ListNode 12 | 13 | - (instancetype)initWithValue:(int)value { 14 | if (self = [super init]) { 15 | _value = value; 16 | } 17 | return self; 18 | } 19 | 20 | + (instancetype)nodeWithValue:(int)value { 21 | return [[self alloc] initWithValue:value]; 22 | } 23 | 24 | - (NSString*)debugDescription { 25 | return [NSString stringWithFormat:@"%d", _value]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /object-c/Linklist/SinglyLinkedList.h: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.h 3 | // demodemo 4 | // 5 | // Created by 李贺 on 2020/4/28. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ListNode.h" 11 | 12 | @interface SinglyLinkedList : NSObject 13 | 14 | @property ListNode* head; 15 | 16 | - (ListNode*)nodeWithValue:(int)value; 17 | - (ListNode*)nodeAtIndex:(NSUInteger)index; 18 | 19 | - (void)insertNodeWithValue:(int)value; 20 | - (void)insertNode:(nonnull ListNode*)node; 21 | + (void)insertNodeWithValue:(int)value afterNode:(nonnull ListNode*)node; 22 | + (void)insertNode:(nonnull ListNode*)aNode afterNode:(nonnull ListNode*)node; 23 | - (void)insertNodeWithValue:(int)value beforeNode:(nonnull ListNode*)node; 24 | - (void)insertNode:(nonnull ListNode*)aNode beforeNode:(nonnull ListNode*)node; 25 | 26 | - (void)deleteNode:(nonnull ListNode*)node; 27 | - (void)deleteNodesWithValue:(int)value; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /object-c/Linklist/SinglyLinkedList.m: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.h 3 | // demodemo 4 | // 5 | // Created by 李贺 on 2020/4/28. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | 9 | #import "SinglyLinkedList.h" 10 | 11 | @implementation SinglyLinkedList 12 | 13 | - (ListNode*)nodeWithValue:(int)value { 14 | ListNode* current = _head; 15 | while (current && current.value != value) { 16 | current = current.next; 17 | } 18 | return current; 19 | } 20 | 21 | - (ListNode*)nodeAtIndex:(NSUInteger)index { 22 | ListNode* current = _head; 23 | NSUInteger position = 0; 24 | while (current && position != index) { 25 | current = current.next; 26 | position++; 27 | } 28 | return current; 29 | } 30 | 31 | - (void)insertNodeWithValue:(int)value { 32 | ListNode* aNode = [ListNode nodeWithValue:value]; 33 | [self insertNode:aNode]; 34 | } 35 | 36 | - (void)insertNode:(nonnull ListNode *)node { 37 | node.next = _head; 38 | _head = node; 39 | } 40 | 41 | + (void)insertNodeWithValue:(int)value afterNode:(nonnull ListNode *)node { 42 | ListNode* aNode = [ListNode nodeWithValue:value]; 43 | [SinglyLinkedList insertNode:aNode afterNode:node]; 44 | } 45 | 46 | + (void)insertNode:(nonnull ListNode *)aNode afterNode:(nonnull ListNode *)node { 47 | aNode.next = node.next; 48 | node.next = aNode; 49 | } 50 | 51 | - (void)insertNodeWithValue:(int)value beforeNode:(nonnull ListNode *)node { 52 | ListNode* aNode = [ListNode nodeWithValue:value]; 53 | [self insertNode:aNode beforeNode:node]; 54 | } 55 | 56 | - (void)insertNode:(nonnull ListNode *)aNode beforeNode:(nonnull ListNode *)node { 57 | ListNode* fakeHead = [ListNode nodeWithValue:0]; 58 | fakeHead.next = _head; 59 | ListNode* current = fakeHead; 60 | while (current.next && current.next != node) { 61 | current = current.next; 62 | } 63 | if (current.next == nil) { 64 | return; 65 | } 66 | aNode.next = node; 67 | current.next = aNode; 68 | } 69 | 70 | - (void)deleteNode:(nonnull ListNode *)node { 71 | if (node.next) { 72 | node.value = node.next.value; 73 | node.next = node.next.next; 74 | return; 75 | } 76 | if (_head == nil) return; 77 | ListNode* current = _head; 78 | while (current.next && current.next != node) { 79 | current = current.next; 80 | } 81 | current.next = nil; 82 | } 83 | 84 | - (void)deleteNodesWithValue:(int)value { 85 | ListNode* fakeHead = [ListNode nodeWithValue:value+1]; 86 | fakeHead.next = _head; 87 | ListNode* prev = fakeHead; 88 | ListNode* current = _head; 89 | while (current) { 90 | if (current.value != value) { 91 | prev.next = current; 92 | prev = prev.next; 93 | } 94 | current = current.next; 95 | } 96 | if (prev.next) { 97 | prev.next = nil; 98 | } 99 | _head = fakeHead.next; 100 | } 101 | 102 | - (NSString*)debugDescription { 103 | NSMutableString* info = [[NSMutableString alloc] init]; 104 | ListNode* current = _head; 105 | if (current) { 106 | [info appendString:current.debugDescription]; 107 | } 108 | current = current.next; 109 | while (current) { 110 | [info appendString:@"->"]; 111 | [info appendString:current.debugDescription]; 112 | current = current.next; 113 | } 114 | return [NSString stringWithString:info]; 115 | } 116 | 117 | @end 118 | -------------------------------------------------------------------------------- /object-c/Sorts/Sort.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sort.h 3 | // 数据结构与算法 4 | // 5 | // Created by 李贺 on 2020/4/20. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface Sort : NSObject 14 | 15 | /// 冒泡排序 16 | + (NSArray *)bubbleSortWithArray:(NSArray *)array ; 17 | 18 | /// 插入排序 19 | + (NSArray *)insertionSortWithArray:(NSArray *)array ; 20 | 21 | /// 选择排序 22 | + (NSArray *)selectionSortWithArray:(NSArray *)array ; 23 | 24 | /// 桶排序 25 | /// @param array 排序数组 26 | /// @param size 单个桶内元素数量 27 | + (NSArray *)bucketSortWithArray:(NSArray *)array bucketsSize:(NSInteger)size ; 28 | 29 | /// 归并排序, 打印结果 30 | - (void)mergeSortWithArray:(NSArray *)array ; 31 | 32 | /// 快速排序 33 | + (NSArray *)quickSortWithArray:(NSArray *)array ; 34 | 35 | /// 计数排序, 假设数组中储存的都是非负整数 36 | + (NSArray *)countingSortWithArray:(NSArray *)array ; 37 | 38 | @end 39 | 40 | NS_ASSUME_NONNULL_END 41 | -------------------------------------------------------------------------------- /object-c/Stack/LinkedStack.h: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.h 3 | // demodemo 4 | // 5 | // Created by 李贺 on 2020/4/28. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | // 基于链表实现的栈 9 | 10 | #import 11 | 12 | @interface LinkedStack : NSObject 13 | 14 | - (BOOL)isEmpty; 15 | - (void)push:(int)value; 16 | - (int)pop; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /object-c/Stack/LinkedStack.m: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.h 3 | // demodemo 4 | // 5 | // Created by 李贺 on 2020/4/28. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | 9 | #import "LinkedStack.h" 10 | #import "ListNode.h" 11 | 12 | @implementation LinkedStack 13 | { 14 | @private 15 | ListNode* _top; 16 | } 17 | 18 | - (BOOL)isEmpty { 19 | return _top == nil; 20 | } 21 | 22 | - (void)push:(int)value { 23 | ListNode *newTop = [ListNode nodeWithValue:value]; 24 | newTop.next = _top; 25 | _top = newTop; 26 | } 27 | 28 | - (int)pop { 29 | if ([self isEmpty]) { 30 | [NSException raise:NSRangeException format:@"The stack is empty."]; 31 | } 32 | int value = _top.value; 33 | _top = _top.next; 34 | return value; 35 | } 36 | 37 | - (NSString *)debugDescription { 38 | NSMutableString *info = [[NSMutableString alloc] init]; 39 | ListNode *current = _top; 40 | while (current) { 41 | [info appendString:[NSString stringWithFormat:@"%d]", current.value]]; 42 | current = current.next; 43 | } 44 | return [NSString stringWithString:info]; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /object-c/Stack/LinkedStackTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.h 3 | // demodemo 4 | // 5 | // Created by 李贺 on 2020/4/28. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LinkedStack.h" 11 | 12 | @interface LinkedStackTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation LinkedStackTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testPush { 29 | LinkedStack *stack = [[LinkedStack alloc] init]; 30 | for (int i = 0; i < 10; i++) { 31 | [stack push:i]; 32 | } 33 | XCTAssertEqualObjects([stack debugDescription], @"9]8]7]6]5]4]3]2]1]0]"); 34 | } 35 | 36 | - (void)testPop { 37 | LinkedStack *stack = [[LinkedStack alloc] init]; 38 | for (int i = 0; i < 10; i++) { 39 | [stack push:i]; 40 | } 41 | [stack pop]; 42 | XCTAssertEqualObjects([stack debugDescription], @"8]7]6]5]4]3]2]1]0]"); 43 | for (int i = 0; i < 9; i++) { 44 | [stack pop]; 45 | } 46 | XCTAssertThrowsSpecificNamed([stack pop], NSException, NSRangeException, @"The stack is empty."); 47 | } 48 | 49 | //- (void)testPerformanceExample { 50 | // // This is an example of a performance test case. 51 | // [self measureBlock:^{ 52 | // // Put the code you want to measure the time of here. 53 | // }]; 54 | //} 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /object-c/Stack/ListNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.h 3 | // demodemo 4 | // 5 | // Created by 李贺 on 2020/4/28. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ListNode : NSObject 12 | 13 | @property int value; 14 | @property ListNode *next; 15 | 16 | - (instancetype)initWithValue:(int)value; 17 | + (instancetype)nodeWithValue:(int)value; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /object-c/Stack/ListNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.h 3 | // demodemo 4 | // 5 | // Created by 李贺 on 2020/4/28. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | #import "ListNode.h" 9 | 10 | @implementation ListNode 11 | 12 | - (instancetype)initWithValue:(int)value { 13 | if (self = [super init]) { 14 | _value = value; 15 | } 16 | return self; 17 | } 18 | 19 | + (instancetype)nodeWithValue:(int)value { 20 | return [[self alloc] initWithValue:value]; 21 | } 22 | 23 | - (NSString*)debugDescription { 24 | return [NSString stringWithFormat:@"%d", _value]; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /object-c/Stack/stack_practice/ArrayStack.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | 栈实现 4 | 5 | Author: Smallfly 6 | */ 7 | 8 | #import 9 | 10 | @interface Stack : NSObject 11 | 12 | - (id)initWithCapacity:(NSUInteger)count; 13 | 14 | - (BOOL)isEmpty; 15 | - (id)top; 16 | - (NSUInteger)size; 17 | 18 | - (BOOL)push:(id)obj; 19 | - (id)pop; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /object-c/Stack/stack_practice/ArrayStack.m: -------------------------------------------------------------------------------- 1 | #import "ArrayStack.h" 2 | 3 | @implementation Stack { 4 | NSMutableArray *_arr; 5 | NSUInteger _capacity; 6 | NSUInteger _count; 7 | } 8 | 9 | - (id)initWithCapacity:(NSUInteger)capacity { 10 | self = [super init]; 11 | _capacity = capacity; 12 | _arr = [[NSMutableArray alloc] initWithCapacity:capacity]; 13 | return self; 14 | } 15 | 16 | - (BOOL)isEmpty { 17 | return _arr.count == 0; 18 | } 19 | 20 | - (BOOL)isFull { 21 | return _arr.count == _capacity; 22 | } 23 | 24 | - (id)top { 25 | if ([self isEmpty]) return nil; 26 | NSUInteger index = _arr.count - 1; 27 | return _arr[index]; 28 | } 29 | 30 | - (NSUInteger)size { 31 | return _arr.count; 32 | } 33 | 34 | - (BOOL)push:(id)obj { 35 | if (!obj) return NO; 36 | if (_arr.count == _capacity) return NO; 37 | [_arr addObject:obj]; 38 | return YES; 39 | } 40 | 41 | - (id)pop { 42 | if ([self isEmpty]) return nil; 43 | NSUInteger index = _arr.count - 1; 44 | id obj = _arr[index]; 45 | [_arr removeLastObject]; 46 | return obj; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /object-c/Stack/stack_practice/BalancedParentheses.h: -------------------------------------------------------------------------------- 1 | /** 2 | 判断括号是否匹配 {} [] () 3 | 4 | Author: Smallfly 5 | */ 6 | #import 7 | 8 | @interface BalancedParentheses : NSObject 9 | 10 | - (BOOL)checkForParenthessBlanced:(NSString *)express; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /object-c/Stack/stack_practice/BalancedParentheses.m: -------------------------------------------------------------------------------- 1 | 2 | #import "BalancedParentheses.h" 3 | #import "ArrayStack.h" 4 | 5 | const NSDictionary *parenthesesDict() { 6 | return @{@"(": @")", @"{": @"}", @"[": @"]"}; 7 | } 8 | 9 | @implementation BalancedParentheses { 10 | Stack *_stack; 11 | } 12 | 13 | - (instancetype)init { 14 | self = [super init]; 15 | _stack = [[Stack alloc] initWithCapacity:100]; 16 | return self; 17 | } 18 | 19 | - (BOOL)checkForParenthessBlanced:(NSString *)express { 20 | NSInteger midIndex = express.length / 2; 21 | for (int i = 0; i < express.length; ++i) { 22 | NSString *ele = [express substringWithRange:NSMakeRange(i, 1)]; 23 | if (i < midIndex) { 24 | // 前半部分把与 ele 匹配的括号加入栈 25 | [_stack push:parenthesesDict()[ele]]; 26 | } else { 27 | // 后半部分检查栈顶的元素与当前元素是否相同 28 | NSString *topEle = [_stack pop]; 29 | if (![topEle isEqualToString:ele]) { 30 | return NO; 31 | } 32 | } 33 | } 34 | return YES; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /object-c/Stack/stack_practice/FourOperation.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | 整型四则运算 4 | 5 | Author: Smallfly 6 | */ 7 | 8 | #import 9 | 10 | @interface FourOperation : NSObject 11 | 12 | + (FourOperation *)shared; 13 | 14 | /** 15 | 整型四则运算 16 | 17 | @param expression 运算表达式,注意操作数和运算符之间要有空格 18 | @return 计算结果 19 | */ 20 | - (NSNumber *)caculateExpression:(NSString *)expression; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /object-c/Stack/stack_practice/FourOperation.m: -------------------------------------------------------------------------------- 1 | #import "FourOperation.h" 2 | #import "ArrayStack.h" 3 | 4 | const NSDictionary *operationPriorityDict() { 5 | return @{@"*": @1, @"/": @1, @"+": @0, @"-": @0}; 6 | } 7 | 8 | @implementation FourOperation { 9 | @private 10 | Stack *_optStack; 11 | Stack *_numStack; 12 | NSNumberFormatter *_numFormatter; 13 | } 14 | 15 | + (FourOperation *)shared { 16 | static FourOperation* single = nil; 17 | static dispatch_once_t onceToken; 18 | dispatch_once(&onceToken, ^{ 19 | single = [FourOperation new]; 20 | }); 21 | return single; 22 | } 23 | 24 | - (instancetype)init { 25 | self = [super init]; 26 | _optStack = [[Stack alloc] initWithCapacity:100]; 27 | _numStack = [[Stack alloc] initWithCapacity:100]; 28 | _numFormatter = [NSNumberFormatter new]; 29 | return self; 30 | } 31 | 32 | - (id)caculateExpression:(NSString *)expression { 33 | NSArray *elements = [expression componentsSeparatedByString:@" "]; 34 | 35 | for (NSString *obj in elements) { 36 | NSNumber *numb = [_numFormatter numberFromString:obj]; 37 | if (numb) { // 运算数 38 | [_numStack push:numb]; 39 | } else { // 操作符 40 | 41 | // 如果栈顶操作符优先级大于等于当前操作符 42 | while ([self _topOperationPriorityIsHigherOrEqualToOperation:obj]) { 43 | 44 | // 取出栈顶的操作符和两个操作数做一次运算 45 | NSNumber *res = [self _excuteOnceCaculate]; 46 | 47 | // 计算结果存入栈 48 | [_numStack push:res]; 49 | } 50 | 51 | [_optStack push:obj]; 52 | } 53 | } 54 | 55 | // 如果操作符存在栈中,依次取出做运算 56 | NSNumber *res = nil; 57 | while ([_optStack top]) { 58 | res = [self _excuteOnceCaculate]; 59 | [_numStack push:res]; 60 | } 61 | return res; 62 | } 63 | 64 | - (NSInteger)_getPriority:(NSString *)opt { 65 | return [[operationPriorityDict() objectForKey:opt] integerValue]; 66 | } 67 | 68 | - (BOOL)_topOperationPriorityIsHigherOrEqualToOperation:(NSString *)opt { 69 | NSString *topOpt = [_optStack top]; 70 | if (!topOpt) return NO; 71 | NSInteger curPriority = [self _getPriority:opt]; 72 | NSInteger topPriority = [self _getPriority:topOpt]; 73 | return curPriority <= topPriority; 74 | } 75 | 76 | - (NSNumber *)_excuteOnceCaculate { 77 | NSNumber *numRight = [_numStack pop]; 78 | NSNumber *numLeft = [_numStack pop]; 79 | NSString *topOpt = [_optStack pop]; 80 | NSInteger result = [self _caculeteWithNumberLeft:numLeft numberRight:numRight operation:topOpt]; 81 | NSNumber *res = [NSNumber numberWithInteger:result]; 82 | return res; 83 | } 84 | 85 | - (NSInteger)_caculeteWithNumberLeft:(NSNumber *)numLeft numberRight:(NSNumber *)numRight operation:(NSString *)opt { 86 | if (!numLeft || !numRight || !opt) return 0; 87 | NSInteger left = [numLeft integerValue]; 88 | NSInteger right = [numRight integerValue]; 89 | if ([opt isEqualToString:@"+"]) { 90 | return left + right; 91 | } else if ([opt isEqualToString:@"-"]) { 92 | return left - right; 93 | } else if ([opt isEqualToString:@"*"]) { 94 | return left * right; 95 | } else if ([opt isEqualToString:@"/"]) { 96 | return left / right; 97 | } else { 98 | return 0; 99 | } 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /object-c/Stack/stack_practice/main.m: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | #import "FourOperation.h" 4 | #import "BalancedParentheses.h" 5 | 6 | int main(int argc, const char * argv[]) { 7 | @autoreleasepool { 8 | // 测试四则运算 9 | NSNumber *a = [[FourOperation shared] caculateExpression:@"10 - 4 / 2 * 3 + 3 - 6 / 2"]; 10 | NSNumber *b = [[FourOperation shared] caculateExpression:@"10 - 3"]; 11 | NSNumber *c = [[FourOperation shared] caculateExpression:@"2 * 3"]; 12 | NSLog(@"FourOperation: %ld\t%ld\t%ld\t", a.integerValue, b.integerValue, c.integerValue); 13 | 14 | // 测试括号匹配 15 | BalancedParentheses *balancedCheck = [BalancedParentheses new]; 16 | BOOL result = [balancedCheck checkForParenthessBlanced:@"([{{{}}}])"]; 17 | NSLog(@"BalancedParentheses: %d", result); 18 | } 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /object-c/bm_match/BM.h: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.h 3 | // demodemo 4 | // 5 | // Created by 李贺 on 2020/4/28. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BM : NSObject 14 | - (instancetype)initWithA:(NSString *)a andB:(NSString *)b; 15 | - (NSInteger)startMatch; 16 | - (void)startMatchCompeletion:(void (^)(NSInteger))completion; 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /object-c/bm_match/BM.m: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.h 3 | // demodemo 4 | // 5 | // Created by 李贺 on 2020/4/28. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | 9 | #import "BM.h" 10 | 11 | #define SIZE 256 12 | 13 | @interface BM() 14 | @property (nonatomic, strong) NSString *a; // 主串 15 | @property (nonatomic, strong) NSString *b; // 匹配串 16 | 17 | @property (nonatomic, strong) NSMutableArray *bc; // 匹配串,哈希表,存储字符在匹配串中的下标 18 | 19 | @property (nonatomic, strong) NSMutableArray *suffix; 20 | @property (nonatomic, strong) NSMutableArray *prifix; 21 | 22 | @end 23 | 24 | @implementation BM 25 | 26 | - (instancetype)initWithA:(NSString *)a andB:(NSString *)b { 27 | self = [super init]; 28 | if (!self) return nil; 29 | _a = a; 30 | _b = b; 31 | _bc = [NSMutableArray new]; 32 | _suffix = [NSMutableArray new]; 33 | _prifix = [NSMutableArray new]; 34 | [self generateBC]; 35 | [self generateGS]; 36 | return self; 37 | } 38 | 39 | // 构建坏字符哈希表,记录每个字符在匹配串中最后出现的位置 40 | - (void)generateBC { 41 | for (int i = 0; i < SIZE; ++i) { 42 | [_bc addObject:@-1]; 43 | } 44 | for (int i = 0; i < _b.length; ++i) { 45 | int ascii = (int)[_b characterAtIndex:i]; // char to ASCII 46 | _bc[ascii] = [NSNumber numberWithInteger:i]; // save b's char index 47 | } 48 | } 49 | 50 | - (NSInteger)bm { 51 | NSInteger i = 0; // 主串和匹配串对齐的第一个字符 52 | NSUInteger n = _a.length; 53 | NSUInteger m = _b.length; 54 | while (i <= n - m) { 55 | NSInteger j; 56 | // 从后往前匹配 57 | for (j = m - 1; j >= 0; --j) { 58 | int aValue = (int)[_a characterAtIndex:(i + j)]; 59 | int bValue = (int)[_b characterAtIndex:j]; 60 | if (aValue != bValue) break; // 找到坏字符下标 j 停止 61 | } 62 | if (j < 0) { 63 | return i; // 匹配成功,返回所在的位置 64 | } 65 | 66 | // 坏字符在匹配串中最后出现的位置 67 | id numberInHashTableBC = _bc[(int)[_a characterAtIndex:(i + j)]]; 68 | NSInteger x = j - [numberInHashTableBC integerValue]; 69 | NSInteger y = 0; 70 | if (j < m - 1) { 71 | y = [self moveByGSBy:j]; 72 | } 73 | i = i + MAX(x, y); 74 | 75 | // 这一步比较难理解,不直接滑到过 j,是因为在 j 之前可能存在于坏字符相同的字符 76 | // 这个于坏字符相同的字符,在匹配串中的最大下标是 numberInHashTableBC 77 | // i = i + (j - [numberInHashTableBC integerValue]); 78 | } 79 | 80 | return -1; 81 | } 82 | 83 | // 好后缀匹配移动 84 | - (NSInteger)moveByGSBy:(NSInteger)j { 85 | NSUInteger m = _b.length; 86 | NSInteger k = m - 1 - j; // 好后缀的长度 87 | NSInteger t = [_suffix[k] integerValue]; 88 | if (t != -1) return j - t + 1; // 匹配串的前缀,是否匹配好后缀,关键 89 | for (NSInteger r = j+1; r <= m-1; ++r) { 90 | if ([_prifix[m-r] boolValue]) { // 关键 91 | return r; 92 | } 93 | } 94 | return m; 95 | } 96 | 97 | - (void)generateGS { 98 | NSUInteger m = _b.length; 99 | for (NSInteger i = 0; i < m; ++i) { 100 | _prifix[i] = @(NO); 101 | _suffix[i] = @(-1); 102 | } 103 | for (NSInteger i = 0; i < m - 1; ++i) { // 从 b 中取两个字符对比 104 | NSInteger j = i; 105 | NSInteger k = 0; // 公共后缀的长度 106 | int jValue = (int)[_b characterAtIndex:j]; 107 | int bmValue = (int)[_b characterAtIndex:(m-1-k)]; 108 | while (j >= 0 && jValue == bmValue) { // 与 b[0, m-1] 求公共子串 109 | ++k; 110 | --j; 111 | _suffix[k] = [NSNumber numberWithInteger:(j+1)]; //j+1 代表公共子串在 b 中的起始下标 112 | } 113 | if (j == -1) _prifix[k] = @(YES); 114 | } 115 | } 116 | 117 | #pragma mark - 118 | 119 | // 同步 120 | - (NSInteger)startMatch { 121 | return [self bm]; 122 | } 123 | 124 | // 异步 125 | - (void)startMatchCompeletion:(void (^)(NSInteger))completion { 126 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 127 | completion([self bm]); 128 | }); 129 | } 130 | 131 | @end 132 | -------------------------------------------------------------------------------- /object-c/bm_match/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // MyArray.h 3 | // demodemo 4 | // 5 | // Created by 李贺 on 2020/4/28. 6 | // Copyright © 2020 李贺. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BM.h" 11 | 12 | int main(int argc, const char * argv[]) { 13 | @autoreleasepool { 14 | BM *bm = [[BM alloc] initWithA:@"abacadc" andB:@"adc"]; 15 | 16 | [bm startMatchCompeletion:^(NSInteger index) { 17 | NSLog(@"异步查找到下标:%ld\n", index); 18 | }]; 19 | 20 | NSLog(@"同步查找到下标:%ld\n", [bm startMatch]); 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /swift/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiHe0308/algo/d7a6e867c2446cd3d2be33c30a62f4e69045e9c3/swift/.DS_Store -------------------------------------------------------------------------------- /swift/Array/MyArray.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/10. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | // Swift 泛型,此数组支持不同数据类型 9 | public struct MyArray { 10 | private var data: [Element] 11 | private var capacity = 0 // 数组长度 12 | private var count = 0 // 已保存的数据个数 13 | 14 | /// 构造方法 15 | /// - parameter defaultElement: 默认元素,用来占位 16 | /// - parameter capacity: 数组长度 17 | init(defaultElement: Element, capacity: Int) { 18 | data = [Element](repeating: defaultElement, count: capacity) 19 | self.capacity = capacity 20 | } 21 | 22 | // 根据 index,查找元素 23 | func find(at index: Int) -> Element? { 24 | // index 必须在 [0, count) 25 | guard index >= 0, index < count else { 26 | return nil 27 | } 28 | 29 | return data[index] 30 | } 31 | 32 | // 根据 index,删除元素 33 | mutating func delete(at index: Int) -> Bool { 34 | // index 必须在 [0, count) 35 | guard index >= 0, index < count else { 36 | return false 37 | } 38 | 39 | // [index, count - 1) 从 index 开始,元素分别向前移动一位 40 | for i in index ..< count - 1 { 41 | data[i] = data[i+1] 42 | } 43 | count -= 1 44 | return true 45 | } 46 | 47 | // 根据 index 插入元素 48 | mutating func insert(value: Element, at index: Int) -> Bool { 49 | // index 必须在 [0, count) 50 | guard index >= 0, index < count, count < capacity else { 51 | return false 52 | } 53 | 54 | // count - 1 ~ index 55 | for i in (index ... count - 1).reversed() { 56 | data[i + 1] = data[i] 57 | } 58 | 59 | data[index] = value 60 | count += 1 61 | return true 62 | } 63 | 64 | // 添加元素 65 | mutating func add(value: Element) -> Bool { 66 | guard count < capacity else { 67 | return false 68 | } 69 | data[count] = value 70 | count += 1 71 | return true 72 | } 73 | 74 | func printAll() { 75 | print("\(data)") 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /swift/Linkedlist/SinglyLinkedList.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/12. 3 | // Copyright © 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | class Node { 9 | var value: T? 10 | var next: Node? 11 | 12 | init(){} 13 | 14 | init(value: T) { 15 | self.value = value 16 | } 17 | } 18 | 19 | /// 单链表 20 | /// 实现插入、删除、查找操作 21 | class List { 22 | private var dummy = Node() // 哨兵结点,不存储数据 23 | var size: Int { 24 | var num = 0 25 | var tmpNode = dummy.next 26 | while tmpNode != nil { 27 | num += 1 28 | tmpNode = tmpNode!.next 29 | } 30 | return num 31 | } 32 | var isEmpty: Bool { return size > 0 } 33 | 34 | /// find node with value 35 | func node(with value: Element) -> Node? { 36 | var node = dummy.next 37 | while node != nil { 38 | if node!.value == value { 39 | return node 40 | } 41 | node = node!.next 42 | } 43 | 44 | return nil 45 | } 46 | // 约定:链表的 index 从 1 开始 47 | func node(at index: Int) -> Node? { 48 | var num = 1 49 | var node = dummy.next 50 | while node != nil { 51 | if num == index { 52 | return node 53 | } 54 | node = node!.next 55 | num += 1 56 | } 57 | return nil 58 | } 59 | 60 | func insertToHead(value: Element) { 61 | let newNode = Node(value: value) 62 | return insertToHead(node: newNode) 63 | } 64 | 65 | func insertToHead(node: Node) { 66 | node.next = dummy.next 67 | dummy.next = node 68 | } 69 | 70 | func insert(after node: Node, newValue: Element) { 71 | let newNode = Node(value: newValue) 72 | return insert(after: node, newNode: newNode) 73 | } 74 | 75 | func insert(after node: Node, newNode: Node) { 76 | newNode.next = node.next 77 | node.next = newNode 78 | } 79 | 80 | func insert(before node: Node, newValue: Element) { 81 | let newNode = Node(value: newValue) 82 | return insert(before: node, newNode: newNode) 83 | } 84 | 85 | func insert(before node: Node, newNode: Node) { 86 | var lastNode = dummy 87 | var tmpNode = dummy.next 88 | 89 | while tmpNode != nil { 90 | if tmpNode === node { 91 | newNode.next = tmpNode 92 | lastNode.next = newNode 93 | break 94 | } 95 | lastNode = tmpNode! 96 | tmpNode = tmpNode!.next 97 | } 98 | } 99 | 100 | func delete(node: Node) { 101 | var lastNode = dummy 102 | var tmpNode = dummy.next 103 | 104 | while tmpNode != nil { 105 | if tmpNode === node { 106 | lastNode.next = tmpNode!.next 107 | break 108 | } 109 | 110 | lastNode = tmpNode! 111 | tmpNode = tmpNode!.next 112 | } 113 | } 114 | /// 删除首个 value 符合要求的结点 115 | func delete(value: Element) { 116 | var lastNode = dummy 117 | var tmpNode = dummy.next 118 | while tmpNode != nil { 119 | if tmpNode!.value == value { 120 | lastNode.next = tmpNode!.next 121 | break 122 | } 123 | 124 | lastNode = tmpNode! 125 | tmpNode = tmpNode!.next 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /swift/Linkedlist_Algo/LinkedListAlgo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/13. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | /** 7 | * 1) 单链表反转 8 | * 2) 链表中环的检测 9 | * 3) 两个有序的链表合并 10 | * 4) 删除链表倒数第n个结点 11 | * 5) 求链表的中间结点 12 | */ 13 | import Foundation 14 | /// 单链表反转 15 | func reverseSinglyLinkedList(head: Node) -> Node? { 16 | var reverseHead: Node?, currentNode: Node?, prevNode: Node? 17 | currentNode = head 18 | while currentNode != nil { 19 | let nextNode = currentNode!.next 20 | if nextNode == nil { 21 | reverseHead = currentNode 22 | } 23 | currentNode!.next = prevNode 24 | prevNode = currentNode 25 | currentNode = nextNode 26 | } 27 | return reverseHead 28 | } 29 | /// 检测环 30 | func hasCircle(head: Node) -> Bool { 31 | var fast = head.next 32 | var slow: Node? = head 33 | while fast != nil { 34 | if fast === slow { 35 | return true 36 | } 37 | fast = fast!.next?.next 38 | slow = slow!.next 39 | } 40 | return false 41 | } 42 | /// 两个有序的链表合并 43 | func mergeSortedLists(headA: Node?, headB: Node?) -> Node? { 44 | guard let headA = headA else { 45 | return headB 46 | } 47 | guard let headB = headB else { 48 | return headA 49 | } 50 | 51 | var head: Node?, tail: Node? 52 | var nodeA: Node? = headA, nodeB: Node? = headB 53 | if nodeA!.value! < nodeB!.value! { 54 | head = nodeA 55 | nodeA = nodeA!.next 56 | } else { 57 | head = nodeB 58 | nodeB = nodeB!.next 59 | } 60 | tail = head 61 | 62 | while nodeA != nil, nodeB != nil { 63 | if nodeA!.value! < nodeB!.value! { 64 | tail!.next = nodeA 65 | nodeA = nodeA!.next 66 | } else { 67 | tail!.next = nodeB 68 | nodeB = nodeB!.next 69 | } 70 | tail = tail!.next 71 | } 72 | 73 | if nodeA != nil { 74 | tail?.next = nodeA 75 | } else { 76 | tail?.next = nodeB 77 | } 78 | 79 | return head 80 | } 81 | 82 | /// 删除倒数第n个结点 83 | func deleteNode(at lastNum: Int, in head: Node) { 84 | var slow: Node? = head 85 | var fast: Node? = head 86 | var num = 1 87 | while fast != nil, num < lastNum { 88 | fast = fast!.next 89 | num += 1 90 | } 91 | 92 | var prevNode: Node? 93 | while fast != nil { 94 | prevNode = slow 95 | fast = fast!.next 96 | slow = slow!.next 97 | } 98 | prevNode?.next = slow?.next 99 | } 100 | 101 | /// 求链表的中间结点 102 | func halfNode(in head: Node) -> Node? { 103 | var slow: Node? = head 104 | var fast: Node? = head 105 | 106 | while fast?.next != nil, fast?.next?.next != nil { 107 | fast = fast!.next?.next 108 | slow = slow!.next 109 | } 110 | return slow 111 | } 112 | -------------------------------------------------------------------------------- /swift/Queue/ArrayQueue.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/11. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | /// 用数组实现的队列 9 | struct ArrayQueue: Queue { 10 | /// 数组 11 | private var items: [Element] 12 | /// 数组最大长度 13 | private var capacity = 0 14 | /// 队头下标 15 | private var head = 0 16 | /// 队尾下标 17 | private var tail = 0 18 | 19 | /// 构造方法 20 | /// - parameter defaultElement: 默认元素 21 | /// - parameter capacity: 数组长度 22 | init(defaultElement: Element, capacity: Int) { 23 | self.capacity = capacity 24 | items = [Element](repeating: defaultElement, count: capacity) 25 | } 26 | 27 | // MARK: Protocol: Queue 28 | 29 | var isEmpty: Bool { return head == tail } 30 | 31 | var size: Int { return tail - head } 32 | 33 | var peek: Element? { return isEmpty ? nil : items[head] } 34 | 35 | // 没有数据搬移的实现,即实现了一个有界序列 36 | // mutating func enqueue(newElement: Element) -> Bool { 37 | // // 整个队列都占满了 38 | // if tail == capacity { 39 | // return false 40 | // } 41 | // 42 | // items[tail] = newElement 43 | // tail += 1 44 | // return true 45 | // } 46 | // 有数据搬移的实现,即实现了一个无界序列 47 | mutating func enqueue(newElement: Element) -> Bool { 48 | // 如果 tail == capacity 表示队列末尾没有空间了 49 | if tail == capacity { 50 | // 整个队列都占满了 51 | if head == 0 { return false } 52 | // 数据搬移 53 | for i in head ..< tail { 54 | items[i - head] = items[i] 55 | } 56 | // 搬移完之后重新更新 head 和 tail 57 | tail -= head 58 | head = 0 59 | } 60 | 61 | items[tail] = newElement 62 | tail += 1 63 | return true 64 | } 65 | 66 | mutating func dequeue() -> Element? { 67 | if isEmpty { 68 | return nil 69 | } 70 | 71 | let item = items[head] 72 | head += 1 73 | return item 74 | } 75 | } 76 | 77 | /// 使用2个数组实现无界队列,用到 Swift 中 Array 较多的方法 78 | /// 来源:《iOS 面试之道》(故胤道长,唐巧) 79 | struct ArrayQueue2: Queue { 80 | /// 输入数组,主要负责入队 81 | var inArray = [Element]() 82 | /// 输出数组,主要负责出队 83 | var outArray = [Element]() 84 | 85 | var isEmpty: Bool { return inArray.isEmpty && outArray.isEmpty } 86 | 87 | var size: Int { return inArray.count + outArray.count } 88 | 89 | // 当 outArray 为空时,返回 inArray 首个元素,否则返回 outArray 末尾元素 90 | var peek: Element? { return outArray.isEmpty ? inArray.first : outArray.last } 91 | 92 | mutating func enqueue(newElement: Element) -> Bool { 93 | // inArray 添加元素 94 | inArray.append(newElement) 95 | return true 96 | } 97 | 98 | mutating func dequeue() -> Element? { 99 | if outArray.isEmpty { 100 | // 将 inArray 倒序存入 outArray 中 101 | outArray = inArray.reversed() 102 | // 清空 inArray 103 | inArray.removeAll() 104 | } 105 | // 弹出 outArray 最后一个元素 106 | return outArray.popLast() 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /swift/Queue/CircularQueue.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/11. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | /// 循环队列 9 | struct CircularQueue: Queue { 10 | /// 数组 11 | private var items: [Element] 12 | /// 数组最大长度 13 | private var capacity = 0 14 | /// 队头下标 15 | private var head = 0 16 | /// 队尾下标 17 | private var tail = 0 18 | 19 | /// 构造方法 20 | /// - parameter defaultElement: 默认元素 21 | /// - parameter capacity: 数组长度 22 | init(defaultElement: Element, capacity: Int) { 23 | self.capacity = capacity 24 | items = [Element](repeating: defaultElement, count: capacity) 25 | } 26 | 27 | // MARK: Protocol: Queue 28 | 29 | var isEmpty: Bool { return head == tail } 30 | 31 | var size: Int { 32 | if tail >= head { 33 | return tail - head 34 | } else { 35 | return (tail + 1) + (capacity - head) 36 | } 37 | } 38 | 39 | var peek: Element? { return isEmpty ? nil : items[head] } 40 | 41 | mutating func enqueue(newElement: Element) -> Bool { 42 | // 整个队列都占满了 43 | if (tail + 1) % capacity == head { 44 | return false 45 | } 46 | 47 | items[tail] = newElement 48 | tail = (tail + 1) % capacity 49 | return true 50 | } 51 | 52 | mutating func dequeue() -> Element? { 53 | if isEmpty { 54 | return nil 55 | } 56 | 57 | let item = items[head] 58 | head = (head + 1) % capacity 59 | return item 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /swift/Queue/Queue.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/11. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | protocol Queue { 9 | /// 持有的数据类型 10 | associatedtype Element 11 | /// 是否为空 12 | var isEmpty: Bool { get } 13 | /// 队列大小 14 | var size: Int { get } 15 | /// 返回队列头部元素 16 | var peek: Element? { get } 17 | /// 入队 18 | mutating func enqueue(newElement: Element) -> Bool 19 | /// 出队 20 | mutating func dequeue() -> Element? 21 | } 22 | -------------------------------------------------------------------------------- /swift/Queue/QueueBasedOnLinkedList.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/11. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | struct QueueBasedOnLinkedList: Queue { 9 | /// 队首 10 | var head: Node? 11 | /// 队尾 12 | var tail: Node? 13 | 14 | // MARK: Protocol: Queue 15 | 16 | var isEmpty: Bool { return head == nil } 17 | 18 | var size: Int { 19 | if isEmpty { 20 | return 0 21 | } 22 | 23 | var count = 1 // head 本身算一个 24 | while head?.next != nil { 25 | count += 1 26 | } 27 | 28 | return count 29 | } 30 | 31 | var peek: Element? { return head?.value } 32 | 33 | mutating func enqueue(newElement: Element) -> Bool { 34 | if isEmpty { 35 | // 空队列 36 | let node = Node(value: newElement) 37 | head = node 38 | tail = node 39 | } else { 40 | tail!.next = Node(value: newElement) 41 | tail = tail!.next 42 | } 43 | return true 44 | } 45 | 46 | mutating func dequeue() -> Element? { 47 | if isEmpty { 48 | return nil 49 | } 50 | 51 | let node = head 52 | head = head!.next 53 | return node?.value 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /swift/Stack/Browser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/12. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | struct Page { 9 | /// 存储前进 url 10 | private var forwardArray = [String]() 11 | /// 存储后退 url 12 | private var backArray = [String]() 13 | 14 | var currentURL: String? { return forwardArray.last } 15 | 16 | init(url: String) { 17 | forwardArray.append(url) 18 | } 19 | /// 前进 20 | mutating func goForward(url: String) { 21 | forwardArray.append(url) 22 | } 23 | /// 后退 24 | mutating func goBack() { 25 | backArray.append(forwardArray.popLast()!) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /swift/Stack/BrowserDemo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/12. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | struct Page { 9 | /// 存储前进 url 10 | private var forwardArray = [String]() 11 | /// 存储后退 url 12 | private var backArray = [String]() 13 | 14 | var currentURL: String { return forwardArray.last! } 15 | 16 | init(url: String) { 17 | forwardArray.append(url) 18 | } 19 | /// 前进 20 | mutating func goForward(url: String) { 21 | forwardArray.append(url) 22 | } 23 | /// 后退 24 | mutating func goBack() { 25 | backArray.append(forwardArray.popLast()!) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /swift/Stack/Stack.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/12. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | protocol Stack { 9 | /// 持有的数据类型 10 | associatedtype Element 11 | /// 是否为空 12 | var isEmpty: Bool { get } 13 | /// 队列大小 14 | var size: Int { get } 15 | /// 返回队列头部元素 16 | var peek: Element? { get } 17 | /// 入栈 18 | mutating func push(newElement: Element) -> Bool 19 | /// 出栈 20 | mutating func pop() -> Element? 21 | } 22 | -------------------------------------------------------------------------------- /swift/Stack/StackBasedOnLinkedList.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jiandan on 2018/10/12. 3 | // Copyright (c) 2018 Jiandan. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | struct StackBasedOnLinkedList: Stack { 9 | private var head = Node() // 哨兵结点,不存储内容 10 | 11 | // MARK: Protocol: Stack 12 | 13 | var isEmpty: Bool { return head.next == nil } 14 | 15 | var size: Int { 16 | var count = 0 17 | var cur = head.next 18 | while cur != nil { 19 | count += 1 20 | cur = cur?.next 21 | } 22 | return count 23 | } 24 | 25 | var peek: Element? { return head.next?.value } 26 | 27 | func push(newElement: Element) -> Bool { 28 | let node = Node(value: newElement) 29 | node.next = head.next 30 | head.next = node 31 | return true 32 | } 33 | 34 | func pop() -> Element? { 35 | let node = head.next 36 | head.next = node?.next 37 | return node?.value 38 | } 39 | } 40 | --------------------------------------------------------------------------------