Merge branch 'master' of https://github.com/wangzheng0822/algo
This commit is contained in:
commit
d4eba0b686
@ -33,7 +33,7 @@ int insert(struct array *array, int elem)
|
||||
}
|
||||
|
||||
if (idx < array->used)
|
||||
memmove(&array->arr[array->used], &array->arr[idx],
|
||||
memmove(&array->arr[idx+1], &array->arr[idx],
|
||||
(array->used - idx) * sizeof(int));
|
||||
|
||||
array->arr[idx] = elem;
|
||||
|
281
c-cpp/06_linkedlist/singlelist_gc/singleList.c
Normal file
281
c-cpp/06_linkedlist/singlelist_gc/singleList.c
Normal file
@ -0,0 +1,281 @@
|
||||
#include "singleList.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
linkedList * listCreate()
|
||||
{
|
||||
linkedList *list = NULL;
|
||||
list = malloc(sizeof(*list));
|
||||
if (NULL == list)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list->dup = NULL;
|
||||
list->free = NULL;
|
||||
list->match = NULL;
|
||||
|
||||
list->head = NULL;
|
||||
list->len = 0;
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
// 释放
|
||||
void listRelease(linkedList *list)
|
||||
{
|
||||
if (NULL == list)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
listEmpty(list);
|
||||
|
||||
free(list);
|
||||
list = NULL;
|
||||
}
|
||||
|
||||
void listEmpty(linkedList *list)
|
||||
{
|
||||
if (NULL == list)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (NULL != list->head)
|
||||
{
|
||||
listNode *pNode = list->head;
|
||||
list->head = pNode->next;
|
||||
if (NULL != list->free)
|
||||
{
|
||||
list->free(pNode->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(pNode->value);
|
||||
}
|
||||
|
||||
pNode->next = NULL;
|
||||
free(pNode);
|
||||
pNode = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
linkedList * listAddNodeHead(linkedList *list, void * value)
|
||||
{
|
||||
if (NULL == list || NULL == value)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
listNode *node = NULL;
|
||||
node = malloc(sizeof(*node));
|
||||
if (NULL == node)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
node->value = value;
|
||||
node->next = list->head;
|
||||
list->head = node;
|
||||
|
||||
++list->len;
|
||||
return list;
|
||||
}
|
||||
|
||||
linkedList * listAddNodeTail(linkedList *list, void *value)
|
||||
{
|
||||
if (NULL == list || NULL == value)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
listNode *node = NULL;
|
||||
node = malloc(sizeof(*node));
|
||||
if (NULL == node)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
node->value = value;
|
||||
node->next = NULL;
|
||||
|
||||
if (NULL == list->head
|
||||
&& list->len == 0)
|
||||
{
|
||||
list->head = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
listNode *tail = list->head;
|
||||
listNode *pre = list->head;
|
||||
while (NULL != tail)
|
||||
{
|
||||
pre = tail;
|
||||
tail = tail->next;
|
||||
}
|
||||
|
||||
pre->next = node;
|
||||
}
|
||||
|
||||
++list->len;
|
||||
return list;
|
||||
}
|
||||
|
||||
linkedList * listInsertNode(linkedList *list, listNode *old_node, void *value, bool after)
|
||||
{
|
||||
if (NULL == list || NULL == old_node)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
listNode *pNode = NULL;
|
||||
pNode = malloc(sizeof(*pNode));
|
||||
if (NULL == pNode)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
pNode->value = value;
|
||||
if (after)
|
||||
{
|
||||
pNode->next = old_node->next;
|
||||
old_node->next = pNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
listNode *pre = list->head;
|
||||
while (pre->next != old_node)
|
||||
{
|
||||
pre = pre->next;
|
||||
}
|
||||
|
||||
if (NULL != pre)
|
||||
{
|
||||
pre->next = pNode;
|
||||
pNode->next = old_node;
|
||||
}
|
||||
}
|
||||
|
||||
++list->len;
|
||||
return list;
|
||||
}
|
||||
|
||||
// 没设置释放函数时不做释放处理
|
||||
void listDelNode(linkedList *list, listNode *node)
|
||||
{
|
||||
if (NULL == list || NULL == node)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
listNode *pre = list->head;
|
||||
listNode *cur = list->head;
|
||||
while (NULL != cur && cur != node)
|
||||
{
|
||||
pre = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
// 不在该链表中
|
||||
if (NULL == pre)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pre->next = node->next;
|
||||
node->next = NULL;
|
||||
--list->len;
|
||||
|
||||
if (NULL != list->free)
|
||||
{
|
||||
list->free(node->value);
|
||||
free(node);
|
||||
node = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
listNode * listSearchKey(linkedList *list, void *key)
|
||||
{
|
||||
if (NULL == list)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
listNode *node = list->head;
|
||||
while (NULL != node)
|
||||
{
|
||||
if (NULL != list->match)
|
||||
{
|
||||
if (list->match(key, node->value) == 0)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (key == node->value)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
listNode * listIndex(linkedList *list, long index)
|
||||
{
|
||||
if (NULL == list)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (index <= 0
|
||||
|| index > list->len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
listNode *pNode = list->head;
|
||||
for (long i = 0; i < index; ++i)
|
||||
{
|
||||
pNode = pNode->next;
|
||||
}
|
||||
|
||||
return pNode;
|
||||
}
|
||||
|
||||
linkedList* listRewind(linkedList *list)
|
||||
{
|
||||
if (NULL == list)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
listNode *head = list->head;
|
||||
listNode *pre = NULL;
|
||||
listNode *next = NULL;
|
||||
while (NULL != head)
|
||||
{
|
||||
next = head->next;
|
||||
head->next = pre;
|
||||
pre = head;
|
||||
head = next;
|
||||
}
|
||||
|
||||
list->head = pre;
|
||||
return list;
|
||||
}
|
||||
|
||||
size_t listLength(linkedList *list)
|
||||
{
|
||||
if (NULL == list)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return list->len;
|
||||
}
|
46
c-cpp/06_linkedlist/singlelist_gc/singleList.h
Normal file
46
c-cpp/06_linkedlist/singlelist_gc/singleList.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef __SINGLELIST_H__
|
||||
#define __SINGLELIST_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct listNode
|
||||
{
|
||||
struct listNode *next;
|
||||
void *value;
|
||||
}listNode;
|
||||
|
||||
typedef struct linkedList
|
||||
{
|
||||
listNode *head;
|
||||
size_t len;
|
||||
size_t typesize;
|
||||
|
||||
void(*dup)(void*, void*);
|
||||
int(*match)(void*, void*);
|
||||
void(*free)(void*);
|
||||
}linkedList;
|
||||
|
||||
#define listSetDupMethod(l,m) ((l)->dup = (m))
|
||||
#define listSetFreeMethod(l,m) ((l)->free = (m))
|
||||
#define listSetMatchMethod(l,m) ((l)->match = (m))
|
||||
|
||||
#define listGetDupMethod(l) ((l)->dup)
|
||||
#define listGetFree(l) ((l)->free)
|
||||
#define listGetMatchMethod(l) ((l)->match)
|
||||
|
||||
linkedList *listCreate();
|
||||
void listRelease(linkedList *list);
|
||||
void listEmpty(linkedList *list);
|
||||
linkedList *listAddNodeHead(linkedList *list, void *value);
|
||||
linkedList *listAddNodeTail(linkedList *list, void *value);
|
||||
linkedList *listInsertNode(linkedList *list, listNode *old_node, void *value, bool after);
|
||||
void listDelNode(linkedList *list, listNode *node);
|
||||
|
||||
listNode *listSearchKey(linkedList *list, void *key);
|
||||
listNode *listIndex(linkedList *list, long index);
|
||||
linkedList* listRewind(linkedList *list);
|
||||
|
||||
size_t listLength(linkedList *list);
|
||||
|
||||
#endif // !__SINGLELIST_H__
|
0
c-cpp/11_sorts/.gitkeep
Normal file
0
c-cpp/11_sorts/.gitkeep
Normal file
139
c-cpp/11_sorts/sorts.c
Normal file
139
c-cpp/11_sorts/sorts.c
Normal file
@ -0,0 +1,139 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct array {
|
||||
int size;
|
||||
int used;
|
||||
int *arr;
|
||||
};
|
||||
|
||||
void dump(struct array *array)
|
||||
{
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < array->used; idx++)
|
||||
printf("[%02d]: %08d\n", idx, array->arr[idx]);
|
||||
}
|
||||
|
||||
void alloc(struct array *array)
|
||||
{
|
||||
array->arr = (int *)malloc(array->size * sizeof(int));
|
||||
}
|
||||
|
||||
void bubble_sort(struct array *array)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (array->used <= 1)
|
||||
return;
|
||||
|
||||
for (i = 0; i < array->used; i++) {
|
||||
bool has_swap = false;
|
||||
for (j = 0; j < array->used - i - 1; j++) {
|
||||
if (array->arr[j] > array->arr[j+1]) {
|
||||
int tmp;
|
||||
tmp = array->arr[j];
|
||||
array->arr[j] = array->arr[j+1];
|
||||
array->arr[j+1] = tmp;
|
||||
has_swap = true;
|
||||
}
|
||||
|
||||
}
|
||||
if (!has_swap)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bubble_sort_test()
|
||||
{
|
||||
int idx;
|
||||
struct array ten_int = {10, 0, NULL};
|
||||
|
||||
alloc(&ten_int);
|
||||
for (idx = 0; idx < 10; idx++)
|
||||
ten_int.arr[idx] = 30 - idx;
|
||||
ten_int.used = 10;
|
||||
dump(&ten_int);
|
||||
bubble_sort(&ten_int);
|
||||
dump(&ten_int);
|
||||
}
|
||||
|
||||
void insertion_sort(struct array *array)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (array->used <= 1)
|
||||
return;
|
||||
|
||||
for (i = 1; i < array->used; i++) {
|
||||
int val = array->arr[i];
|
||||
|
||||
for (j = i - 1; j >= 0; j--) {
|
||||
if (val < array->arr[j])
|
||||
array->arr[j+1] = array->arr[j];
|
||||
else
|
||||
break;
|
||||
}
|
||||
array->arr[j+1] = val;
|
||||
}
|
||||
}
|
||||
|
||||
void insertion_sort_test()
|
||||
{
|
||||
int idx;
|
||||
struct array ten_int = {10, 0, NULL};
|
||||
|
||||
alloc(&ten_int);
|
||||
for (idx = 0; idx < 10; idx++)
|
||||
ten_int.arr[idx] = 30 - idx;
|
||||
ten_int.used = 10;
|
||||
dump(&ten_int);
|
||||
insertion_sort(&ten_int);
|
||||
dump(&ten_int);
|
||||
}
|
||||
|
||||
void selection_sort(struct array *array)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (array->used <= 1)
|
||||
return;
|
||||
|
||||
for (i = 0; i < array->used - 1; i++) {
|
||||
int tmp, idx = i;
|
||||
|
||||
for (j = i + 1; j < array->used; j++)
|
||||
if (array->arr[j] < array->arr[idx])
|
||||
idx = j;
|
||||
|
||||
if (idx == i)
|
||||
continue;
|
||||
|
||||
tmp = array->arr[i];
|
||||
array->arr[i] = array->arr[idx];
|
||||
array->arr[idx] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void selection_sort_test()
|
||||
{
|
||||
int idx;
|
||||
struct array ten_int = {10, 0, NULL};
|
||||
|
||||
alloc(&ten_int);
|
||||
for (idx = 0; idx < 10; idx++)
|
||||
ten_int.arr[idx] = 30 - idx;
|
||||
ten_int.used = 10;
|
||||
dump(&ten_int);
|
||||
selection_sort(&ten_int);
|
||||
dump(&ten_int);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
//bubble_sort_test();
|
||||
//selection_sort_test();
|
||||
insertion_sort_test();
|
||||
return 0;
|
||||
}
|
47
c-cpp/11_sorts/sorts.cpp
Normal file
47
c-cpp/11_sorts/sorts.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
// C program for implementation of selection sort
|
||||
#include <stdio.h>
|
||||
|
||||
void swap(int *xp, int *yp)
|
||||
{
|
||||
int temp = *xp;
|
||||
*xp = *yp;
|
||||
*yp = temp;
|
||||
}
|
||||
|
||||
void selectionSort(int arr[], int n)
|
||||
{
|
||||
int i, j, min_idx;
|
||||
|
||||
// One by one move boundary of unsorted subarray
|
||||
for (i = 0; i < n-1; i++)
|
||||
{
|
||||
// Find the minimum element in unsorted array
|
||||
min_idx = i;
|
||||
for (j = i+1; j < n; j++)
|
||||
if (arr[j] < arr[min_idx])
|
||||
min_idx = j;
|
||||
|
||||
// Swap the found minimum element with the first element
|
||||
swap(&arr[min_idx], &arr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to print an array */
|
||||
void printArray(int arr[], int size)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < size; i++)
|
||||
printf("%d ", arr[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// Driver program to test above functions
|
||||
int main()
|
||||
{
|
||||
int arr[] = {64, 25, 12, 22, 11};
|
||||
int n = sizeof(arr)/sizeof(arr[0]);
|
||||
selectionSort(arr, n);
|
||||
printf("Sorted array: \n");
|
||||
printArray(arr, n);
|
||||
return 0;
|
||||
}
|
89
c-cpp/11_sorts/sorts.hpp
Normal file
89
c-cpp/11_sorts/sorts.hpp
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Created by Liam Huang (Liam0205) on 2018/10/16.
|
||||
*/
|
||||
|
||||
#ifndef SORTS_SORTS_HPP_
|
||||
#define SORTS_SORTS_HPP_
|
||||
|
||||
#include <iterator>
|
||||
#include <functional>
|
||||
|
||||
template <typename BidirIt,
|
||||
typename BinaryPred = std::less<typename std::iterator_traits<BidirIt>::value_type>>
|
||||
void bubble_sort(BidirIt first, BidirIt last, BinaryPred comp = BinaryPred()) {
|
||||
if (std::distance(first, last) <= 1) { return; }
|
||||
bool flag = true;
|
||||
for (auto it = first; flag and it != last; ++it) {
|
||||
flag = false;
|
||||
for (auto itt = first; itt != last - std::distance(first, it) - 1; ++itt) {
|
||||
if (comp(*(itt + 1), *itt)) {
|
||||
std::swap(*itt, *(itt + 1));
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BidirIt,
|
||||
typename BinaryPred = std::less<typename std::iterator_traits<BidirIt>::value_type>>
|
||||
void insertion_sort(BidirIt first, BidirIt last, BinaryPred comp = BinaryPred()) {
|
||||
if (std::distance(first, last) <= 1) { return; }
|
||||
for (auto it = first + 1; it != last; ++it) {
|
||||
const auto target = *it;
|
||||
auto itt = it;
|
||||
for (; std::distance(first, itt) > 0 and comp(target, *(itt - 1)); --itt) {
|
||||
*itt = *(itt - 1);
|
||||
}
|
||||
*itt = target;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BidirIt,
|
||||
typename BinaryPred = std::less<typename std::iterator_traits<BidirIt>::value_type>>
|
||||
void selection_sort(BidirIt first, BidirIt last, BinaryPred comp = BinaryPred()) {
|
||||
if (std::distance(first, last) <= 1) { return; }
|
||||
for (auto it = first; it != last - 1; ++it) {
|
||||
auto tag = it;
|
||||
for (auto itt = it + 1; itt != last; ++itt) {
|
||||
if (comp(*itt, *tag)) {
|
||||
tag = itt;
|
||||
}
|
||||
}
|
||||
if (tag != it) {
|
||||
std::swap(*it, *tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename FrwdIt,
|
||||
typename BinaryPred = std::less<typename std::iterator_traits<FrwdIt>::value_type>>
|
||||
void bubble_down_sort(FrwdIt first, FrwdIt last, BinaryPred comp = BinaryPred()) {
|
||||
if (std::distance(first, last) <= 1) { return; }
|
||||
for (auto it = first; it != last; ++it) {
|
||||
for (auto itt = it + 1; itt != last; ++itt) {
|
||||
if (comp(*itt, *it)) {
|
||||
std::swap(*it, *itt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BidirIt,
|
||||
typename BinaryPred = std::less<typename std::iterator_traits<BidirIt>::value_type>>
|
||||
void shell_sort(BidirIt first, BidirIt last, BinaryPred comp = BinaryPred()) {
|
||||
const size_t len = std::distance(first, last);
|
||||
if (len <= 1) { return; }
|
||||
for (size_t step = len / 2; step >= 1; step /= 2) {
|
||||
for (auto it = first + step; it != last; ++it) {
|
||||
auto target = *it;
|
||||
auto itt = it - step;
|
||||
for (; std::distance(first, itt) >= 0 and comp(target, *itt); itt -= step) {
|
||||
*(itt + step) = *itt;
|
||||
}
|
||||
*(itt + step) = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SORTS_SORTS_HPP_
|
||||
|
45
c-cpp/11_sorts/sorts_test.cc
Normal file
45
c-cpp/11_sorts/sorts_test.cc
Normal file
@ -0,0 +1,45 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "sorts.hpp"
|
||||
|
||||
int main() {
|
||||
const std::vector<int> test_data{1, 2, 3, 0};
|
||||
|
||||
std::vector<int> a(test_data.begin(), test_data.end());
|
||||
bubble_sort(a.begin(), a.end());
|
||||
for (auto i : a) {
|
||||
std::cout << i << ' ';
|
||||
}
|
||||
std::cout << '\n';
|
||||
|
||||
std::vector<int> b(test_data.begin(), test_data.end());
|
||||
insertion_sort(b.begin(), b.end());
|
||||
for (auto i : b) {
|
||||
std::cout << i << ' ';
|
||||
}
|
||||
std::cout << '\n';
|
||||
|
||||
std::vector<int> c(test_data.begin(), test_data.end());
|
||||
selection_sort(c.begin(), c.end());
|
||||
for (auto i : c) {
|
||||
std::cout << i << ' ';
|
||||
}
|
||||
std::cout << '\n';
|
||||
|
||||
std::vector<int> d(test_data.begin(), test_data.end());
|
||||
bubble_down_sort(d.begin(), d.end());
|
||||
for (auto i : d) {
|
||||
std::cout << i << ' ';
|
||||
}
|
||||
std::cout << '\n';
|
||||
|
||||
std::vector<int> e(test_data.begin(), test_data.end());
|
||||
shell_sort(e.begin(), e.end());
|
||||
for (auto i : e) {
|
||||
std::cout << i << ' ';
|
||||
}
|
||||
std::cout << '\n';
|
||||
|
||||
return 0;
|
||||
}
|
0
c-cpp/12_sorts/.gitkeep
Normal file
0
c-cpp/12_sorts/.gitkeep
Normal file
84
c-cpp/12_sorts/merge_sort.c
Normal file
84
c-cpp/12_sorts/merge_sort.c
Normal file
@ -0,0 +1,84 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
void dump(int *arr, int size)
|
||||
{
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < size; idx++)
|
||||
printf("%08d\n", arr[idx]);
|
||||
}
|
||||
|
||||
void __merge(int *arr, int p, int q, int r)
|
||||
{
|
||||
int *tmp;
|
||||
int i, j, k;
|
||||
|
||||
tmp = (int*)malloc((r - p + 1) * sizeof(int));
|
||||
|
||||
if (!tmp)
|
||||
abort();
|
||||
|
||||
for (i = p, j = q + 1, k = 0; i <= q && j <= r;) {
|
||||
if (arr[i] <= arr[j])
|
||||
tmp[k++] = arr[i++];
|
||||
else
|
||||
tmp[k++] = arr[j++];
|
||||
}
|
||||
|
||||
if (i == q + 1) {
|
||||
for (; j <= r;)
|
||||
tmp[k++] = arr[j++];
|
||||
} else {
|
||||
for (; i <= q;)
|
||||
tmp[k++] = arr[i++];
|
||||
}
|
||||
|
||||
memcpy(arr + p, tmp, (r - p + 1) * sizeof(int));
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
void __merge_sort(int *arr, int p, int r)
|
||||
{
|
||||
int q;
|
||||
|
||||
if (p >= r)
|
||||
return;
|
||||
|
||||
q = (p + r) / 2;
|
||||
__merge_sort(arr, p, q);
|
||||
__merge_sort(arr, q + 1, r);
|
||||
__merge(arr, p, q, r);
|
||||
}
|
||||
|
||||
void merge_sort(int *arr, int size)
|
||||
{
|
||||
__merge_sort(arr, 0, size - 1);
|
||||
}
|
||||
|
||||
void merge_verify()
|
||||
{
|
||||
int test[10] = {5, 8, 9, 23, 67, 1, 3, 7, 31, 56};
|
||||
|
||||
__merge(test, 0, 4, 9);
|
||||
|
||||
dump(test, 10);
|
||||
}
|
||||
|
||||
void merge_sort_test()
|
||||
{
|
||||
int test[10] = {5, 8, 9, 23, 67, 1, 3, 7, 31, 56};
|
||||
|
||||
merge_sort(test, 10);
|
||||
|
||||
dump(test, 10);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
//merge_verify();
|
||||
merge_sort_test();
|
||||
return 0;
|
||||
}
|
62
c-cpp/12_sorts/merge_sort.hpp
Normal file
62
c-cpp/12_sorts/merge_sort.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Created by Liam Huang (Liam0205) on 2018/10/17.
|
||||
*/
|
||||
|
||||
#ifndef SORTS_MERGE_SORT_HPP_
|
||||
#define SORTS_MERGE_SORT_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
namespace detail {
|
||||
template <typename InputIt1, typename InputIt2, typename OutputIt,
|
||||
typename BinaryPred = std::less<typename std::iterator_traits<InputIt1>::value_type>>
|
||||
OutputIt merge(InputIt1 first1, InputIt1 last1,
|
||||
InputIt2 first2, InputIt2 last2,
|
||||
OutputIt d_first,
|
||||
BinaryPred comp = BinaryPred()) {
|
||||
for (; first1 != last1; ++d_first) {
|
||||
if (first2 == last2) {
|
||||
return std::copy(first1, last1, d_first);
|
||||
}
|
||||
if (comp(*first2, *first1)) {
|
||||
*d_first = *first2;
|
||||
++first2;
|
||||
} else {
|
||||
*d_first = *first1;
|
||||
++first1;
|
||||
}
|
||||
}
|
||||
return std::copy(first2, last2, d_first);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <typename FrwdIt,
|
||||
typename BinaryPred = std::less<typename std::iterator_traits<FrwdIt>::value_type>>
|
||||
void merge_sort(FrwdIt first, FrwdIt last, BinaryPred comp = BinaryPred()) {
|
||||
const auto len = std::distance(first, last);
|
||||
if (len <= 1) { return; }
|
||||
auto cut = first + len / 2;
|
||||
merge_sort(first, cut, comp);
|
||||
merge_sort(cut, last, comp);
|
||||
std::vector<typename std::iterator_traits<FrwdIt>::value_type> tmp;
|
||||
tmp.reserve(len);
|
||||
detail::merge(first, cut, cut, last, std::back_inserter(tmp), comp);
|
||||
std::copy(tmp.begin(), tmp.end(), first);
|
||||
}
|
||||
|
||||
template <typename BidirIt,
|
||||
typename BinaryPred = std::less<typename std::iterator_traits<BidirIt>::value_type>>
|
||||
void inplace_merge_sort(BidirIt first, BidirIt last, BinaryPred comp = BinaryPred()) {
|
||||
const auto len = std::distance(first, last);
|
||||
if (len <= 1) { return; }
|
||||
auto cut = first + len / 2;
|
||||
inplace_merge_sort(first, cut, comp);
|
||||
inplace_merge_sort(cut, last, comp);
|
||||
std::inplace_merge(first, cut, last, comp);
|
||||
}
|
||||
|
||||
#endif // SORTS_MERGE_SORT_HPP_
|
||||
|
28
c-cpp/12_sorts/merge_sort_test.cc
Normal file
28
c-cpp/12_sorts/merge_sort_test.cc
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Created by Liam Huang (Liam0205) on 2018/10/17.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "merge_sort.hpp"
|
||||
|
||||
int main() {
|
||||
const std::vector<int> test_data{0, -1, 3, 190, -500};
|
||||
|
||||
std::vector<int> a{test_data};
|
||||
merge_sort(a.begin(), a.end());
|
||||
for (auto i : a) {
|
||||
std::cout << i << ' ';
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
std::vector<int> b{test_data};
|
||||
inplace_merge_sort(b.begin(), b.end());
|
||||
for (auto i : b) {
|
||||
std::cout << i << ' ';
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
69
c-cpp/12_sorts/quick_sort.c
Normal file
69
c-cpp/12_sorts/quick_sort.c
Normal file
@ -0,0 +1,69 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
void dump(int *arr, int size)
|
||||
{
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < size; idx++)
|
||||
printf("%08d\n", arr[idx]);
|
||||
}
|
||||
|
||||
void swap(int *a, int *b)
|
||||
{
|
||||
int tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
int partition(int *arr, int p, int r)
|
||||
{
|
||||
//int pivot = arr[r];
|
||||
int i, j;
|
||||
|
||||
i = j = p;
|
||||
|
||||
for (; j < r; j++) {
|
||||
if (arr[j] < arr[r]) {
|
||||
swap(arr + i, arr + j);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
swap(arr + i, arr + r);
|
||||
return i;
|
||||
}
|
||||
|
||||
void __quick_sort(int *arr, int p, int r)
|
||||
{
|
||||
int q;
|
||||
|
||||
if (p >= r)
|
||||
return;
|
||||
|
||||
q = partition(arr, p, r);
|
||||
__quick_sort(arr, p, q-1);
|
||||
__quick_sort(arr, q+1, r);
|
||||
}
|
||||
|
||||
void quick_sort(int *arr, int size)
|
||||
{
|
||||
__quick_sort(arr, 0, size - 1);
|
||||
}
|
||||
|
||||
void quick_sort_test()
|
||||
{
|
||||
int test[10] = {5, 8, 9, 23, 67, 1, 3, 7, 31, 56};
|
||||
|
||||
quick_sort(test, 10);
|
||||
|
||||
dump(test, 10);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
quick_sort_test();
|
||||
return 0;
|
||||
}
|
71
c-cpp/12_sorts/quick_sort.hpp
Normal file
71
c-cpp/12_sorts/quick_sort.hpp
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Created by Liam Huang (Liam0205) on 2018/10/17.
|
||||
*/
|
||||
|
||||
#ifndef SORTS_QUICK_SORT_HPP_
|
||||
#define SORTS_QUICK_SORT_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
namespace detail {
|
||||
template <typename T, typename Compare = std::less<T>>
|
||||
const T& median(const T& a, const T& b, const T& c, Compare comp = Compare()) {
|
||||
if (comp(a, b) and comp(b, c) or comp(c, b) and comp(b, a)) {
|
||||
return b;
|
||||
} else if (comp(b, c) and comp(c, a) or comp(a, c) and comp(c, b)) {
|
||||
return c;
|
||||
} else {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iter,
|
||||
typename T = typename std::iterator_traits<Iter>::value_type,
|
||||
typename Compare = std::less<T>>
|
||||
const T& iter_median(Iter a, Iter b, Iter c, Compare comp = Compare()) {
|
||||
return median(*a, *b, *c, comp);
|
||||
}
|
||||
|
||||
template <typename BidirIt,
|
||||
typename T = typename std::iterator_traits<BidirIt>::value_type,
|
||||
typename Compare = std::less<T>>
|
||||
std::pair<BidirIt, BidirIt> inplace_partition(BidirIt first,
|
||||
BidirIt last,
|
||||
const T& pivot,
|
||||
Compare comp = Compare()) {
|
||||
BidirIt last_less, last_greater, first_equal, last_equal;
|
||||
for (last_less = first, last_greater = first, first_equal = last;
|
||||
last_greater != first_equal; ) {
|
||||
if (comp(*last_greater, pivot)) {
|
||||
std::iter_swap(last_greater++, last_less++);
|
||||
} else if (comp(pivot, *last_greater)) {
|
||||
++last_greater;
|
||||
} else { // pivot == *last_greater
|
||||
std::iter_swap(last_greater, --first_equal);
|
||||
}
|
||||
}
|
||||
const auto cnt = std::distance(first_equal, last);
|
||||
std::swap_ranges(first_equal, last, last_less);
|
||||
first_equal = last_less;
|
||||
last_equal = first_equal + cnt;
|
||||
return {first_equal, last_equal};
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <typename BidirIt,
|
||||
typename T = typename std::iterator_traits<BidirIt>::value_type,
|
||||
typename Compare = std::less<T>>
|
||||
void quick_sort(BidirIt first, BidirIt last, Compare comp = Compare()) {
|
||||
for (auto size = std::distance(first, last); size > 1; size = std::distance(first, last)) {
|
||||
const T pivot = detail::iter_median(first, last - 1, first + size / 2, comp);
|
||||
const auto eq = detail::inplace_partition(first, last, pivot, comp);
|
||||
quick_sort(first, eq.first, comp);
|
||||
first = eq.second; // Liam Huang: economize half of recursive calling.
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SORTS_QUICK_SORT_HPP_
|
||||
|
25
c-cpp/12_sorts/quick_sort_test.cc
Normal file
25
c-cpp/12_sorts/quick_sort_test.cc
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Created by Liam Huang (Liam0205) on 2018/10/17.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "quick_sort.hpp"
|
||||
|
||||
void test_quick_sort(std::vector<int> test_data) {
|
||||
quick_sort(test_data.begin(), test_data.end());
|
||||
std::transform(test_data.begin(), test_data.end(),
|
||||
std::ostream_iterator<int>(std::cout, " "), [](int i){ return i; });
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_quick_sort({-3, -1, 1, -2, -3, 0, -3, 100, 1, 1, -100});
|
||||
test_quick_sort({1, 1, 1});
|
||||
test_quick_sort({1, 0, -1});
|
||||
test_quick_sort({1});
|
||||
return 0;
|
||||
}
|
||||
|
0
c-cpp/14_sorts/.gitkeep
Normal file
0
c-cpp/14_sorts/.gitkeep
Normal file
8
c-cpp/14_sorts/analytics_of_std_sort.md
Normal file
8
c-cpp/14_sorts/analytics_of_std_sort.md
Normal file
@ -0,0 +1,8 @@
|
||||
# C++ STL 中的 std::sort 分析
|
||||
|
||||
参见 [Liam Huang 的博客](https://liam.page/)中的 3 篇文章:
|
||||
|
||||
* [谈谈基于比较的排序算法的复杂度下界](https://liam.page/2018/08/28/lower-bound-of-comparation-based-sort-algorithm/)
|
||||
* [谈谈内省式排序算法](https://liam.page/2018/08/29/introspective-sort/)
|
||||
* [谈谈 STL 中的 std::sort](https://liam.page/2018/09/18/std-sort-in-STL/)
|
||||
|
66
c-cpp/14_sorts/counting_sort.c
Normal file
66
c-cpp/14_sorts/counting_sort.c
Normal file
@ -0,0 +1,66 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
void dump(int *arr, int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
printf("%08d\n", arr[i]);
|
||||
}
|
||||
|
||||
// content in arr must be positive integer
|
||||
void counting_sort(int *arr, int size)
|
||||
{
|
||||
int max, i;
|
||||
int *count, *tmp;
|
||||
|
||||
if (size <= 1)
|
||||
return;
|
||||
|
||||
max = 0;
|
||||
// find the biggest integer
|
||||
for (i = 0; i < size; i++) {
|
||||
if (max < arr[i])
|
||||
max = arr[i];
|
||||
}
|
||||
|
||||
// init count to 0
|
||||
count = (int*)malloc((max+1) * sizeof(int));
|
||||
tmp = (int*)malloc(size * sizeof(int));
|
||||
if (!count || !tmp)
|
||||
return;
|
||||
memset(count, 0, (max + 1) * sizeof(int));
|
||||
|
||||
// counting
|
||||
for (i = 0; i < size; i++)
|
||||
count[arr[i]]++;
|
||||
for (i = 1; i < max + 1; i++)
|
||||
count[i] = count[i-1] + count[i];
|
||||
|
||||
// iterate arr and put it to the correct index in tmp
|
||||
for (i = 0; i < size; i++){
|
||||
int index = count[arr[i]] - 1;
|
||||
tmp[index] = arr[i];
|
||||
count[arr[i]]--;
|
||||
}
|
||||
|
||||
// move back to arr
|
||||
memcpy(arr, tmp, size * sizeof(int));
|
||||
}
|
||||
|
||||
void counting_sort_test()
|
||||
{
|
||||
int test_data[10] = {3, 23, 98, 1, 27, 36, 52, 89, 76, 44};
|
||||
|
||||
counting_sort(test_data, 10);
|
||||
dump(test_data, 10);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
counting_sort_test();
|
||||
return 0;
|
||||
}
|
0
c-cpp/15_bsearch/.gitkeep
Normal file
0
c-cpp/15_bsearch/.gitkeep
Normal file
66
c-cpp/15_bsearch/bsearch.hpp
Normal file
66
c-cpp/15_bsearch/bsearch.hpp
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Created by Liam Huang (Liam0205) on 2018/10/24.
|
||||
*/
|
||||
|
||||
#ifndef BSEARCH_BSEARCH_HPP_
|
||||
#define BSEARCH_BSEARCH_HPP_
|
||||
|
||||
#include <iterator>
|
||||
#include <functional>
|
||||
|
||||
enum class BsearchPolicy { FIRST, LAST, UNSPECIFIED };
|
||||
|
||||
// Liam Huang: The algorithm works right with iterators that meet the ForwardIterator requirement,
|
||||
// but with a bad time complexity. For better performance, iterators should meet
|
||||
// the RandomAccessIterator requirement.
|
||||
template <typename IterT,
|
||||
typename ValueT = typename std::iterator_traits<IterT>::value_type,
|
||||
typename Compare>
|
||||
IterT bsearch(IterT first,
|
||||
IterT last,
|
||||
ValueT target,
|
||||
Compare comp,
|
||||
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
|
||||
IterT result = last;
|
||||
while (std::distance(first, last) > 0) {
|
||||
IterT mid = first + std::distance(first, last) / 2;
|
||||
if (comp(*mid, target)) {
|
||||
first = mid + 1;
|
||||
} else if (comp(target, *mid)) {
|
||||
last = mid;
|
||||
} else { // equal
|
||||
if (policy == BsearchPolicy::FIRST) {
|
||||
if (mid == first or comp(*(mid - 1), *mid)) {
|
||||
result = mid;
|
||||
break;
|
||||
} else {
|
||||
last = mid;
|
||||
}
|
||||
} else if (policy == BsearchPolicy::LAST) {
|
||||
if (std::distance(mid, last) == 1 or comp(*mid, *(mid + 1))) {
|
||||
result = mid;
|
||||
break;
|
||||
} else {
|
||||
first = mid + 1;
|
||||
}
|
||||
} else {
|
||||
result = mid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename IterT,
|
||||
typename ValueT = typename std::iterator_traits<IterT>::value_type,
|
||||
typename Compare = std::less<ValueT>>
|
||||
IterT bsearch(IterT first,
|
||||
IterT last,
|
||||
ValueT target,
|
||||
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
|
||||
return bsearch(first, last, target, Compare(), policy);
|
||||
}
|
||||
|
||||
#endif // BSEARCH_BSEARCH_HPP_
|
||||
|
38
c-cpp/15_bsearch/bsearch_test.cc
Normal file
38
c-cpp/15_bsearch/bsearch_test.cc
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Created by Liam Huang (Liam0205) on 2018/10/24.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "bsearch.hpp"
|
||||
|
||||
template <typename VecT, typename T = typename VecT::value_type>
|
||||
void test_bsearch(const VecT& test,
|
||||
T target,
|
||||
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
|
||||
auto it = bsearch(test.begin(), test.end(), target, policy);
|
||||
std::cout << std::distance(test.begin(), it) << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::vector<int> test{0, 0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 5, 6, 7}; // std::less<int>()
|
||||
|
||||
test_bsearch(test, 8); // 14
|
||||
test_bsearch(test, -1); // 14
|
||||
test_bsearch(test, 0); // 0, 1
|
||||
test_bsearch(test, 0, BsearchPolicy::FIRST); // 0
|
||||
test_bsearch(test, 0, BsearchPolicy::LAST); // 1
|
||||
test_bsearch(test, 4); // 5, 6
|
||||
test_bsearch(test, 4, BsearchPolicy::FIRST); // 5
|
||||
test_bsearch(test, 4, BsearchPolicy::LAST); // 6
|
||||
test_bsearch(test, 5); // 7, 8, 9, 10, 11
|
||||
test_bsearch(test, 5, BsearchPolicy::FIRST); // 7
|
||||
test_bsearch(test, 5, BsearchPolicy::LAST); // 11
|
||||
test_bsearch(test, 7); // 13
|
||||
test_bsearch(test, 7, BsearchPolicy::FIRST); // 13
|
||||
test_bsearch(test, 7, BsearchPolicy::LAST); // 13
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,54 +1,66 @@
|
||||
package _1_sorts
|
||||
|
||||
func BubbleSort(a []int) {
|
||||
arrLen := len(a)
|
||||
if arrLen <= 1 {
|
||||
/*
|
||||
冒泡排序、插入排序、选择排序
|
||||
*/
|
||||
|
||||
//冒泡排序,a是数组,n表示数组大小
|
||||
func BubbleSort(a []int, n int) {
|
||||
if n <= 1 {
|
||||
return
|
||||
}
|
||||
for i := arrLen - 1; i > 0; i-- {
|
||||
for j := 0; j < i; j++ {
|
||||
for i := 0; i < n; i++ {
|
||||
// 提前退出标志
|
||||
flag := false
|
||||
for j := 0; j < n-i-1; j++ {
|
||||
if a[j] > a[j+1] {
|
||||
tmp := a[j+1]
|
||||
a[j+1] = a[j]
|
||||
a[j] = tmp
|
||||
a[j], a[j+1] = a[j+1], a[j]
|
||||
//此次冒泡有数据交换
|
||||
flag = true
|
||||
}
|
||||
}
|
||||
// 如果没有交换数据,提前退出
|
||||
if !flag {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func InsertSort(a []int) {
|
||||
arrLen := len(a)
|
||||
if arrLen <= 1 {
|
||||
// 插入排序,a表示数组,n表示数组大小
|
||||
func InsertionSort(a []int, n int) {
|
||||
if n <= 1 {
|
||||
return
|
||||
}
|
||||
for i := 1; i < arrLen; i++ {
|
||||
v := a[i]
|
||||
for i := 1; i < n; i++ {
|
||||
value := a[i]
|
||||
j := i - 1
|
||||
//查找要插入的位置并移动数据
|
||||
for ; j >= 0; j-- {
|
||||
if a[j] > v {
|
||||
if a[j] > value {
|
||||
a[j+1] = a[j]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
a[j+1] = v
|
||||
a[j+1] = value
|
||||
}
|
||||
}
|
||||
|
||||
func SelectionSort(a []int) {
|
||||
arrLen := len(a)
|
||||
if arrLen <= 1 {
|
||||
// 选择排序,a表示数组,n表示数组大小
|
||||
func SelectionSort(a []int, n int) {
|
||||
if n <= 1 {
|
||||
return
|
||||
}
|
||||
for i := 0; i < arrLen; i++ {
|
||||
for i := 0; i < n; i++ {
|
||||
// 查找最小值
|
||||
minIndex := i
|
||||
for j := i + 1; j < arrLen; j++ {
|
||||
for j := i + 1; j < n; j++ {
|
||||
if a[j] < a[minIndex] {
|
||||
minIndex = j
|
||||
}
|
||||
}
|
||||
if minIndex != i {
|
||||
tmp := a[minIndex]
|
||||
a[minIndex] = a[i]
|
||||
a[i] = tmp
|
||||
}
|
||||
// 交换
|
||||
a[i], a[minIndex] = a[minIndex],a[i]
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,43 +1,27 @@
|
||||
package _1_sorts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBubbleSort(t *testing.T) {
|
||||
a := []int{5, 4, 3, 2, 1}
|
||||
BubbleSort(a)
|
||||
t.Log(a)
|
||||
arr := []int{1,5,9,6,3,7,5,10}
|
||||
fmt.Println("排序前:",arr)
|
||||
BubbleSort(arr,len(arr))
|
||||
fmt.Println("排序后:",arr)
|
||||
}
|
||||
|
||||
func TestInsertionSort(t *testing.T) {
|
||||
arr := []int{1,5,9,6,3,7,5,10}
|
||||
fmt.Println("排序前:",arr)
|
||||
InsertionSort(arr,len(arr))
|
||||
fmt.Println("排序后:",arr)
|
||||
}
|
||||
|
||||
func TestSelectionSort(t *testing.T) {
|
||||
a := []int{5, 4, 3, 2, 1}
|
||||
SelectionSort(a)
|
||||
t.Log(a)
|
||||
}
|
||||
func TestInsertSort(t *testing.T) {
|
||||
a := []int{5, 4, 3, 2, 1}
|
||||
InsertSort(a)
|
||||
t.Log(a)
|
||||
}
|
||||
|
||||
func BenchmarkBubbleSort(b *testing.B) {
|
||||
a := []int{5, 4, 3, 2, 1}
|
||||
for i := 0; i < b.N; i++ {
|
||||
BubbleSort(a)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSelectionSort(b *testing.B) {
|
||||
a := []int{5, 4, 3, 2, 1}
|
||||
for i := 0; i < b.N; i++ {
|
||||
SelectionSort(a)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInsertSort(b *testing.B) {
|
||||
a := []int{5, 4, 3, 2, 1}
|
||||
for i := 0; i < b.N; i++ {
|
||||
InsertSort(a)
|
||||
}
|
||||
arr := []int{1,5,9,6,3,7,5,10}
|
||||
fmt.Println("排序前:",arr)
|
||||
SelectionSort(arr,len(arr))
|
||||
fmt.Println("排序后:",arr)
|
||||
}
|
||||
|
48
go/12_sorts/MergeSort.go
Normal file
48
go/12_sorts/MergeSort.go
Normal file
@ -0,0 +1,48 @@
|
||||
package _2_sorts
|
||||
|
||||
func MergeSort(arr []int) {
|
||||
arrLen := len(arr)
|
||||
if arrLen <= 1 {
|
||||
return
|
||||
}
|
||||
|
||||
mergeSort(arr, 0, arrLen-1)
|
||||
}
|
||||
|
||||
func mergeSort(arr []int, start, end int) {
|
||||
if start >= end {
|
||||
return
|
||||
}
|
||||
|
||||
mid := (start + end) / 2
|
||||
mergeSort(arr, start, mid)
|
||||
mergeSort(arr, mid+1, end)
|
||||
merge(arr, start, mid, end)
|
||||
}
|
||||
|
||||
func merge(arr []int, start, mid, end int) {
|
||||
tmpArr := make([]int, end-start+1)
|
||||
|
||||
i := start
|
||||
j := mid + 1
|
||||
k := 0
|
||||
for ; i <= mid && j <= end; k++ {
|
||||
if arr[i] < arr[j] {
|
||||
tmpArr[k] = arr[i]
|
||||
i++
|
||||
} else {
|
||||
tmpArr[k] = arr[j]
|
||||
j++
|
||||
}
|
||||
}
|
||||
|
||||
for ; i <= mid; i++ {
|
||||
tmpArr[k] = arr[i]
|
||||
k++
|
||||
}
|
||||
for ; j <= end; j++ {
|
||||
tmpArr[k] = arr[j]
|
||||
k++
|
||||
}
|
||||
copy(arr[start:end+1], tmpArr)
|
||||
}
|
13
go/12_sorts/MergeSort_test.go
Normal file
13
go/12_sorts/MergeSort_test.go
Normal file
@ -0,0 +1,13 @@
|
||||
package _2_sorts
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestMergeSort(t *testing.T) {
|
||||
arr := []int{5, 4}
|
||||
MergeSort(arr)
|
||||
t.Log(arr)
|
||||
|
||||
arr = []int{5, 4, 3, 2, 1}
|
||||
MergeSort(arr)
|
||||
t.Log(arr)
|
||||
}
|
38
go/12_sorts/QuickSort.go
Normal file
38
go/12_sorts/QuickSort.go
Normal file
@ -0,0 +1,38 @@
|
||||
package _2_sorts
|
||||
|
||||
func QuickSort(arr []int) {
|
||||
arrLen := len(arr)
|
||||
if arrLen <= 1 {
|
||||
return
|
||||
}
|
||||
quickSort(arr, 0, arrLen-1)
|
||||
}
|
||||
|
||||
func quickSort(arr []int, start, end int) {
|
||||
if start >= end {
|
||||
return
|
||||
}
|
||||
|
||||
pivot := partition(arr, start, end)
|
||||
quickSort(arr, start, pivot)
|
||||
quickSort(arr, pivot+1, end)
|
||||
}
|
||||
|
||||
func partition(arr []int, low, high int) int {
|
||||
pivotV := arr[low]
|
||||
for low < high {
|
||||
for low < high && arr[high] > pivotV { //指针从右边开始向右找到一个比pivot小的数
|
||||
high--
|
||||
}
|
||||
arr[low] = arr[high] //将这个数放到low位,注意第一次这个位置放的是pivot值,所以不会丢
|
||||
|
||||
for low < high && arr[low] < pivotV { //指针从左边开始向右找到第一个比pivot大的数
|
||||
low++
|
||||
}
|
||||
arr[high] = arr[low] //将这个数赋值给之前的high指针,因为之前high指针指向的数已经被一定,所以不会丢
|
||||
}
|
||||
|
||||
//最后将pivot的值放入合适位置,此时low与high相等
|
||||
arr[low] = pivotV
|
||||
return low
|
||||
}
|
13
go/12_sorts/QuickSort_test.go
Normal file
13
go/12_sorts/QuickSort_test.go
Normal file
@ -0,0 +1,13 @@
|
||||
package _2_sorts
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestQuickSort(t *testing.T) {
|
||||
arr := []int{5, 4}
|
||||
QuickSort(arr)
|
||||
t.Log(arr)
|
||||
|
||||
arr = []int{5, 4, 3, 2, 1}
|
||||
QuickSort(arr)
|
||||
t.Log(arr)
|
||||
}
|
33
go/14_sorts/CountingSort.go
Normal file
33
go/14_sorts/CountingSort.go
Normal file
@ -0,0 +1,33 @@
|
||||
package _4_sorts
|
||||
|
||||
import "math"
|
||||
|
||||
func CountingSort(a []int, n int) {
|
||||
if n <= 1 {
|
||||
return
|
||||
}
|
||||
|
||||
var max int = math.MinInt32
|
||||
for i := range a {
|
||||
if a[i] > max {
|
||||
max = a[i]
|
||||
}
|
||||
}
|
||||
|
||||
c := make([]int, max+1)
|
||||
for i := range a {
|
||||
c[a[i]]++
|
||||
}
|
||||
for i := 1; i <= max; i++ {
|
||||
c[i] += c[i-1]
|
||||
}
|
||||
|
||||
r := make([]int, n)
|
||||
for i := range a {
|
||||
index := c[a[i]] - 1
|
||||
r[index] = a[i]
|
||||
c[a[i]]--
|
||||
}
|
||||
|
||||
copy(a, r)
|
||||
}
|
13
go/14_sorts/CountingSort_test.go
Normal file
13
go/14_sorts/CountingSort_test.go
Normal file
@ -0,0 +1,13 @@
|
||||
package _4_sorts
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCountingSort(t *testing.T) {
|
||||
arr := []int{5, 4}
|
||||
CountingSort(arr, len(arr))
|
||||
t.Log(arr)
|
||||
|
||||
arr = []int{5, 4, 3, 2, 1}
|
||||
CountingSort(arr, len(arr))
|
||||
t.Log(arr)
|
||||
}
|
47
go/15_binarysearch/binarysearch.go
Normal file
47
go/15_binarysearch/binarysearch.go
Normal file
@ -0,0 +1,47 @@
|
||||
package _5_binarysearch
|
||||
|
||||
func BinarySearch(a []int, v int) int {
|
||||
n := len(a)
|
||||
if n == 0 {
|
||||
return -1
|
||||
}
|
||||
|
||||
low := 0
|
||||
high := n - 1
|
||||
for low <= high {
|
||||
mid := (low + high) / 2
|
||||
if a[mid] == v {
|
||||
return mid
|
||||
} else if a[mid] > v {
|
||||
high = mid - 1
|
||||
} else {
|
||||
low = mid + 1
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
func BinarySearchRecursive(a []int, v int) int {
|
||||
n := len(a)
|
||||
if n == 0 {
|
||||
return -1
|
||||
}
|
||||
|
||||
return bs(a, v, 0, n-1)
|
||||
}
|
||||
|
||||
func bs(a []int, v int, low, high int) int {
|
||||
if low > high {
|
||||
return -1
|
||||
}
|
||||
|
||||
mid := (low + high) / 2
|
||||
if a[mid] == v {
|
||||
return mid
|
||||
} else if a[mid] > v {
|
||||
return bs(a, v, low, mid-1)
|
||||
} else {
|
||||
return bs(a, v, mid+1, high)
|
||||
}
|
||||
}
|
27
go/15_binarysearch/binarysearch_test.go
Normal file
27
go/15_binarysearch/binarysearch_test.go
Normal file
@ -0,0 +1,27 @@
|
||||
package _5_binarysearch
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestBinarySearch(t *testing.T) {
|
||||
var a []int
|
||||
|
||||
a = []int{1, 3, 5, 6, 8}
|
||||
if BinarySearch(a, 8) != 4 {
|
||||
t.Fatal(BinarySearch(a, 3))
|
||||
}
|
||||
if BinarySearch(a, 4) != -1 {
|
||||
t.Fatal(BinarySearch(a, 4))
|
||||
}
|
||||
}
|
||||
|
||||
func TestBinarySearchRecursive(t *testing.T) {
|
||||
var a []int
|
||||
|
||||
a = []int{1, 3, 5, 6, 8}
|
||||
if BinarySearchRecursive(a, 8) != 4 {
|
||||
t.Fatal(BinarySearch(a, 3))
|
||||
}
|
||||
if BinarySearchRecursive(a, 4) != -1 {
|
||||
t.Fatal(BinarySearch(a, 4))
|
||||
}
|
||||
}
|
@ -2,20 +2,20 @@
|
||||
*
|
||||
* 1)泛型动态数组
|
||||
*
|
||||
* Author: shi
|
||||
* Author: shi
|
||||
*/
|
||||
|
||||
public class GenericArray<T> {
|
||||
private T[] data;
|
||||
private int size;
|
||||
|
||||
// 根据传入容量,构造Array
|
||||
// 根据传入容量,构造Array
|
||||
public GenericArray(int capacity) {
|
||||
data = (T[]) new Object[capacity];
|
||||
size = 0;
|
||||
}
|
||||
|
||||
// 无参构造方法,默认数组容量为10
|
||||
// 无参构造方法,默认数组容量为10
|
||||
public GenericArray() {
|
||||
this(10);
|
||||
}
|
||||
@ -71,7 +71,7 @@
|
||||
// 在 index 位置,插入元素e, 时间复杂度 O(m+n)
|
||||
public void add(int index, T e) {
|
||||
checkIndex(index);
|
||||
// 如果当前元素个数等于数组容量,则将数组扩容为原来的2倍
|
||||
// 如果当前元素个数等于数组容量,则将数组扩容为原来的2倍
|
||||
if (size == data.length) {
|
||||
resize(2 * data.length);
|
||||
}
|
||||
@ -158,7 +158,7 @@
|
||||
|
||||
private void checkIndex(int index) {
|
||||
if (index < 0 || index > size) {
|
||||
throw new IllegalArgumentException("Add failed! Require index >=0 and index <= size.");
|
||||
throw new IllegalArgumentException("Add failed! Require index >=0 and index <= size.");
|
||||
}
|
||||
}
|
||||
}
|
@ -49,15 +49,31 @@ public class Sorts {
|
||||
// 选择排序,a表示数组,n表示数组大小
|
||||
public static void selectionSort(int[] a, int n) {
|
||||
if (n <= 1) return;
|
||||
<<<<<<< HEAD
|
||||
for (int i = 0; i < n; ++i) {
|
||||
// 查找最小值
|
||||
int minIndex = i;
|
||||
int minValue = a[i];
|
||||
for (int j = i; j < n; ++j) {
|
||||
if (a[j] < minValue) {
|
||||
minValue = a[j];
|
||||
=======
|
||||
for (int i = 0; i < n - 1; ++i) {
|
||||
// 查找最小值
|
||||
int minIndex = i;
|
||||
for (int j = i + 1; j < n; ++j) {
|
||||
if (a[j] < a[minIndex]) {
|
||||
>>>>>>> upstream/master
|
||||
minIndex = j;
|
||||
}
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
if (minIndex == i)
|
||||
continue;
|
||||
|
||||
>>>>>>> upstream/master
|
||||
// 交换
|
||||
int tmp = a[i];
|
||||
a[i] = a[minIndex];
|
||||
|
@ -15,8 +15,8 @@ public class MergeSort {
|
||||
// 递归终止条件
|
||||
if (p >= r) return;
|
||||
|
||||
// 取p到r之间的中间位置q
|
||||
int q = (p+r)/2;
|
||||
// 取p到r之间的中间位置q,防止(p+r)的和超过int类型最大值
|
||||
int q = p + (r - p)/2;
|
||||
// 分治递归
|
||||
mergeSortInternally(a, p, q);
|
||||
mergeSortInternally(a, q+1, r);
|
||||
|
@ -282,7 +282,7 @@ Point 2: 2, 4
|
||||
Point 3: 8, 1
|
||||
Point 4: 2, 9
|
||||
|
||||
也可以用之前的 puh() 等操作方法来操作对象数组
|
||||
也可以用之前的 push() 等操作方法来操作对象数组
|
||||
```
|
||||
var p5 = new Point(11,13);
|
||||
point.push(p5);
|
||||
|
68
javascript/11_sorts/sort.js
Normal file
68
javascript/11_sorts/sort.js
Normal file
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 冒泡,插入,选择排序
|
||||
*
|
||||
* Author: nameczz
|
||||
*/
|
||||
|
||||
// 冒泡排序
|
||||
const bubbleSort = (arr) => {
|
||||
if (arr.length <= 1) return
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
let hasChange = false
|
||||
for (let j = 0; j < arr.length - i - 1; j++) {
|
||||
if (arr[j] > arr[j + 1]) {
|
||||
const temp = arr[j]
|
||||
arr[j] = arr[j + 1]
|
||||
arr[j + 1] = temp
|
||||
hasChange = true
|
||||
}
|
||||
}
|
||||
// 如果false 说明所有元素已经到位
|
||||
if (!hasChange) break
|
||||
}
|
||||
console.log(arr)
|
||||
}
|
||||
|
||||
// 插入排序
|
||||
const insertionSort = (arr) => {
|
||||
if (arr.length <= 1) return
|
||||
for (let i = 1; i < arr.length; i++) {
|
||||
const temp = arr[i]
|
||||
let j = i - 1
|
||||
// 若arr[i]前有大于arr[i]的值的化,向后移位,腾出空间,直到一个<=arr[i]的值
|
||||
for (j; j >= 0; j--) {
|
||||
if (arr[j] > temp) {
|
||||
arr[j + 1] = arr[j]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
arr[j + 1] = temp
|
||||
}
|
||||
console.log(arr)
|
||||
}
|
||||
|
||||
// 选择排序
|
||||
const selectionSort = (arr) => {
|
||||
if (arr.length <= 1) return
|
||||
// 需要注意这里的边界, 因为需要在内层进行 i+1后的循环,所以外层需要 数组长度-1
|
||||
for (let i = 0; i < arr.length - 1; i++) {
|
||||
let minIndex = i
|
||||
for (let j = i + 1; j < arr.length; j++) {
|
||||
if (arr[j] < arr[minIndex]) {
|
||||
minIndex = j // 找到整个数组的最小值
|
||||
}
|
||||
}
|
||||
const temp = arr[i]
|
||||
arr[i] = arr[minIndex]
|
||||
arr[minIndex] = temp
|
||||
}
|
||||
console.log(arr)
|
||||
}
|
||||
|
||||
const test = [4, 5, 6, 3, 2, 1]
|
||||
bubbleSort(test)
|
||||
const testSort = [4, 1, 6, 3, 2, 1]
|
||||
insertionSort(testSort)
|
||||
const testSelect = [4, 8, 6, 3, 2, 1, 0, 12]
|
||||
selectionSort(testSelect)
|
43
javascript/12_sorts/MergeSort.js
Normal file
43
javascript/12_sorts/MergeSort.js
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 归并排序
|
||||
*
|
||||
* Author: nameczz
|
||||
*/
|
||||
|
||||
const mergeArr = (left, right) => {
|
||||
let temp = []
|
||||
let leftIndex = 0
|
||||
let rightIndex = 0
|
||||
// 判断2个数组中元素大小,依次插入数组
|
||||
while (left.length > leftIndex && right.length > rightIndex) {
|
||||
if (left[leftIndex] <= right[rightIndex]) {
|
||||
temp.push(left[leftIndex])
|
||||
leftIndex++
|
||||
} else {
|
||||
temp.push(right[rightIndex])
|
||||
rightIndex++
|
||||
}
|
||||
}
|
||||
// 合并 多余数组
|
||||
return temp.concat(left.slice(leftIndex)).concat(right.slice(rightIndex))
|
||||
}
|
||||
|
||||
const mergeSort = (arr) => {
|
||||
// 当任意数组分解到只有一个时返回。
|
||||
if (arr.length <= 1) return arr
|
||||
const middle = Math.floor(arr.length / 2) // 找到中间值
|
||||
const left = arr.slice(0, middle) // 分割数组
|
||||
const right = arr.slice(middle)
|
||||
// 递归 分解 合并
|
||||
return mergeArr(mergeSort(left), mergeSort(right))
|
||||
}
|
||||
|
||||
const testArr = []
|
||||
let i = 0
|
||||
while (i < 100) {
|
||||
testArr.push(Math.floor(Math.random() * 1000))
|
||||
i++
|
||||
}
|
||||
|
||||
const res = mergeSort(testArr)
|
||||
console.log(res)
|
46
javascript/12_sorts/QuickSort.js
Normal file
46
javascript/12_sorts/QuickSort.js
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 快速排序
|
||||
*
|
||||
* Author: nameczz
|
||||
*/
|
||||
|
||||
const swap = (arr, i, j) => {
|
||||
const temp = arr[i]
|
||||
arr[i] = arr[j]
|
||||
arr[j] = temp
|
||||
}
|
||||
|
||||
// 获取 pivot 交换完后的index
|
||||
const partition = (arr, pivot, left, right) => {
|
||||
const pivotVal = arr[pivot]
|
||||
let startIndex = left
|
||||
for (let i = left; i < right; i++) {
|
||||
if (arr[i] < pivotVal) {
|
||||
swap(arr, i, startIndex)
|
||||
startIndex++
|
||||
}
|
||||
}
|
||||
swap(arr, startIndex, pivot)
|
||||
return startIndex
|
||||
}
|
||||
|
||||
const quickSort = (arr, left, right) => {
|
||||
if (left < right) {
|
||||
let pivot = right
|
||||
let partitionIndex = partition(arr, pivot, left, right)
|
||||
quickSort(arr, left, partitionIndex - 1 < left ? left : partitionIndex - 1)
|
||||
quickSort(arr, partitionIndex + 1 > right ? right : partitionIndex + 1, right)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const testArr = []
|
||||
let i = 0
|
||||
while (i < 10) {
|
||||
testArr.push(Math.floor(Math.random() * 1000))
|
||||
i++
|
||||
}
|
||||
console.log('unsort', testArr)
|
||||
quickSort(testArr, 0, testArr.length - 1);
|
||||
console.log('sort', testArr)
|
100
notes/11_sorts/readme.md
Normal file
100
notes/11_sorts/readme.md
Normal file
@ -0,0 +1,100 @@
|
||||
# 排序(上)
|
||||
|
||||
| 排序算法 | 时间复杂度 | 是否基于比较 |
|
||||
|---------|----|----|
|
||||
| 冒泡、插入、选择 | $O(n^2)$ | [y] |
|
||||
| 快排、归并 | $O(n\log n)$ | [y] |
|
||||
| 桶、基数、计数 | $O(n) | [x] |
|
||||
|
||||
开篇问题:插入排序和冒泡排序的时间复杂度相同,都是 $O(n^2)$,在实际软件开发中,为什么我们更倾向于使用插入排序而不是冒泡排序?
|
||||
|
||||
## 如何分析「排序算法」?
|
||||
|
||||
### 算法执行效率
|
||||
|
||||
1. 最好、最坏、平均情况的时间复杂度
|
||||
2. 时间复杂度的系数、低阶、常数——在渐进复杂度相同的情况下,需要比较系数、低阶和常数
|
||||
3. 比较和交换(移动)的次数——基于比较的排序算法的两种基本操作
|
||||
|
||||
### 算法的内存消耗
|
||||
|
||||
是否为原地排序算法(In-place sort algorithm),即算法的空间复杂度是否为 $O(1)$。
|
||||
|
||||
### 排序的稳定性
|
||||
|
||||
经过排序算法处理后,值相同的元素,在原序列和排序后序列中的相对位置保持不变,则称该排序算法是稳定的。
|
||||
|
||||
> 待排序的 `item` 并不是简单的值,而是一个基于对象中的某个 `key` 进行排序时,排序的稳定性就有意义了。
|
||||
|
||||
## 冒泡排序
|
||||
|
||||
* 每次循环都从序列起始位置开始
|
||||
* 循环中的每个动作,都对比相邻两个元素的大小是否满足偏序要求,若不满足,则交换顺序
|
||||
|
||||
![冒泡排序例图](https://static001.geekbang.org/resource/image/88/34/8890cbf63ea80455ce82490a23361134.jpg)
|
||||
|
||||
分析:
|
||||
|
||||
* 原地排序
|
||||
* 稳定排序(偏序关系是严格的偏序关系,如 `<` 或 `>`)
|
||||
* 时间复杂度
|
||||
* 最好 $O(n)$
|
||||
* 最坏 $O(n^2)$
|
||||
* 平均 $O(n^2)$
|
||||
|
||||
### 冒泡排序的平均时间复杂度非严格分析
|
||||
|
||||
* 有序度:序列中满足偏序关系的两两组合的元素对的个数
|
||||
* 满有序度:排序完成的序列的有序度,它等于 $n(n - 1) / 2$
|
||||
* 逆序度:序列中不满足偏序关系的亮亮组合的元素对的个数
|
||||
|
||||
显然,$\text{逆序度} = \text{满有序度} - \text{有序度}$。
|
||||
|
||||
在冒泡排序中,每产生一次「交换」操作,$\text{逆序度}--$。于是,平均情况下,需要 $n(n - 1)/4$ 次交换操作,它已经是 $O(n^2)$ 了。因此,尽管比较操作的数量会大于交换操作的数量,但我们依然能说,冒泡排序的平均时间复杂度是 $O(n^2)$。
|
||||
|
||||
> 分析过程不严格,但足够说明问题。
|
||||
|
||||
## 插入排序
|
||||
|
||||
1. 将待排序数列分为已排序区间和未排序区间
|
||||
2. 取未排序区间的第一个元素
|
||||
3. 遍历已排序区间,按照偏序关系,寻找合适的位置,插入未排序区间的第一个元素
|
||||
4. 重复 2 -- 3 直至未排序区间长度为零
|
||||
|
||||
![插入排序例图](https://static001.geekbang.org/resource/image/fd/01/fd6582d5e5927173ee35d7cc74d9c401.jpg)
|
||||
|
||||
分析:
|
||||
|
||||
* 原地排序
|
||||
* 稳定排序(值相同的元素,往后插)
|
||||
* 时间复杂度
|
||||
* 最好 $O(n)$
|
||||
* 最坏 $O(n^2)$
|
||||
* 平均 $O(n^2)$(乘法法则)
|
||||
|
||||
## 选择排序
|
||||
|
||||
1. 将待排序数列分为已排序区间和未排序区间
|
||||
2. 遍历未排序区间,取未排序区间的最小元素
|
||||
3. 交换上述最小元素与未排序区间中的第一个元素的位置
|
||||
4. 重复 2 -- 3 直至未排序区间长度为零
|
||||
|
||||
![选择排序例图](https://static001.geekbang.org/resource/image/32/1d/32371475a0b08f0db9861d102474181d.jpg)
|
||||
|
||||
分析:
|
||||
|
||||
* 非原地排序
|
||||
* 非稳定排序
|
||||
* 时间复杂度
|
||||
* 最好 $O(n^2)$
|
||||
* 最坏 $O(n^2)$
|
||||
* 平均 $O(n^2)$(乘法法则)
|
||||
|
||||
## 开篇问题
|
||||
|
||||
* 对同一份未排序序列数据,冒泡排序和插入排序所需的交换(移动)次数是一定的,且是相等的
|
||||
* 单次数据交换,冒泡排序所需的时间更长(三次赋值操作,插排只需要一次)
|
||||
|
||||
另有插入排序的优化版本[希尔排序](https://zh.wikipedia.org/wiki/%E5%B8%8C%E5%B0%94%E6%8E%92%E5%BA%8F)。
|
||||
|
||||
![小结](https://static001.geekbang.org/resource/image/34/50/348604caaf0a1b1d7fee0512822f0e50.jpg)
|
@ -28,6 +28,8 @@ function expression($str)
|
||||
array_push($operStack, $arr[$i]);
|
||||
break;
|
||||
case '*':
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
$arrLen = count($operStack);
|
||||
while ($operStack[$arrLen-1] === '/'){
|
||||
compute($numStack, $operStack);
|
||||
@ -36,6 +38,7 @@ function expression($str)
|
||||
array_push($operStack, $arr[$i]);
|
||||
break;
|
||||
|
||||
>>>>>>> upstream/master
|
||||
case '/':
|
||||
case '(':
|
||||
array_push($operStack, $arr[$i]);
|
||||
@ -78,9 +81,13 @@ function compute(&$numStack, &$operStack){
|
||||
case '-':
|
||||
array_push($numStack, array_pop($numStack) - $num);
|
||||
break;
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
case '(':
|
||||
throw new \Exception("不匹配的(", 2);
|
||||
break;
|
||||
>>>>>>> upstream/master
|
||||
}
|
||||
}
|
||||
expression('-1+2-(1+2*3)');
|
||||
|
66
php/12_sort/mergeSort.php
Normal file
66
php/12_sort/mergeSort.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
$arr = [4, 5, 6, 1, 3, 2];
|
||||
$length = count($arr);
|
||||
|
||||
$p = 0;
|
||||
$r = $length - 1;
|
||||
|
||||
$result = $this->mergeSort($arr, $p, $r);
|
||||
|
||||
var_dump($result);
|
||||
|
||||
|
||||
//递归调用,分解数组
|
||||
function mergeSort(array $arr, $p, $r)
|
||||
{
|
||||
if ($p >= $r) {
|
||||
return [$arr[$r]];
|
||||
}
|
||||
$q = (int)(($p + $r) / 2);
|
||||
|
||||
$left = $this->mergeSort($arr, $p, $q);
|
||||
$right = $this->mergeSort($arr, $q + 1, $r);
|
||||
return $this->merge($left, $right);
|
||||
}
|
||||
|
||||
//合并
|
||||
function merge(array $left, array $right)
|
||||
{
|
||||
$tmp = [];
|
||||
|
||||
$i = 0;
|
||||
|
||||
$j = 0;
|
||||
|
||||
$leftLength = count($left);
|
||||
|
||||
$rightLength = count($right);
|
||||
|
||||
do {
|
||||
if ($left[$i] <= $right[$j]) {
|
||||
$tmp[] = $left[$i++];
|
||||
} else {
|
||||
$tmp[] = $right[$j++];
|
||||
}
|
||||
|
||||
} while ($i < $leftLength && $j < $rightLength);
|
||||
|
||||
|
||||
$start = $i;
|
||||
$end = $leftLength;
|
||||
$copyArr = $left;
|
||||
|
||||
if ($j < $rightLength) {
|
||||
$start = $j;
|
||||
$end = $rightLength;
|
||||
$copyArr = $right;
|
||||
}
|
||||
|
||||
for (; $start < $end; $start++) {
|
||||
$tmp[] = $copyArr[$start];
|
||||
}
|
||||
|
||||
return $tmp;
|
||||
|
||||
}
|
@ -17,7 +17,11 @@
|
||||
* findMiddleNode 求链表的中间结点
|
||||
|
||||
#### 08_stack
|
||||
<<<<<<< HEAD
|
||||
* 链栈实现
|
||||
=======
|
||||
* 链栈实现
|
||||
|
||||
#### 09_stack
|
||||
* 队列链表实现
|
||||
>>>>>>> upstream/master
|
||||
|
78
php/Stack/Compute.php
Normal file
78
php/Stack/Compute.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
// 四则运算 +-*/()
|
||||
function expression($str)
|
||||
{
|
||||
$str = str_replace(' ','',$str);
|
||||
$arr = preg_split('/([\+\-\*\/\(\)])/', $str, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
$numStack = []; // 存放数字
|
||||
$operStack = []; // 存放运算符
|
||||
$operStack[] = NULL;
|
||||
|
||||
for ($i = 0; $i < count($arr); $i++){
|
||||
if (ord($arr[$i]) >= 48 && ord($arr[$i] <= 57)){
|
||||
array_push($numStack, $arr[$i]);
|
||||
continue;
|
||||
}
|
||||
switch ($arr[$i]){
|
||||
case '+':
|
||||
case '-':
|
||||
$arrLen = count($operStack);
|
||||
while ($operStack[$arrLen-1] === '*' || $operStack[$arrLen-1] === '/' || $operStack[$arrLen-1] === '-'){
|
||||
compute($numStack, $operStack);
|
||||
$arrLen--;
|
||||
}
|
||||
array_push($operStack, $arr[$i]);
|
||||
break;
|
||||
case '*':
|
||||
case '/':
|
||||
case '(':
|
||||
array_push($operStack, $arr[$i]);
|
||||
break;
|
||||
case ')':
|
||||
$arrLen = count($operStack);
|
||||
while ($operStack[$arrLen-1] !== '('){
|
||||
compute($numStack, $operStack);
|
||||
$arrLen--;
|
||||
}
|
||||
array_pop($operStack);
|
||||
break;
|
||||
default:
|
||||
throw new \Exception("不支持的运算符", 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$arrLen = count($operStack);
|
||||
while ($operStack[$arrLen-1] !== NULL){
|
||||
compute($numStack, $operStack);
|
||||
$arrLen--;
|
||||
}
|
||||
echo array_pop($numStack);
|
||||
}
|
||||
|
||||
//数字栈长度减一,运算符栈长度减一
|
||||
function compute(&$numStack, &$operStack){
|
||||
$num = array_pop($numStack);
|
||||
switch (array_pop($operStack)) {
|
||||
case '*':
|
||||
array_push($numStack, array_pop($numStack) * $num);
|
||||
break;
|
||||
case '/':
|
||||
array_push($numStack, array_pop($numStack) / $num);
|
||||
break;
|
||||
case '+':
|
||||
array_push($numStack, array_pop($numStack) + $num);
|
||||
break;
|
||||
case '-':
|
||||
array_push($numStack, array_pop($numStack) - $num);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
expression('-1+2-(1+2*3)');
|
||||
echo PHP_EOL;
|
||||
eval('echo -1+2-(1+2*3);');
|
@ -7,8 +7,12 @@
|
||||
"psr-4": {
|
||||
"Algo_06\\": "06_linkedlist/",
|
||||
"Algo_07\\": "07_linkedlist/",
|
||||
<<<<<<< HEAD
|
||||
"Algo_08\\": "08_stack/"
|
||||
=======
|
||||
"Algo_08\\": "08_stack/",
|
||||
"Algo_09\\": "09_queue/"
|
||||
>>>>>>> upstream/master
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,35 +9,53 @@ class MyArray:
|
||||
"""A simple wrapper around List.
|
||||
You cannot have -1 in the array.
|
||||
"""
|
||||
|
||||
def __init__(self, capacity: int):
|
||||
|
||||
self._data = []
|
||||
self._count = 0
|
||||
self._capacity = capacity
|
||||
|
||||
def __getitem__(self, position: int) -> int:
|
||||
|
||||
"""Support for subscript.
|
||||
Perhaps better than the find() method below.
|
||||
"""
|
||||
return self._data[position]
|
||||
|
||||
def find(self, index: int) -> Optional[int]:
|
||||
|
||||
if index >= self._count or index <= -self._count: return None
|
||||
return self._data[index]
|
||||
|
||||
def delete(self, index: int) -> bool:
|
||||
|
||||
if index >= self._count or index <= -self._count: return False
|
||||
|
||||
self._data[index:-1] = self._data[index+1:]
|
||||
self._count -= 1
|
||||
# 真正将数据删除并覆盖原来的数据 ,这个需要增加
|
||||
self._data = self._data[0:self._count]
|
||||
print ('delet function',self._data)
|
||||
return True
|
||||
|
||||
def insert(self, index: int, value: int) -> bool:
|
||||
if index >= self._count or index <= -self._count: return False
|
||||
|
||||
#if index >= self._count or index <= -self._count: return False
|
||||
if self._capacity == self._count: return False
|
||||
self._data.insert(index, value)
|
||||
# 如果还有空间,那么插入位置大于当前的元素个数,可以插入最后的位置
|
||||
if index >= self._count:
|
||||
self._data.append(value)
|
||||
# 同上,如果位置小于0 可以插入第0个位置.
|
||||
if index < 0:
|
||||
print (index)
|
||||
self._data.insert(0, value)
|
||||
|
||||
self._count += 1
|
||||
return True
|
||||
|
||||
def insert_to_tail(self, value: int) -> bool:
|
||||
|
||||
if self._count == self._capacity: return False
|
||||
if self._count == len(self._data):
|
||||
self._data.append(value)
|
||||
@ -47,11 +65,13 @@ class MyArray:
|
||||
return True
|
||||
|
||||
def __repr__(self) -> str:
|
||||
|
||||
return " ".join(str(num) for num in self._data[:self._count])
|
||||
|
||||
def print_all(self):
|
||||
|
||||
for num in self._data[:self._count]:
|
||||
print(f"{num}", end=" ")
|
||||
print("{num}", end=" ")
|
||||
print("\n", flush=True)
|
||||
|
||||
if __name__ == "__main__":
|
||||
@ -59,7 +79,17 @@ if __name__ == "__main__":
|
||||
for i in range(6):
|
||||
a.insert_to_tail(i)
|
||||
|
||||
<<<<<<< HEAD
|
||||
a.delete(2)
|
||||
print(a)
|
||||
a.insert_to_tail(7)
|
||||
print(a)
|
||||
=======
|
||||
print('origin',a)
|
||||
a.delete(4)
|
||||
print ('delete ',a)
|
||||
|
||||
a.insert(100,10000)
|
||||
print (a)
|
||||
|
||||
>>>>>>> upstream/master
|
||||
|
54
python/06_linkedlist/palindrome.py
Normal file
54
python/06_linkedlist/palindrome.py
Normal file
@ -0,0 +1,54 @@
|
||||
"""
|
||||
check a single-linked list whether a palindrome
|
||||
"""
|
||||
|
||||
import sys
|
||||
# 引用当前文件夹下的single_linked_list
|
||||
sys.path.append('singly_linked_list')
|
||||
from singly_linked_list import SinglyLinkedList
|
||||
|
||||
def reverse(head):
|
||||
reverse_head = None
|
||||
while head:
|
||||
next = head._next
|
||||
head._next = reverse_head
|
||||
reverse_head = head
|
||||
head = next
|
||||
|
||||
return reverse_head
|
||||
|
||||
def is_palindrome(l):
|
||||
l.print_all()
|
||||
slow = l._head
|
||||
fast = l._head
|
||||
position = 0
|
||||
while fast and fast._next:
|
||||
slow = slow._next
|
||||
fast = fast._next._next
|
||||
position += 1
|
||||
|
||||
reverse_node = reverse(slow)
|
||||
head_node = l._head
|
||||
is_palin = True
|
||||
while (head_node and reverse_node):
|
||||
if (head_node.data == reverse_node.data):
|
||||
head_node = head_node._next
|
||||
reverse_node = reverse_node._next
|
||||
else:
|
||||
is_palin = False
|
||||
break
|
||||
|
||||
return is_palin
|
||||
|
||||
if __name__ == '__main__':
|
||||
# the result should be False, True, True, True, True
|
||||
test_str_arr = ['ab', 'aa', 'aba', 'abba', 'abcba']
|
||||
for str in test_str_arr:
|
||||
l = SinglyLinkedList()
|
||||
for i in str:
|
||||
l.insert_value_to_head(i)
|
||||
|
||||
print(is_palindrome(l))
|
||||
|
||||
|
||||
|
@ -21,7 +21,11 @@ class ArrayQueue:
|
||||
return False
|
||||
else:
|
||||
for i in range(0, self._tail - self._head):
|
||||
<<<<<<< HEAD
|
||||
self._data[i] = self._items[i + self._head]
|
||||
=======
|
||||
self._items[i] = self._items[i + self._head]
|
||||
>>>>>>> upstream/master
|
||||
self._tail = self._tail - self._head
|
||||
self._head = 0
|
||||
|
||||
|
@ -11,8 +11,13 @@ from typing import List
|
||||
def bubble_sort(a: List[int]):
|
||||
if len(a) <= 1: return
|
||||
|
||||
<<<<<<< HEAD
|
||||
made_swap = False
|
||||
for i in range(len(a)):
|
||||
=======
|
||||
for i in range(len(a)):
|
||||
made_swap = False
|
||||
>>>>>>> upstream/master
|
||||
for j in range(len(a) - i - 1):
|
||||
if a[j] > a[j+1]:
|
||||
a[j], a[j+1] = a[j+1], a[j]
|
||||
|
48
python/12_sorts/merge_sort.py
Normal file
48
python/12_sorts/merge_sort.py
Normal file
@ -0,0 +1,48 @@
|
||||
"""
|
||||
Author: Wenru
|
||||
"""
|
||||
|
||||
from typing import List
|
||||
|
||||
def merge_sort(a: List[int]):
|
||||
_merge_sort_between(a, 0, len(a)-1)
|
||||
|
||||
def _merge_sort_between(a: List[int], low: int, high: int):
|
||||
# The indices are inclusive for both low and high.
|
||||
if low >= high: return
|
||||
mid = low + (high - low)//2
|
||||
_merge_sort_between(a, low, mid)
|
||||
_merge_sort_between(a, mid+1, high)
|
||||
|
||||
_merge(a, low, mid, high)
|
||||
|
||||
def _merge(a: List[int], low: int, mid: int, high: int):
|
||||
# a[low:mid], a[mid+1, high] are sorted.
|
||||
i, j = low, mid+1
|
||||
tmp = []
|
||||
while i <= mid and j <= high:
|
||||
if a[i] <= a[j]:
|
||||
tmp.append(a[i])
|
||||
i += 1
|
||||
else:
|
||||
tmp.append(a[j])
|
||||
j += 1
|
||||
start = i if i <= mid else j
|
||||
end = mid if i <= mid else high
|
||||
tmp.extend(a[start:end+1])
|
||||
a[low:high+1] = tmp
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
a1 = [3, 5, 6, 7, 8]
|
||||
a2 = [2, 2, 2, 2]
|
||||
a3 = [4, 3, 2, 1]
|
||||
a4 = [5, -1, 9, 3, 7, 8, 3, -2, 9]
|
||||
merge_sort(a1)
|
||||
print(a1)
|
||||
merge_sort(a2)
|
||||
print(a2)
|
||||
merge_sort(a3)
|
||||
print(a3)
|
||||
merge_sort(a4)
|
||||
print(a4)
|
43
python/12_sorts/quick_sort.py
Normal file
43
python/12_sorts/quick_sort.py
Normal file
@ -0,0 +1,43 @@
|
||||
"""
|
||||
Author: Wenru
|
||||
"""
|
||||
|
||||
from typing import List
|
||||
import random
|
||||
|
||||
def quick_sort(a: List[int]):
|
||||
_quick_sort_between(a, 0, len(a)-1)
|
||||
|
||||
def _quick_sort_between(a: List[int], low: int, high: int):
|
||||
if low >= high: return
|
||||
# get a random position as the pivot
|
||||
k = random.randint(low, high)
|
||||
a[low], a[k] = a[k], a[low]
|
||||
|
||||
m = _partition(a, low, high) # a[m] is in final position
|
||||
_quick_sort_between(a, low, m-1)
|
||||
_quick_sort_between(a, m+1, high)
|
||||
|
||||
def _partition(a: List[int], low: int, high: int):
|
||||
pivot, j = a[low], low
|
||||
for i in range(low+1, high+1):
|
||||
if a[i] <= pivot:
|
||||
j += 1
|
||||
a[j], a[i] = a[i], a[j] # swap
|
||||
a[low], a[j] = a[j], a[low]
|
||||
return j
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
a1 = [3, 5, 6, 7, 8]
|
||||
a2 = [2, 2, 2, 2]
|
||||
a3 = [4, 3, 2, 1]
|
||||
a4 = [5, -1, 9, 3, 7, 8, 3, -2, 9]
|
||||
quick_sort(a1)
|
||||
print(a1)
|
||||
quick_sort(a2)
|
||||
print(a2)
|
||||
quick_sort(a3)
|
||||
print(a3)
|
||||
quick_sort(a4)
|
||||
print(a4)
|
40
python/14_sorts/counting_sort.py
Normal file
40
python/14_sorts/counting_sort.py
Normal file
@ -0,0 +1,40 @@
|
||||
"""
|
||||
计数排序
|
||||
|
||||
Author: Wenru
|
||||
"""
|
||||
|
||||
from typing import List
|
||||
import itertools
|
||||
|
||||
def counting_sort(a: List[int]):
|
||||
if len(a) <= 1: return
|
||||
|
||||
# a中有counts[i]个数不大于i
|
||||
counts = [0] * (max(a) + 1)
|
||||
for num in a:
|
||||
counts[num] += 1
|
||||
counts = list(itertools.accumulate(counts))
|
||||
|
||||
# 临时数组,储存排序之后的结果
|
||||
a_sorted = [0] * len(a)
|
||||
for num in reversed(a):
|
||||
index = counts[num] - 1
|
||||
a_sorted[index] = num
|
||||
counts[num] -= 1
|
||||
|
||||
a = a_sorted
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
a1 = [1, 2, 3, 4]
|
||||
counting_sort(a1)
|
||||
print(a1)
|
||||
|
||||
a2 = [1, 1, 1, 1]
|
||||
counting_sort(a2)
|
||||
print(a2)
|
||||
|
||||
a3 = [4, 5, 0, 9, 3, 3, 1, 9, 8, 7]
|
||||
counting_sort(a3)
|
||||
print(a3)
|
22
python/15_bsearch/bsearch.py
Normal file
22
python/15_bsearch/bsearch.py
Normal file
@ -0,0 +1,22 @@
|
||||
"""
|
||||
Author: Wenru
|
||||
"""
|
||||
|
||||
from typing import List
|
||||
|
||||
def bsearch(nums: List[int], target: int) -> int:
|
||||
"""Binary search of a target in a sorted array
|
||||
without duplicates. If such a target does not exist,
|
||||
return -1, othewise, return its index.
|
||||
"""
|
||||
low, high = 0, len(nums) - 1
|
||||
while low <= high:
|
||||
mid = low + (high - low) // 2
|
||||
if nums[mid] == target:
|
||||
return mid
|
||||
elif nums[mid] < target:
|
||||
low = mid + 1
|
||||
else:
|
||||
high = mid - 1
|
||||
|
||||
return -1
|
77
python/16_bsearch/bsearch_variants.py
Normal file
77
python/16_bsearch/bsearch_variants.py
Normal file
@ -0,0 +1,77 @@
|
||||
"""
|
||||
Author: Wenru
|
||||
"""
|
||||
|
||||
from typing import List
|
||||
|
||||
def bsearch_left(nums: List[int], target: int) -> int:
|
||||
"""Binary search of the index of the first element
|
||||
equal to a given target in the ascending sorted array.
|
||||
If not found, return -1.
|
||||
"""
|
||||
low, high = 0, len(nums) - 1
|
||||
while low <= high:
|
||||
mid = low + (high - low) // 2
|
||||
if nums[mid] < target:
|
||||
low = mid + 1
|
||||
else:
|
||||
high = mid - 1
|
||||
return low if nums[low] == target else -1
|
||||
|
||||
def bsearch_right(nums: List[int], target: int) -> int:
|
||||
"""Binary search of the index of the last element
|
||||
equal to a given target in the ascending sorted array.
|
||||
If not found, return -1.
|
||||
"""
|
||||
low, high = 0, len(nums) - 1
|
||||
while low <= high:
|
||||
mid = low + (high - low) // 2
|
||||
if nums[mid] <= target:
|
||||
low = mid + 1
|
||||
else:
|
||||
high = mid - 1
|
||||
return high if nums[high] == target else -1
|
||||
|
||||
|
||||
def bsearch_left_not_less(nums: List[int], target: int) -> int:
|
||||
"""Binary search of the index of the first element
|
||||
not less than a given target in the ascending sorted array.
|
||||
If not found, return -1.
|
||||
"""
|
||||
low, high = 0, len(nums) - 1
|
||||
while low <= high:
|
||||
mid = low + (high - low) // 2
|
||||
if nums[mid] < target:
|
||||
low = mid + 1
|
||||
else:
|
||||
high = mid - 1
|
||||
return low if low < len(nums) else -1
|
||||
|
||||
def bsearch_right_not_greater(nums: List[int], target: int) -> int:
|
||||
"""Binary search of the index of the last element
|
||||
not greater than a given target in the ascending sorted array.
|
||||
If not found, return -1.
|
||||
"""
|
||||
low, high = 0, len(nums) - 1
|
||||
while low <= high:
|
||||
mid = low + (high - low) // 2
|
||||
if nums[mid] <= target:
|
||||
low = mid + 1
|
||||
else:
|
||||
high = mid - 1
|
||||
return high if high > 0 else -1
|
||||
|
||||
if __name__ == "__main__":
|
||||
import bisect
|
||||
|
||||
a = [0, 1, 1, 2, 3, 4, 5, 6, 6, 7, 8, 8, 10, 10, 10]
|
||||
b = [11, 12, 12, 13, 14, 14, 15, 15]
|
||||
print(bisect.bisect_left(a, 10) == bsearch_left(a, 10))
|
||||
print(bisect.bisect_right(a, 10))
|
||||
print(bisect.bisect_right(a, 6)-1 == bsearch_right(a, 6))
|
||||
print(bisect.bisect_right(b, 14)-1 == bsearch_right(b, 14))
|
||||
|
||||
print(bsearch_left_not_less(a, 11))
|
||||
print(bsearch_right_not_greater(b, 12))
|
||||
print(bsearch_right_not_greater(b, 10))
|
||||
print(bsearch_right_not_greater(b, 17))
|
70
python/array.py
Normal file
70
python/array.py
Normal file
@ -0,0 +1,70 @@
|
||||
# 1.数组的插入、删除、按照下标随机访问操作;
|
||||
# 2.数组中的数据类型是Int
|
||||
#
|
||||
# Author:Lee
|
||||
|
||||
class Array():
|
||||
|
||||
def __init__(self):
|
||||
'''数组类初始化方法.'''
|
||||
self.__data = [] # 数据存储List
|
||||
|
||||
def find(self, index):
|
||||
'''数组的查找方法.
|
||||
|
||||
参数:
|
||||
index:将要查找的数据的下标
|
||||
|
||||
返回:
|
||||
如果查找成功,则返回找到的数据
|
||||
如果查找失败,则返回False
|
||||
'''
|
||||
if index > len(self.__data) or index < 0:
|
||||
return False
|
||||
else:
|
||||
return self.__data[index]
|
||||
|
||||
def delete(self, index):
|
||||
'''数组的删除方法.
|
||||
|
||||
参数:
|
||||
index:将要删除的数据的下标
|
||||
|
||||
返回:
|
||||
如果删除成功,则返回True
|
||||
如果删除失败,则返回False
|
||||
'''
|
||||
if index > len(self.__data) or index < 0:
|
||||
return False
|
||||
else:
|
||||
self.__data.pop(index)
|
||||
return True
|
||||
|
||||
def insert(self, index, value):
|
||||
'''数组插入数据操作.
|
||||
|
||||
参数:
|
||||
index:将要插入的下标
|
||||
value:将要插入的数据
|
||||
|
||||
返回:
|
||||
如果插入成功,则返回True
|
||||
如果插入失败,则返回False
|
||||
'''
|
||||
if index > len(self.__data) or index < 0:
|
||||
return False
|
||||
else:
|
||||
self.__data.insert(index, value)
|
||||
return True
|
||||
|
||||
def insertToTail(self, value):
|
||||
'''直接在数组尾部插入数据.
|
||||
|
||||
参数:
|
||||
value:将要插入的数据
|
||||
'''
|
||||
self.__data.append(value)
|
||||
|
||||
def printAll(self):
|
||||
'''打印当前数组所有数据'''
|
||||
print(self.__data)
|
68
scala/11_sorts/Sorts.scala
Normal file
68
scala/11_sorts/Sorts.scala
Normal file
@ -0,0 +1,68 @@
|
||||
import scala.util.control.Breaks._
|
||||
|
||||
/**
|
||||
* 冒泡排序、插入排序、选择排序
|
||||
*
|
||||
* Author: yangchuz
|
||||
*/
|
||||
object Sorts {
|
||||
def main(args: Array[String]): Unit ={
|
||||
// println(bubbleSort(Array(0, 6, 2, 3, 8, 5, 6, 7), 8).mkString(", "))
|
||||
// println(insertSort(Array(0, 6, 2, 3, 8, 5, 6, 7), 8).mkString(", "))
|
||||
println(selectionSort(Array(0, 6, 2, 3, 8, 5, 6, 7), 8).mkString(", "))
|
||||
}
|
||||
|
||||
def bubbleSort(arr: Array[Int], n:Int): Array[Int] = {
|
||||
val n = arr.length
|
||||
breakable {
|
||||
for(i <- (n-1) to (1, -1)){
|
||||
var flag = false
|
||||
for(j <- 0 until i){
|
||||
if(arr(j) > arr(j+1)){
|
||||
val tmp = arr(j)
|
||||
arr(j) = arr(j+1)
|
||||
arr(j+1) = tmp
|
||||
flag = true
|
||||
}
|
||||
}
|
||||
if(!flag){
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
arr
|
||||
}
|
||||
|
||||
def insertSort(arr: Array[Int], n:Int): Array[Int] = {
|
||||
for(i <- 1 until n){
|
||||
val tmp = arr(i)
|
||||
breakable{
|
||||
for(j <- (i-1) to (0, -1)){
|
||||
if(tmp < arr(j)){
|
||||
arr(j+1) = arr(j)
|
||||
}else{
|
||||
arr(j+1) = tmp
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
arr
|
||||
}
|
||||
|
||||
def selectionSort(arr: Array[Int], n:Int): Array[Int] = {
|
||||
for(i <- 0 until n){
|
||||
var min = i
|
||||
for(j <- (i + 1) until n){
|
||||
if(arr(j) < arr(min)){
|
||||
min = j
|
||||
}
|
||||
}
|
||||
|
||||
val tmp = arr(i)
|
||||
arr(i) = arr(min)
|
||||
arr(min) = tmp
|
||||
}
|
||||
arr
|
||||
}
|
||||
}
|
BIN
swift/12_sorts/.DS_Store
vendored
Normal file
BIN
swift/12_sorts/.DS_Store
vendored
Normal file
Binary file not shown.
36
swift/12_sorts/QuickSort.swift
Normal file
36
swift/12_sorts/QuickSort.swift
Normal file
@ -0,0 +1,36 @@
|
||||
//
|
||||
// QuickSort.swift
|
||||
// algo
|
||||
//
|
||||
// Created by Wenru Dong on 2018/10/17.
|
||||
// Copyright © 2018年 Wenru Dong. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public func quickSort<T: RandomAccessCollection & MutableCollection>(_ a: inout T) where T.Element: Comparable {
|
||||
quickSort(&a, from: a.startIndex, to: a.index(before: a.endIndex))
|
||||
}
|
||||
|
||||
fileprivate func quickSort<T: RandomAccessCollection & MutableCollection>(_ a: inout T, from low: T.Index, to high: T.Index) where T.Element: Comparable {
|
||||
if low >= high { return }
|
||||
|
||||
let m = partition(&a, from: low, to: high)
|
||||
quickSort(&a, from: low, to: a.index(before: m))
|
||||
quickSort(&a, from: a.index(after: m), to: high)
|
||||
}
|
||||
|
||||
fileprivate func partition<T: RandomAccessCollection & MutableCollection>(_ a: inout T, from low: T.Index, to high: T.Index) -> T.Index where T.Element: Comparable {
|
||||
let pivot = a[low]
|
||||
var j = low
|
||||
var i = a.index(after: low)
|
||||
while i <= high {
|
||||
if a[i] < pivot {
|
||||
a.formIndex(after: &j)
|
||||
a.swapAt(i, j)
|
||||
}
|
||||
a.formIndex(after: &i)
|
||||
}
|
||||
a.swapAt(low, j)
|
||||
return j
|
||||
}
|
58
swift/12_sorts/SortsTests.swift
Normal file
58
swift/12_sorts/SortsTests.swift
Normal file
@ -0,0 +1,58 @@
|
||||
//
|
||||
// SortsTests.swift
|
||||
// SortsTests
|
||||
//
|
||||
// Created by Wenru Dong on 2018/10/14.
|
||||
// Copyright © 2018年 Wenru Dong. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class SortsTests: XCTestCase {
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testMergeSort() {
|
||||
var a1 = [1, 1, 1, 1]
|
||||
mergeSort(&a1)
|
||||
XCTAssertEqual(a1, [1, 1, 1, 1])
|
||||
|
||||
var a2 = [4, 3, 2, 1]
|
||||
mergeSort(&a2)
|
||||
XCTAssertEqual(a2, [1, 2, 3, 4])
|
||||
|
||||
var a3 = [3, 6, 9, 7, 8, -1, 9, 3, -2, 0]
|
||||
mergeSort(&a3)
|
||||
XCTAssertEqual(a3, [-2, -1, 0, 3, 3, 6, 7, 8, 9, 9])
|
||||
}
|
||||
|
||||
func testQuickSort() {
|
||||
var a1 = [1, 1, 1, 1]
|
||||
quickSort(&a1)
|
||||
XCTAssertEqual(a1, [1, 1, 1, 1])
|
||||
|
||||
var a2 = [4, 3, 2, 1]
|
||||
quickSort(&a2)
|
||||
XCTAssertEqual(a2, [1, 2, 3, 4])
|
||||
|
||||
var a3 = [3, 6, 9, 7, 8, -1, 9, 3, -2, 0]
|
||||
quickSort(&a3)
|
||||
XCTAssertEqual(a3, [-2, -1, 0, 3, 3, 6, 7, 8, 9, 9])
|
||||
}
|
||||
|
||||
func testPerformanceExample() {
|
||||
// This is an example of a performance test case.
|
||||
self.measure {
|
||||
// Put the code you want to measure the time of here.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
52
swift/12_sorts/mergeSort.swift
Normal file
52
swift/12_sorts/mergeSort.swift
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// sorts.swift
|
||||
// algo
|
||||
//
|
||||
// Created by Wenru Dong on 2018/10/14.
|
||||
// Copyright © 2018年 Wenru Dong. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public func mergeSort<T>(_ a: inout T) where T: RandomAccessCollection, T: MutableCollection, T.Element: Comparable {
|
||||
mergeSort(&a, from: a.startIndex, to: a.index(before: a.endIndex))
|
||||
}
|
||||
|
||||
fileprivate func mergeSort<T>(_ a: inout T, from low: T.Index, to high: T.Index) where T: RandomAccessCollection, T: MutableCollection, T.Element: Comparable {
|
||||
if low >= high { return }
|
||||
let dist = a.distance(from: low, to: high)
|
||||
let mid = a.index(low, offsetBy: dist/2)
|
||||
mergeSort(&a, from: low, to: mid)
|
||||
mergeSort(&a, from: a.index(mid, offsetBy: 1), to: high)
|
||||
merge(&a, from: low, through: mid, to: high)
|
||||
}
|
||||
|
||||
fileprivate func merge<T>(_ a: inout T, from low: T.Index, through mid: T.Index, to high: T.Index) where T: RandomAccessCollection, T: MutableCollection, T.Element: Comparable {
|
||||
var i = low
|
||||
var j = a.index(mid, offsetBy: 1)
|
||||
var tmp = Array<T.Element>()
|
||||
tmp.reserveCapacity(a.distance(from: low, to: high) + 1)
|
||||
while i <= mid && j <= high {
|
||||
if a[i] <= a[j] {
|
||||
tmp.append(a[i])
|
||||
a.formIndex(after: &i)
|
||||
} else {
|
||||
tmp.append(a[j])
|
||||
a.formIndex(after: &j)
|
||||
}
|
||||
}
|
||||
|
||||
var start = i
|
||||
var end = mid
|
||||
if j <= high {
|
||||
start = j
|
||||
end = high
|
||||
}
|
||||
tmp.append(contentsOf: a[start...end])
|
||||
|
||||
var current = low
|
||||
for element in tmp {
|
||||
a[current] = element
|
||||
a.formIndex(after: ¤t)
|
||||
}
|
||||
}
|
33
swift/14_sorts/CountingSort.swift
Normal file
33
swift/14_sorts/CountingSort.swift
Normal file
@ -0,0 +1,33 @@
|
||||
//
|
||||
// CountingSort.swift
|
||||
// algo
|
||||
//
|
||||
// Created by Wenru Dong on 2018/10/18.
|
||||
// Copyright © 2018年 Wenru Dong. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// 假设数组中储存的都是非负整数
|
||||
public func countingSort(_ a: inout [Int]) {
|
||||
if a.count <= 1 { return }
|
||||
|
||||
var counts = Array(repeating: 0, count: a.max()! + 1)
|
||||
for num in a {
|
||||
counts[num] += 1
|
||||
}
|
||||
for i in 1..<counts.count {
|
||||
counts[i] = counts[i-1] + counts[i]
|
||||
}
|
||||
|
||||
var aSorted = Array(repeating: 0, count: a.count)
|
||||
for num in a.reversed() {
|
||||
let index = counts[num] - 1
|
||||
aSorted[index] = num
|
||||
counts[num] -= 1
|
||||
}
|
||||
|
||||
for (i, num) in aSorted.enumerated() {
|
||||
a[i] = num
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user