commit
f0c4d7a167
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
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;
|
||||
merge_sort(first, cut, comp);
|
||||
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;
|
||||
}
|
||||
|
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;
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
/**
|
||||
*
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
@ -57,7 +57,7 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取对应元素的下标, 未找到,返回 -1
|
||||
// 获取对应元素的下标, 未找到,返回 -1
|
||||
public int find(T e) {
|
||||
for ( int i = 0; i < size; i++) {
|
||||
if (data[i].equals(e)) {
|
||||
@ -66,12 +66,12 @@
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 在 index 位置,插入元素e, 时间复杂度 O(m+n)
|
||||
public void add(int index, T e) {
|
||||
checkIndex(index);
|
||||
// 如果当前元素个数等于数组容量,则将数组扩容为原来的2倍
|
||||
// 如果当前元素个数等于数组容量,则将数组扩容为原来的2倍
|
||||
if (size == data.length) {
|
||||
resize(2 * data.length);
|
||||
}
|
||||
@ -96,7 +96,7 @@
|
||||
// 删除 index 位置的元素,并返回
|
||||
public T remove(int index) {
|
||||
checkIndex(index);
|
||||
|
||||
|
||||
T ret = data[index];
|
||||
for (int i = index + 1; i < size; i++) {
|
||||
data[i - 1] = data[i];
|
||||
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
@ -58,6 +58,9 @@ public class Sorts {
|
||||
}
|
||||
}
|
||||
|
||||
if (minIndex == i)
|
||||
continue;
|
||||
|
||||
// 交换
|
||||
int tmp = a[i];
|
||||
a[i] = a[minIndex];
|
||||
|
53
java/14_sorts/CountingSort.java
Normal file
53
java/14_sorts/CountingSort.java
Normal file
@ -0,0 +1,53 @@
|
||||
package sorts;
|
||||
|
||||
/**
|
||||
* 计数排序
|
||||
*
|
||||
* Author: ZHENG
|
||||
*/
|
||||
public class CountingSort {
|
||||
|
||||
// 计数排序,a是数组,n是数组大小。假设数组中存储的都是非负整数。
|
||||
public static void countingSort(int[] a, int n) {
|
||||
if (n <= 1) return;
|
||||
|
||||
// 查找数组中数据的范围
|
||||
int max = a[0];
|
||||
for (int i = 1; i < n; ++i) {
|
||||
if (max < a[i]) {
|
||||
max = a[i];
|
||||
}
|
||||
}
|
||||
|
||||
// 申请一个计数数组c,下标大小[0,max]
|
||||
int[] c = new int[max + 1];
|
||||
for (int i = 0; i < max + 1; ++i) {
|
||||
c[i] = 0;
|
||||
}
|
||||
|
||||
// 计算每个元素的个数,放入c中
|
||||
for (int i = 0; i < n; ++i) {
|
||||
c[a[i]]++;
|
||||
}
|
||||
|
||||
// 依次累加
|
||||
for (int i = 1; i < max + 1; ++i) {
|
||||
c[i] = c[i-1] + c[i];
|
||||
}
|
||||
|
||||
// 临时数组r,存储排序之后的结果
|
||||
int[] r = new int[n];
|
||||
// 计算排序的关键步骤了,有点难理解
|
||||
for (int i = n - 1; i >= 0; --i) {
|
||||
int index = c[a[i]]-1;
|
||||
r[index] = a[i];
|
||||
c[a[i]]--;
|
||||
}
|
||||
|
||||
// 将结果拷贝会a数组
|
||||
for (int i = 0; i < n; ++i) {
|
||||
a[i] = r[i];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
@ -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,10 @@ if __name__ == "__main__":
|
||||
for i in range(6):
|
||||
a.insert_to_tail(i)
|
||||
|
||||
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)
|
||||
|
||||
|
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,7 @@ class ArrayQueue:
|
||||
return False
|
||||
else:
|
||||
for i in range(0, self._tail - self._head):
|
||||
self._data[i] = self._items[i + self._head]
|
||||
self._items[i] = self._items[i + self._head]
|
||||
self._tail = self._tail - self._head
|
||||
self._head = 0
|
||||
|
||||
|
@ -11,8 +11,8 @@ from typing import List
|
||||
def bubble_sort(a: List[int]):
|
||||
if len(a) <= 1: return
|
||||
|
||||
made_swap = False
|
||||
for i in range(len(a)):
|
||||
made_swap = False
|
||||
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)
|
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