Merge pull request #1 from wangzheng0822/master

动态数组
This commit is contained in:
Shi Yue 2018-10-12 18:55:34 +08:00 committed by GitHub
commit c6275984b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 2848 additions and 26 deletions

1
.gitignore vendored
View File

@ -24,3 +24,4 @@ hs_err_pid*
# editor files
.vscode
.*.swp

View File

@ -1,2 +1,5 @@
# 数据结构和算法之美
# 请点击查看:[https://time.geekbang.org/column/intro/126](https://time.geekbang.org/column/intro/126)
# [https://time.geekbang.org/column/intro/126](https://time.geekbang.org/column/intro/126)
# Java rate limiting library/framework
# https://github.com/wangzheng0822/ratelimiter4j

278
c-cpp/05_array/Array_gp.c Normal file
View File

@ -0,0 +1,278 @@
#include "Array.h"
#include <string.h>
#include <stdbool.h>
Array* arrayCreate()
{
struct Array *array = NULL;
array = malloc(sizeof(*array));
if (NULL == array)
{
return NULL;
}
array->p = NULL;
array->size = 0;
array->typeSize = 0;
array->len = 0;
array->dup = NULL;
array->free = NULL;
array->match = NULL;
return array;
}
void arrayInit(Array *array, int size, int typeSize)
{
if (NULL == array
|| typeSize <= 0
|| size < 0)
{
return;
}
void *p = calloc(1, size* typeSize);
if (NULL == p)
{
return;
}
array->p = p;
array->len = 0;
array->size = size;
array->typeSize = typeSize;
}
int arrayInsert(Array *array, size_t pos, void *const value)
{
if (NULL == array)
{
return -1;
}
if (array->len >= array->size)
{
return -2;
}
if (pos > array->size || pos <= 0)
{
return -3;
}
char *pBegin = array->p;
for (size_t i = array->len; i > pos - 1; --i)
{
void *pNew = pBegin + i * array->typeSize;
void *pOld = pBegin + (i - 1) *array->typeSize;
if (NULL != array->dup)
{
array->dup(pNew, pOld);
}
else
{
memcpy(pNew, pOld, array->typeSize);
}
}
void *pCopy = (void*)(pBegin + ((pos - 1) * array->typeSize));
if (NULL != array->dup)
{
array->dup(pCopy, value);
}
else
{
memcpy(pCopy, value, array->typeSize);
}
++array->len;
return 0;
}
size_t arraySearchValue(Array *array, void* const value)
{
if (NULL == array)
{
return -1;
}
char *pBegin = array->p;
size_t i = 0;
for (; i < array->len; ++i)
{
int nCmp = 0;
if (NULL != array->match)
{
nCmp = array->match(pBegin + i * array->typeSize, value);
}
else
{
nCmp = memcmp(pBegin + i * array->typeSize, value, array->typeSize);
}
if (nCmp == 0)
{
break;
}
}
return i;
}
void* arrayIndex(Array *array, size_t index)
{
if (NULL == array)
{
return NULL;
}
if (index > array->len
|| index <= 0)
{
return NULL;
}
char *pBegin = array->p;
return pBegin + array->typeSize * (index - 1);
}
int arrayModify(Array *array, size_t pos, void *const value)
{
if (NULL == array)
{
return -1;
}
if (pos > array->len
|| pos <= 0)
{
return -2;
}
char *pBegin = array->p;
void *pOld = pBegin + (pos - 1) * array->typeSize;
if (NULL != array->dup)
{
array->dup(pOld, value);
}
else
{
memcpy(pOld, value, array->typeSize);
}
return 0;
}
size_t arrayLen(Array *array)
{
if (NULL == array)
{
return 0;
}
return array->len;
}
size_t arraySize(Array *array)
{
if (NULL == array)
{
return 0;
}
return array->size;
}
void arrayEmpty(Array *array)
{
if (NULL == array)
{
return;
}
free(array->p);
array->p = NULL;
free(array);
array = NULL;
}
void arrayDelValue(Array *array, void *value)
{
if (NULL == array)
{
return;
}
char* pBegin = array->p;
bool bCopy = false;
for (size_t i = 0; i < array->len; ++i)
{
if (!bCopy)
{
int nCmp = 0;
if (NULL != array->match)
{
nCmp = array->match(pBegin + i * array->typeSize, value);
}
else
{
nCmp = memcmp(pBegin + i * array->typeSize, value, array->typeSize);
}
if (0 == nCmp)
{
bCopy = true;
continue;
}
}
else
{
void *pOld = pBegin + (i + 1) * array->typeSize;
void *pNew = pBegin + i * array->typeSize;
if (NULL != array->dup)
{
array->dup(pNew, pOld);
}
else
{
memcpy(pNew, pOld, array->typeSize);
}
}
}
if (bCopy)
{
--array->len;
}
}
void arrayDelIndex(Array *array, size_t pos)
{
if (NULL == array)
{
return;
}
if (pos > array->len || pos <= 0)
{
return;
}
char* pBegin = array->p;
for (size_t i = pos - 1; i < array->len - 1; ++i)
{
void *pOld = pBegin + (i + 1) * array->typeSize;
void *pNew = pBegin + i * array->typeSize;
if (NULL != array->dup)
{
array->dup(pNew, pOld);
}
else
{
memcpy(pNew, pOld, array->typeSize);
}
}
--array->len;
}

48
c-cpp/05_array/Array_gp.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef __ARRAY_H__
#define __ARRAY_H__
#include <stdio.h>
#include <stdlib.h>
typedef struct Array
{
// p指针的空间大小
size_t size;
// p指针已经使用的空间大小
size_t len;
// 数据类型的大小
size_t typeSize;
// 值复制函数
void(*dup)(void *ptr, void *key);
// 值释放函数
void(*free)(void *ptr);
// 值比较函数
int(*match)(void *ptr, void *key);
// 存放数据的指针
void *p;
}Array;
#define arraySetDupMethod(a, m) ((a)->dup = (m))
#define arraySetFreeMethod(a, m) ((a)->free = (m))
#define arraySetMatchMethod(a, m) ((a)->match = (m))
#define arrayGetDupMethod(a) ((a)->dup)
#define arrayGetFree(a) ((a)->free)
#define arrayGetMatchMethod(a) ((a)->match)
Array* arrayCreate();
void arrayInit(Array *array, int size, int typeSize);
int arrayInsert(Array *array, size_t pos, void *const value);
size_t arraySearchValue(Array *array, void* const value);
void* arrayIndex(Array *array, size_t index);
int arrayModify(Array *array, size_t pos, void *const value);
size_t arrayLen(Array *array);
size_t arraySize(Array *array);
void arrayEmpty(Array *array);
void arrayDelValue(Array *array, void *value);
void arrayDelIndex(Array *array, size_t pos);
#endif // !__ARRAY_H__

View File

@ -0,0 +1,220 @@
/*************************************************************************
> File Name: Dlist.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-07
> Desc:
************************************************************************/
#include<stdio.h>
#include <stdbool.h>
#include "./Dlist.h"
void dlist_init(stDlistHead *dlist)
{
dlist->size = 0;
dlist->head = NULL;
dlist->tail = NULL;
return;
}
void dlist_destory(stDlistHead *dlist)
{
stDlistNode *pNode = NULL;
while(dlist->size > 0)
{
pNode = dlist->head;
dlist->head = dlist->head->next;
free(pNode);
dlist->size--;
}
memset(dlist,0,sizeof(stDlistHead));
return;
}
int dlist_insert_head(stDlistHead *dlist,stDlistNode *pNode,int data)
{
if(pNode == NULL)
{
pNode = (stDlistNode *)malloc(sizeof(stDlistNode));
if (pNode == NULL)
{
return -1;
}
}
pNode->data = data;
pNode->prev = NULL;
pNode->next = NULL;
if (dlist->size == 0)
{
dlist->head = pNode;
dlist->tail = pNode;
}
else
{
pNode->next = dlist->head;
dlist->head->prev = pNode;
dlist->head = pNode;
}
dlist->size++;
return 0;
}
stDlistNode * dlist_remove_tail(stDlistHead *dlist)
{
stDlistNode *pNode = NULL;
if(dlist->size == 0)
{
return NULL;
}
pNode = dlist->tail;
if(dlist->size > 1)
{
dlist->tail = dlist->tail->prev;
dlist->tail->next = NULL;
}
else
{
dlist->head = NULL;
dlist->tail = NULL;
}
dlist->size--;
return pNode;
}
void dlist_remove_node(stDlistHead * dlist,stDlistNode *pNode)
{
if ((dlist == NULL)||(pNode == NULL))
{
return;
}
if (dlist->head == pNode)
{
dlist->head = dlist->head->next;
}
else if (dlist->tail == pNode)
{
dlist->tail = pNode->prev;
dlist->tail->next = NULL;
}
else
{
pNode->prev->next = pNode->next;
pNode->next->prev = pNode->prev;
}
dlist->size--;
pNode->prev = NULL;
pNode->next = NULL;
if (dlist->size == 0)
{
memset(dlist,0,sizeof(stDlistHead));
}
return;
}
stDlistNode * dlist_search(stDlistHead * dlist,int data)
{
stDlistNode *pNode = dlist->head;
while(pNode != NULL)
{
if (pNode->data == data)
{
return pNode;
}
pNode = pNode->next;
}
return NULL;
}
void dlist_dump(stDlistHead *dlist)
{
int no = 0;
stDlistNode *pNode = dlist->head;
while(pNode != NULL)
{
printf("\r\n [%d] = %d",no++,pNode->data);
pNode = pNode->next;
}
return;
}
void Lru_dlist(stDlistHead *dlist,int data)
{
stDlistNode *pNode = NULL;
pNode = dlist_search(dlist,data);
if (pNode != NULL)
{
dlist_remove_node(dlist,pNode);
}
else if(dlist->size >= 4)
{
pNode = dlist_remove_tail(dlist);
}
dlist_insert_head(dlist ,pNode,data);
return;
}
int main()
{
stDlistHead dlist = {0};
stDlistNode * pNode = NULL;
dlist_init(&dlist);
printf("\r\n inset 1,2,3");
dlist_insert_head(&dlist,NULL,1);
dlist_insert_head(&dlist,NULL,2);
dlist_insert_head(&dlist,NULL,3);
dlist_dump(&dlist);
pNode = dlist_remove_tail(&dlist);
if(pNode != NULL)
{
printf("\r\n remove %d",pNode->data);
}
dlist_insert_head(&dlist,pNode,4);
dlist_dump(&dlist);
Lru_dlist(&dlist,5);
dlist_dump(&dlist);
Lru_dlist(&dlist,6);
dlist_dump(&dlist);
Lru_dlist(&dlist,7);
dlist_dump(&dlist);
Lru_dlist(&dlist,5);
dlist_dump(&dlist);
while(dlist.size > 0)
{
pNode = dlist_remove_tail(&dlist);
if(pNode != NULL)
{
printf("\r\n remove %d",pNode->data);
free (pNode);
}
}
return 0;
}

View File

@ -0,0 +1,23 @@
/*************************************************************************
> File Name: Dlist.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-07
> Desc:
************************************************************************/
#include<stdio.h>
typedef struct DlistNode
{
struct DlistNode *prev;
struct DlistNode *next;
int data;
}stDlistNode;
typedef struct Dlisthead
{
int size;
stDlistNode *head;
stDlistNode *tail;
}stDlistHead;

0
c-cpp/09_queue/.gitkeep Normal file
View File

View File

@ -0,0 +1,97 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/10.
*/
#ifndef QUEUE_ARRAY_QUEUE_HPP_
#define QUEUE_ARRAY_QUEUE_HPP_
template <typename T>
class ArrayQueue {
private:
T* items_ = nullptr;
size_t capacity_ = 0;
size_t head_ = 0;
size_t tail_ = 0;
public:
ArrayQueue() = delete;
ArrayQueue(const size_t capacity) : capacity_(capacity) {
items_ = new T[capacity_];
}
~ArrayQueue() {
if (nullptr != items_) {
delete[] items_;
items_ = nullptr;
}
}
ArrayQueue(const ArrayQueue& other) : capacity_(other.capacity_) {
items_ = new T[capacity_];
for (size_t i = other.head_; i != other.tail_; ++i) {
enqueue(other.items_[i]);
}
}
ArrayQueue& operator=(const ArrayQueue& rhs) {
delete[] items_;
head_ = 0;
tail_ = 0;
capacity_ = rhs.capacity_;
items_ = new T[capacity_];
for (size_t i = rhs.head_; i != rhs.tail_; ++i) {
enqueue(rhs.items_[i]);
}
return *this;
}
ArrayQueue(ArrayQueue&& other) : items_(other.items_),
capacity_(other.capacity_),
head_(other.head_),
tail_(other.tail_) {
other.items_ = nullptr;
other.capacity_ = 0;
other.head_ = 0;
other.tail_ = 0;
}
ArrayQueue& operator=(ArrayQueue&& rhs) {
delete[] items_;
items_ = rhs.items_;
capacity_ = rhs.capacity_;
head_ = rhs.head_;
tail_ = rhs.tail_;
rhs.items_ = nullptr;
rhs.capacity_ = 0;
rhs.head_ = 0;
rhs.tail_ = 0;
return *this;
}
public:
void enqueue(T item) {
if (capacity_ == tail_) {
throw "Push data into a full queue!";
}
items_[tail_++] = item;
}
T head() const {
if (head_ != tail_) {
return items_[head_];
} else {
throw "Fetch data from an empty queue!";
}
}
void dequeue() {
if (head_ != tail_) {
++head_;
} else {
throw "Pop data from an empty queue!";
}
}
public:
template <typename UnaryFunc>
void traverse(UnaryFunc do_traverse) {
for (size_t i = head_; i != tail_; ++i) {
do_traverse(items_[i]);
}
}
};
#endif // QUEUE_ARRAY_QUEUE_HPP_

View File

@ -0,0 +1,56 @@
#include <iostream>
#include "array_queue.hpp"
int main() {
auto do_traverse = [&](auto item){ std::cout << item << ' '; };
ArrayQueue<int> array_queue_1(3);
array_queue_1.enqueue(1);
array_queue_1.enqueue(2);
array_queue_1.enqueue(3);
// array_queue_1.enqueue(4); // throw
array_queue_1.traverse(do_traverse);
std::cout << std::endl;
ArrayQueue<int> array_queue_2(array_queue_1); // copy constructor
array_queue_2.traverse(do_traverse);
std::cout << std::endl;
ArrayQueue<int> array_queue_3(std::move(array_queue_2)); // move constructor
array_queue_3.traverse(do_traverse);
std::cout << std::endl;
array_queue_2.traverse(do_traverse);
std::cout << std::endl;
std::cout << array_queue_3.head() << std::endl;
array_queue_3.dequeue();
std::cout << array_queue_3.head() << std::endl;
array_queue_3.dequeue();
std::cout << array_queue_3.head() << std::endl;
array_queue_3.dequeue();
// std::cout << array_queue_3.head() << std::endl; // throw
// array_queue_3.dequeue(); // throw
ArrayQueue<int> array_queue_4(1);
array_queue_4 = array_queue_1; // copy assignment
array_queue_4.traverse(do_traverse);
std::cout << std::endl;
ArrayQueue<int> array_queue_5(100);
array_queue_5 = std::move(array_queue_4); // move assignment
array_queue_5.traverse(do_traverse);
std::cout << std::endl;
array_queue_4.traverse(do_traverse);
std::cout << std::endl;
std::cout << array_queue_5.head() << std::endl;
array_queue_5.dequeue();
std::cout << array_queue_5.head() << std::endl;
array_queue_5.dequeue();
std::cout << array_queue_5.head() << std::endl;
array_queue_5.dequeue();
// std::cout << array_queue_5.head() << std::endl; // throw
// array_queue_5.dequeue(); // throw
return 0;
}

View File

@ -0,0 +1,82 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/11.
*/
#ifndef QUEUE_BLOCK_QUEUE_HPP_
#define QUEUE_BLOCK_QUEUE_HPP_
#include <queue>
#include <mutex>
#include <condition_variable>
template <typename T>
class BlockQueue {
public:
using value_type = T;
using container_type = std::queue<value_type>;
using size_type = typename container_type::size_type;
private:
size_type capacity_ = 0;
container_type container_;
mutable std::mutex mutex_;
mutable std::condition_variable not_empty_;
mutable std::condition_variable not_full_;
public:
BlockQueue() = delete;
BlockQueue(const size_type capacity) : capacity_(capacity) {}
BlockQueue(const BlockQueue&) = default;
BlockQueue(BlockQueue&&) = default;
BlockQueue& operator=(const BlockQueue&) = default;
BlockQueue& operator=(BlockQueue&&) = default;
private:
bool empty() const { return container_.empty(); }
bool full() const { return not(container_.size() < capacity_); }
public:
void put(const value_type& item) {
std::unqiue_lock<std::mutex> lock(mutex_);
while (full()) {
not_full_.wait(lock);
}
container_.push(item);
not_empty_.notify_one();
}
void take(value_type& out) {
std::unique_lock<std::mutex> lock(mutex_);
while (empty()) {
not_empty_.wait(lock);
}
out = container_.front();
container_.pop();
not_full_.notify_one();
}
template <typename Duration>
bool put_for(const value_type& item, const Duration& d) {
std::unqiue_lock<std::mutex> lock(mutex_);
if (not_full_.wait_for(lock, d, [&](){ return not full(); })) {
container_.push(item);
not_empty_.notify_one();
return true;
} else {
return false;
}
}
template <typename Duration>
bool take_for(const Duration& d, value_type& out) {
std::unique_lock<std::mutex> lock(mutex_);
if (not_empty_.wait_for(lock, d, [&](){ return not empty(); })) {
out = container_.front();
container_.pop();
not_full_.notify_one();
return true;
} else {
return false;
}
}
};
#endif // QUEUE_BLOCK_QUEUE_HPP_

View File

@ -0,0 +1,99 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/10.
*/
#ifndef QUEUE_CIRCULAR_QUEUE_HPP_
#define QUEUE_CIRCULAR_QUEUE_HPP_
template <typename T>
class CircularQueue {
private:
T* items_ = nullptr;
size_t capacity_ = 0;
size_t head_ = 0;
size_t tail_ = 0;
public:
CircularQueue() = delete;
CircularQueue(const size_t capacity) : capacity_(capacity) {
items_ = new T[capacity_];
}
~CircularQueue() {
if (nullptr != items_) {
delete[] items_;
items_ = nullptr;
}
}
CircularQueue(const CircularQueue& other) : capacity_(other.capacity_) {
items_ = new T[capacity_];
for (size_t i = other.head_; i != other.tail_; ++i) {
enqueue(other.items_[i]);
}
}
CircularQueue& operator=(const CircularQueue& rhs) {
delete[] items_;
head_ = 0;
tail_ = 0;
capacity_ = rhs.capacity_;
items_ = new T[capacity_];
for (size_t i = rhs.head_; i != rhs.tail_; ++i) {
enqueue(rhs.items_[i]);
}
return *this;
}
CircularQueue(CircularQueue&& other) : items_(other.items_),
capacity_(other.capacity_),
head_(other.head_),
tail_(other.tail_) {
other.items_ = nullptr;
other.capacity_ = 0;
other.head_ = 0;
other.tail_ = 0;
}
CircularQueue& operator=(CircularQueue&& rhs) {
delete[] items_;
items_ = rhs.items_;
capacity_ = rhs.capacity_;
head_ = rhs.head_;
tail_ = rhs.tail_;
rhs.items_ = nullptr;
rhs.capacity_ = 0;
rhs.head_ = 0;
rhs.tail_ = 0;
return *this;
}
public:
void enqueue(T item) {
if ((tail_ + 1) % capacity_ == head_) {
throw "Push data into a full queue!";
}
items_[tail_] = item;
tail_ = (tail_ + 1) % capacity_;
}
T head() const {
if (head_ != tail_) {
return items_[head_];
} else {
throw "Fetch data from an empty queue!";
}
}
void dequeue() {
if (head_ != tail_) {
head_ = (head_ + 1) % capacity_;
} else {
throw "Pop data from an empty queue!";
}
}
public:
template <typename UnaryFunc>
void traverse(UnaryFunc do_traverse) {
if (0 == capacity_) return;
for (size_t i = head_; i % capacity_ != tail_; ++i) {
do_traverse(items_[i % capacity_]);
}
}
};
#endif // QUEUE_CIRCULAR_QUEUE_HPP_

View File

@ -0,0 +1,62 @@
#include <iostream>
#include "circular_queue.hpp"
int main() {
auto do_traverse = [&](auto item){ std::cout << item << ' '; };
CircularQueue<int> circular_queue_1(4);
circular_queue_1.enqueue(1);
circular_queue_1.enqueue(2);
circular_queue_1.enqueue(3);
// circular_queue_1.enqueue(4); // throw
circular_queue_1.traverse(do_traverse);
std::cout << std::endl;
CircularQueue<int> circular_queue_2(circular_queue_1); // copy constructor
circular_queue_2.traverse(do_traverse);
std::cout << std::endl;
CircularQueue<int> circular_queue_3(std::move(circular_queue_2)); // move constructor
circular_queue_3.traverse(do_traverse);
std::cout << std::endl;
circular_queue_2.traverse(do_traverse);
std::cout << std::endl;
std::cout << circular_queue_3.head() << std::endl;
circular_queue_3.dequeue();
std::cout << circular_queue_3.head() << std::endl;
circular_queue_3.dequeue();
std::cout << circular_queue_3.head() << std::endl;
circular_queue_3.dequeue();
// std::cout << circular_queue_3.head() << std::endl; // throw
// circular_queue_3.dequeue(); // throw
CircularQueue<int> circular_queue_4(1);
circular_queue_4 = circular_queue_1; // copy assignment
circular_queue_4.traverse(do_traverse);
std::cout << std::endl;
CircularQueue<int> circular_queue_5(100);
circular_queue_5 = std::move(circular_queue_4); // move assignment
circular_queue_5.traverse(do_traverse);
std::cout << std::endl;
circular_queue_4.traverse(do_traverse);
std::cout << std::endl;
std::cout << circular_queue_5.head() << std::endl;
circular_queue_5.dequeue();
std::cout << circular_queue_5.head() << std::endl;
circular_queue_5.dequeue();
std::cout << circular_queue_5.head() << std::endl;
circular_queue_5.dequeue();
// std::cout << circular_queue_5.head() << std::endl; // throw
// circular_queue_5.dequeue(); // throw
for (size_t i = 0; i != 4; ++i) {
circular_queue_1.dequeue();
circular_queue_1.enqueue(i + 4);
circular_queue_1.traverse(do_traverse);
std::cout << std::endl;
}
return 0;
}

View File

@ -0,0 +1,85 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/11.
*/
#ifndef QUEUE_CONCURRENCY_QUEUE_HPP_
#define QUEUE_CONCURRENCY_QUEUE_HPP_
#include <queue>
#include <mutex>
#include <condition_variable>
#include <memory>
template <typename T>
class ConcurrencyQueue {
public:
using value_type = T;
using container_type = std::queue<value_type>;
using size_type = typename container_type::size_type;
private:
container_type container_;
mutable std::mutex mutex_;
std::condition_variable container_cond_;
public:
ConcurrencyQueue() = default;
ConcurrencyQueue(const ConcurrencyQueue&) = default;
ConcurrencyQueue(ConcurrencyQueue&&) = default;
ConcurrencyQueue& operator=(const ConcurrencyQueue&) = default;
ConcurrencyQueue& operator=(ConcurrencyQueue&&) = default;
private:
bool empty_() const { return container_.empty(); }
public:
bool empty() const {
std::lock_guard<std::mutex> lg(mutex_);
return container_.empty();
}
void push(value_type item) {
std::lock_guard<std::mutex> lg(mutex_);
container_.push(std::move(item));
container_cond_.notify_one();
}
void wait_and_pop(value_type& out) {
std::unique_lock<std::mutex> lk(mutex_);
while (empty_()) {
container_cond_.wait(lk)
}
out = std::move(container_.front());
container_.pop();
}
std::shared_ptr<value_type> wait_and_pop() {
std::unique_lock<std::mutex> lk(mutex_);
while (empty_()) {
container_cond_.wait(lk)
}
auto res = std::make_shared<value_type>(std::move(container_.front()));
container_.pop();
return res;
}
bool try_pop(value_type& out) {
std::lock_guard<std::mutex> lg(mutex_);
if (empty_()) {
return false;
} else {
out = std::move(container_.front());
container_.pop();
return true;
}
}
std::shared_ptr<value_type> try_pop() {
std::lock_guard<std::mutex> lg(mutex_);
if (empty_()) {
return nullptr;
} else {
auto res = std::make_shared<value_type>(std::move(container_.front()));
container_.pop();
return res;
}
}
};
#endif // QUEUE_CONCURRENCY_QUEUE_HPP_

View File

@ -0,0 +1,105 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/10.
*/
#ifndef QUEUE_DYNAMIC_ARRAY_QUEUE_HPP_
#define QUEUE_DYNAMIC_ARRAY_QUEUE_HPP_
template <typename T>
class DynamicArrayQueue {
private:
T* items_ = nullptr;
size_t capacity_ = 0;
size_t head_ = 0;
size_t tail_ = 0;
public:
DynamicArrayQueue() = delete;
DynamicArrayQueue(const size_t capacity) : capacity_(capacity) {
items_ = new T[capacity_];
}
~DynamicArrayQueue() {
if (nullptr != items_) {
delete[] items_;
items_ = nullptr;
}
}
DynamicArrayQueue(const DynamicArrayQueue& other) : capacity_(other.capacity_) {
items_ = new T[capacity_];
for (size_t i = other.head_; i != other.tail_; ++i) {
enqueue(other.items_[i]);
}
}
DynamicArrayQueue& operator=(const DynamicArrayQueue& rhs) {
delete[] items_;
head_ = 0;
tail_ = 0;
capacity_ = rhs.capacity_;
items_ = new T[capacity_];
for (size_t i = rhs.head_; i != rhs.tail_; ++i) {
enqueue(rhs.items_[i]);
}
return *this;
}
DynamicArrayQueue(DynamicArrayQueue&& other) : items_(other.items_),
capacity_(other.capacity_),
head_(other.head_),
tail_(other.tail_) {
other.items_ = nullptr;
other.capacity_ = 0;
other.head_ = 0;
other.tail_ = 0;
}
DynamicArrayQueue& operator=(DynamicArrayQueue&& rhs) {
delete[] items_;
items_ = rhs.items_;
capacity_ = rhs.capacity_;
head_ = rhs.head_;
tail_ = rhs.tail_;
rhs.items_ = nullptr;
rhs.capacity_ = 0;
rhs.head_ = 0;
rhs.tail_ = 0;
return *this;
}
public:
void enqueue(T item) {
if (capacity_ == tail_ - head_) {
throw "Push data into a full queue!";
}
if (capacity_ == tail_) {
// item transport
for (size_t i = head_; i != tail_; ++i) {
items_[i - head_] = items_[i];
}
tail_ = tail_ - head_;
head_ = 0;
}
items_[tail_++] = item;
}
T head() const {
if (head_ != tail_) {
return items_[head_];
} else {
throw "Fetch data from an empty queue!";
}
}
void dequeue() {
if (head_ != tail_) {
++head_;
} else {
throw "Pop data from an empty queue!";
}
}
public:
template <typename UnaryFunc>
void traverse(UnaryFunc do_traverse) {
for (size_t i = head_; i != tail_; ++i) {
do_traverse(items_[i]);
}
}
};
#endif // QUEUE_DYNAMIC_ARRAY_QUEUE_HPP_

View File

@ -0,0 +1,62 @@
#include <iostream>
#include "dynamic_array_queue.hpp"
int main() {
auto do_traverse = [&](auto item){ std::cout << item << ' '; };
DynamicArrayQueue<int> dynamic_array_queue_1(3);
dynamic_array_queue_1.enqueue(1);
dynamic_array_queue_1.enqueue(2);
dynamic_array_queue_1.enqueue(3);
// dynamic_array_queue_1.enqueue(4); // throw
dynamic_array_queue_1.traverse(do_traverse);
std::cout << std::endl;
DynamicArrayQueue<int> dynamic_array_queue_2(dynamic_array_queue_1); // copy constructor
dynamic_array_queue_2.traverse(do_traverse);
std::cout << std::endl;
DynamicArrayQueue<int> dynamic_array_queue_3(std::move(dynamic_array_queue_2)); // move constructor
dynamic_array_queue_3.traverse(do_traverse);
std::cout << std::endl;
dynamic_array_queue_2.traverse(do_traverse);
std::cout << std::endl;
std::cout << dynamic_array_queue_3.head() << std::endl;
dynamic_array_queue_3.dequeue();
std::cout << dynamic_array_queue_3.head() << std::endl;
dynamic_array_queue_3.dequeue();
std::cout << dynamic_array_queue_3.head() << std::endl;
dynamic_array_queue_3.dequeue();
// std::cout << dynamic_array_queue_3.head() << std::endl; // throw
// dynamic_array_queue_3.dequeue(); // throw
DynamicArrayQueue<int> dynamic_array_queue_4(1);
dynamic_array_queue_4 = dynamic_array_queue_1; // copy assignment
dynamic_array_queue_4.traverse(do_traverse);
std::cout << std::endl;
DynamicArrayQueue<int> dynamic_array_queue_5(100);
dynamic_array_queue_5 = std::move(dynamic_array_queue_4); // move assignment
dynamic_array_queue_5.traverse(do_traverse);
std::cout << std::endl;
dynamic_array_queue_4.traverse(do_traverse);
std::cout << std::endl;
std::cout << dynamic_array_queue_5.head() << std::endl;
dynamic_array_queue_5.dequeue();
std::cout << dynamic_array_queue_5.head() << std::endl;
dynamic_array_queue_5.dequeue();
std::cout << dynamic_array_queue_5.head() << std::endl;
dynamic_array_queue_5.dequeue();
// std::cout << dynamic_array_queue_5.head() << std::endl; // throw
// dynamic_array_queue_5.dequeue(); // throw
for (size_t i = 0; i != 3; ++i) {
dynamic_array_queue_1.dequeue();
dynamic_array_queue_1.enqueue(i + 4);
dynamic_array_queue_1.traverse(do_traverse);
std::cout << std::endl;
}
return 0;
}

View File

@ -0,0 +1,75 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/10.
*/
#ifndef QUEUE_LINKED_QUEUE_HPP_
#define QUEUE_LINKED_QUEUE_HPP_
#include <memory>
template <typename T>
struct Node {
using ptr_t = std::shared_ptr<Node<T>>;
T data;
ptr_t next;
Node(T data_) : data(data_), next(nullptr) {}
Node() : next(nullptr) {}
};
template <typename T>
class LinkedQueue {
public:
using node_type = Node<T>;
using node_ptr_t = typename node_type::ptr_t;
private:
node_ptr_t head_ = nullptr;
node_ptr_t before_tail_ = nullptr;
public:
LinkedQueue() = default;
~LinkedQueue() = default;
LinkedQueue(const LinkedQueue& other) = default;
LinkedQueue& operator=(const LinkedQueue& rhs) = default;
LinkedQueue(LinkedQueue&& other) = default;
LinkedQueue& operator=(LinkedQueue&& rhs) = default;
public:
void enqueue(T item) {
if (nullptr == head_) {
head_ = std::make_shared<node_type>(item);
before_tail_ = head_;
} else {
before_tail_->next = std::make_shared<node_type>(item);
before_tail_ = before_tail_->next;
}
}
T head() const {
if (nullptr != head_) {
return head_->data;
} else {
throw "Fetch data from an empty queue!";
}
}
void dequeue() {
if (nullptr != head_) {
head_ = head_->next;
if (nullptr == head_) {
before_tail_ = nullptr;
}
} else {
throw "Pop data from an empty queue!";
}
}
public:
template <typename UnaryFunc>
void traverse(UnaryFunc do_traverse) {
for (node_ptr_t work = head_; nullptr != work; work = work->next) {
do_traverse(work->data);
}
}
};
#endif // QUEUE_LINKED_QUEUE_HPP_

View File

@ -0,0 +1,55 @@
#include <iostream>
#include "linked_queue.hpp"
int main() {
auto do_traverse = [&](auto item){ std::cout << item << ' '; };
LinkedQueue<int> linked_queue_1;
linked_queue_1.enqueue(1);
linked_queue_1.enqueue(2);
linked_queue_1.enqueue(3);
linked_queue_1.traverse(do_traverse);
std::cout << std::endl;
LinkedQueue<int> linked_queue_2(linked_queue_1); // copy constructor
linked_queue_2.traverse(do_traverse);
std::cout << std::endl;
LinkedQueue<int> linked_queue_3(std::move(linked_queue_2)); // move constructor
linked_queue_3.traverse(do_traverse);
std::cout << std::endl;
linked_queue_2.traverse(do_traverse);
std::cout << std::endl;
std::cout << linked_queue_3.head() << std::endl;
linked_queue_3.dequeue();
std::cout << linked_queue_3.head() << std::endl;
linked_queue_3.dequeue();
std::cout << linked_queue_3.head() << std::endl;
linked_queue_3.dequeue();
// std::cout << linked_queue_3.head() << std::endl; // throw
// linked_queue_3.dequeue(); // throw
LinkedQueue<int> linked_queue_4;
linked_queue_4 = linked_queue_1; // copy assignment
linked_queue_4.traverse(do_traverse);
std::cout << std::endl;
LinkedQueue<int> linked_queue_5;
linked_queue_5 = std::move(linked_queue_4); // move assignment
linked_queue_5.traverse(do_traverse);
std::cout << std::endl;
linked_queue_4.traverse(do_traverse);
std::cout << std::endl;
std::cout << linked_queue_5.head() << std::endl;
linked_queue_5.dequeue();
std::cout << linked_queue_5.head() << std::endl;
linked_queue_5.dequeue();
std::cout << linked_queue_5.head() << std::endl;
linked_queue_5.dequeue();
// std::cout << linked_queue_5.head() << std::endl; // throw
// linked_queue_5.dequeue(); // throw
return 0;
}

View File

@ -0,0 +1,84 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/11.
*/
#ifndef QUEUE_LOCK_FREE_QUEUE_HPP_
#define QUEUE_LOCK_FREE_QUEUE_HPP_
#include <memory>
#include <atomic>
template <typename T>
class LockFreeQueue {
public:
using value_type = T;
private:
struct node {
std::shared<value_type> data = nullptr;
node* next = nullptr;
};
std::atomic<node*> head = nullptr;
std::atomic<node*> tail = nullptr;
public:
LockFreeQueue() head(new node), tail(head.load()) {}
LockFreeQueue(const LockFreeQueue&) = delete;
LockFreeQueue(LockFreeQueue&& other) : head(other.head.load()), tail(other.tail.load()) {
other.head.store(nullptr);
other.tail.store(nullptr);
}
LockFreeQueue& operator=(const LockFreeQueue&) = delete;
LockFreeQueue& operator=(LockFreeQueue&& rhs) {
while (node* const old_head = head.load()) {
head.store(old_head->next);
delete old_head;
}
head.store(rhs.head.load());
tail.store(rhs.tail.load());
rhs.head.store(nullptr);
rhs.tail.store(nullptr);
}
~LockFreeQueue() {
while (node* const old_head = head.load()) {
head.store(old_head->next);
delete old_head;
}
}
private:
node* pop_head() {
node* const res = head.load();
if (res == tail.load()) {
return nullptr;
}
head.store(res->next);
return res;
}
public:
bool empty() const {
return head.load() == tail.load();
}
std::shared_ptr<value_type> pop() {
node* old_head = pop_head();
if (nullptr == old_head) {
return nullptr;
} else {
auto res = old_head->data;
delete old_head;
return res;
}
}
void push(value_type new_value) {
auto new_data = std::make_shared<value_type>(new_value);
node* p = new node;
node* old_tail = tail.load();
old_tail->data.swap(new_data);
old_tail->next = p;
tail_.store(p);
}
};
#endif // QUEUE_LOCK_FREE_QUEUE_HPP_

View File

View File

@ -0,0 +1,71 @@
#include <iostream>
#include <unordered_map>
class SolutionOFOneTwoStep {
private:
static std::unordered_map<size_t, size_t> result_;
public:
enum class POLICY {
RECURSIVE,
NONRECURSIVE
};
private:
size_t recursive(size_t steps) {
auto iter = result_.find(steps);
if (result_.end() != iter) { // found.
return iter->second;
} else {
size_t res = operator()(steps - 1) + operator()(steps - 2);
result_.insert({steps, res});
return res;
}
}
size_t nonrecursive(size_t steps) {
auto iter = result_.find(steps);
if (result_.end() != iter) { // found.
return iter->second;
} else {
size_t start;
for (start = steps; start != 2 and result_.end() == result_.find(start); --start) {}
for (size_t i = start; i != steps; ++i) {
result_.insert({i + 1, result_[i - 1] + result_[i]});
}
return result_[steps];
}
}
public:
size_t operator()(size_t steps, const POLICY policy = POLICY::RECURSIVE) {
if (policy == POLICY::RECURSIVE) {
return recursive(steps);
} else if (policy == POLICY::NONRECURSIVE) {
return nonrecursive(steps);
}
}
static void debug() {
for (auto kv : result_) {
std::cout << kv.first << ' ' << kv.second << std::endl;
}
std::cout << std::endl;
}
};
std::unordered_map<size_t, size_t> SolutionOFOneTwoStep::result_ = {{1, 1}, {2, 2}};
int main() {
SolutionOFOneTwoStep::debug();
std::cout << SolutionOFOneTwoStep()(5, SolutionOFOneTwoStep::POLICY::RECURSIVE) << std::endl;
SolutionOFOneTwoStep::debug();
std::cout << SolutionOFOneTwoStep()(10, SolutionOFOneTwoStep::POLICY::NONRECURSIVE) << std::endl;
SolutionOFOneTwoStep::debug();
std::cout << SolutionOFOneTwoStep()(20, SolutionOFOneTwoStep::POLICY::RECURSIVE) << std::endl;
SolutionOFOneTwoStep::debug();
return 0;
}

View File

@ -28,12 +28,17 @@ func (this *ArrayStack) IsEmpty() bool {
}
func (this *ArrayStack) Push(v interface{}) {
this.data = append(this.data, v)
if this.top < 0 {
this.top = 0
} else {
this.top += 1
}
if this.top > len(this.data)-1 {
this.data = append(this.data, v)
} else {
this.data[this.top] = v
}
}
func (this *ArrayStack) Pop() interface{} {

View File

@ -6,7 +6,12 @@ func TestArrayStack_Push(t *testing.T) {
s := NewArrayStack()
s.Push(1)
s.Push(2)
t.Log(s.Pop())
s.Push(3)
t.Log(s.Pop())
t.Log(s.Pop())
s.Push(4)
t.Log(s.Pop())
s.Print()
}

View File

@ -0,0 +1,72 @@
package _9_queue
import "fmt"
type CircularQueue struct {
q []interface{}
capacity int
head int
tail int
}
func NewCircularQueue(n int) *CircularQueue {
if n == 0 {
return nil
}
return &CircularQueue{make([]interface{}, n), n, 0, 0}
}
/*
栈空条件head==tail为true
*/
func (this *CircularQueue) IsEmpty() bool {
if this.head == this.tail {
return true
}
return false
}
/*
栈满条件(tail+1)%capacity==head为true
*/
func (this *CircularQueue) IsFull() bool {
if this.head == (this.tail+1)%this.capacity {
return true
}
return false
}
func (this *CircularQueue) EnQueue(v interface{}) bool {
if this.IsFull() {
return false
}
this.q[this.tail] = v
this.tail = (this.tail + 1) % this.capacity
return true
}
func (this *CircularQueue) DeQueue() interface{} {
if this.IsEmpty() {
return nil
}
v := this.q[this.head]
this.head = (this.head + 1) % this.capacity
return v
}
func (this *CircularQueue) String() string {
if this.IsEmpty() {
return "empty queue"
}
result := "head"
var i = this.head
for true {
result += fmt.Sprintf("<-%+v", this.q[i])
i = (i + 1) % this.capacity
if i == this.tail {
break
}
}
result += "<-tail"
return result
}

View File

@ -0,0 +1,37 @@
package _9_queue
import "testing"
func TestCircularQueue_EnQueue(t *testing.T) {
q := NewCircularQueue(5)
q.EnQueue(1)
q.EnQueue(2)
q.EnQueue(3)
q.EnQueue(4)
q.EnQueue(5)
q.EnQueue(6)
t.Log(q)
}
func TestCircularQueue_DeQueue(t *testing.T) {
q := NewCircularQueue(5)
q.EnQueue(1)
q.EnQueue(2)
q.EnQueue(3)
q.EnQueue(4)
q.EnQueue(5)
q.EnQueue(6)
t.Log(q)
t.Log(q.DeQueue())
t.Log(q)
q.EnQueue(5)
t.Log(q)
q.DeQueue()
t.Log(q)
q.DeQueue()
t.Log(q)
q.DeQueue()
t.Log(q)
q.DeQueue()
t.Log(q)
}

View File

@ -0,0 +1,44 @@
package _9_queue
import "fmt"
type ArrayQueue struct {
q []interface{}
capacity int
head int
tail int
}
func NewArrayQueue(n int) *ArrayQueue {
return &ArrayQueue{make([]interface{}, n), n, 0, 0}
}
func (this *ArrayQueue) EnQueue(v interface{}) bool {
if this.tail == this.capacity {
return false
}
this.q[this.tail] = v
this.tail++
return true
}
func (this *ArrayQueue) DeQueue() interface{} {
if this.head == this.tail {
return nil
}
v := this.q[this.head]
this.head++
return v
}
func (this *ArrayQueue) String() string {
if this.head == this.tail {
return "empty queue"
}
result := "head"
for i := this.head; i <= this.tail-1; i++ {
result += fmt.Sprintf("<-%+v", this.q[i])
}
result += "<-tail"
return result
}

View File

@ -0,0 +1,35 @@
package _9_queue
import "testing"
func TestArrayQueue_EnQueue(t *testing.T) {
q := NewArrayQueue(5)
q.EnQueue(1)
q.EnQueue(2)
q.EnQueue(3)
q.EnQueue(4)
q.EnQueue(5)
q.EnQueue(6)
t.Log(q)
}
func TestArrayQueue_DeQueue(t *testing.T) {
q := NewArrayQueue(5)
q.EnQueue(1)
q.EnQueue(2)
q.EnQueue(3)
q.EnQueue(4)
q.EnQueue(5)
q.EnQueue(6)
t.Log(q)
q.DeQueue()
t.Log(q)
q.DeQueue()
t.Log(q)
q.DeQueue()
t.Log(q)
q.DeQueue()
t.Log(q)
q.DeQueue()
t.Log(q)
}

View File

@ -0,0 +1,52 @@
package _9_queue
import "fmt"
type ListNode struct {
val interface{}
next *ListNode
}
type LinkedListQueue struct {
head *ListNode
tail *ListNode
length int
}
func NewLinkedListQueue() *LinkedListQueue {
return &LinkedListQueue{nil, nil, 0}
}
func (this *LinkedListQueue) EnQueue(v interface{}) {
node := &ListNode{v, nil}
if nil == this.tail {
this.tail = node
this.head = node
} else {
this.tail.next = node
this.tail = node
}
this.length++
}
func (this *LinkedListQueue) DeQueue() interface{} {
if this.head == nil {
return nil
}
v := this.head.val
this.head = this.head.next
this.length--
return v
}
func (this *LinkedListQueue) String() string {
if this.head == nil {
return "empty queue"
}
result := "head<-"
for cur := this.head; cur != nil; cur = cur.next {
result += fmt.Sprintf("<-%+v", cur.val)
}
result += "<-tail"
return result
}

View File

@ -0,0 +1,35 @@
package _9_queue
import "testing"
func TestListQueue_EnQueue(t *testing.T) {
q := NewLinkedListQueue()
q.EnQueue(1)
q.EnQueue(2)
q.EnQueue(3)
q.EnQueue(4)
q.EnQueue(5)
q.EnQueue(6)
t.Log(q)
}
func TestListQueue_DeQueue(t *testing.T) {
q := NewLinkedListQueue()
q.EnQueue(1)
q.EnQueue(2)
q.EnQueue(3)
q.EnQueue(4)
q.EnQueue(5)
q.EnQueue(6)
t.Log(q)
q.DeQueue()
t.Log(q)
q.DeQueue()
t.Log(q)
q.DeQueue()
t.Log(q)
q.DeQueue()
t.Log(q)
q.DeQueue()
t.Log(q)
}

View File

@ -11,14 +11,14 @@ public class Array {
public int data[];
//定义数组长度
private int n;
//定义中保存的数据个数
//定义中实际个数
private int count;
//构造方法定义数组大小
public Array(int capacity){
this.data = new int[]{0,1,2,3,4};
this.data = new int[capacity];
this.n = capacity;
this.count=capacity;
this.count=0;//一开始一个数都没有存所以为0
}
//根据索引找到数据中的元素并返回
@ -49,13 +49,14 @@ public class Array {
//向数组中插入一个元素
public boolean insert(int index, int value){
if (index<0 || index>=count) return false;
// if (count == n) return false;不是太懂
//数组长度增加1
int[] arr = new int[count+1];
//当实际存储的个数等于数组的最大长度就不让新增
if (count == n) return false;
//数组长度增加1不需要初始化
/*int[] arr = new int[count+1];
for (int i = 0; i < data.length; i++) {
arr[i] = data[i];
}
data=arr;
data=arr;*/
for (int i = count-1; i>=index; --i){
data[i+1] = data[i];
@ -66,13 +67,15 @@ public class Array {
}
public boolean insertToTail(int value) {
// if (count == n) return false;不是太懂
//当实际存储的个数等于数组的最大长度就不让新增
if (count == n) return false;
//数组长度增加1
int[] arr = new int[count+1];
/*int[] arr = new int[count+1];
for (int i = 0; i < data.length; i++) {
arr[i] = data[i];
}
data=arr;
data=arr;*/
data[count++] = value;
return true;
}

View File

@ -36,7 +36,8 @@ public class CircularQueue {
}
public void printAll() {
for (int i = head; i < tail; ++i) {
if (0 == n) return;
for (int i = head; i % n != tail; ++i) {
System.out.print(items[i] + " ");
}
System.out.println();

View File

@ -3,7 +3,7 @@ package queue;
/**
* Created by wangzheng on 2018/10/9.
*/
public class DynimacArrayQueue {
public class DynamicArrayQueue {
// 数组items数组大小n
private String[] items;
private int n = 0;
@ -12,7 +12,7 @@ public class DynimacArrayQueue {
private int tail = 0;
// 申请一个大小为capacity的数组
public DynimacArrayQueue(int capacity) {
public DynamicArrayQueue(int capacity) {
items = new String[capacity];
n = capacity;
}

View File

@ -33,7 +33,7 @@ class LinkedList {
currentNode = currentNode.next
pos++
}
return currentNode === null ? -1 : pos
return currentNode === null ? -1 : currentNode
}
// 指定元素向后插入
insert(newElement, element) {
@ -69,6 +69,9 @@ class LinkedList {
}
// 遍历显示所有节点
display() {
//先检查是否为环
if(this.checkCircle()) return false
let currentNode = this.head
while (currentNode !== null) {
console.log(currentNode.element)
@ -89,6 +92,30 @@ class LinkedList {
this.head = root
}
//增强尾插法可读性,便于初学者理解
reverseList1(){
//head节点即哨兵作用就是使所有链表
// 包括空链表的头节点不为null,并使对单链表的插入、删除操作不需要区分是否为空表或是否在第一个位置进行,
// 从而与其他位置的插入、删除操作一致
//所以反转链表的时候不需要带上head节点
let currentNode=this.head.next
//第一个节点头结点让其指向null
let previousNode=null
while(currentNode!==null){
//务必先保留下一节点的指针地址
let nextNode=currentNode.next
//第一次是null
currentNode.next=previousNode
//此时将previousNode赋值为当前节点
// 那么下次循环的时候方便下次的currentNode指向previousNode
previousNode=currentNode
//抬走,下一个!
currentNode=nextNode
}
//最后将反转好的链表加上头节点
this.head.next=previousNode
}
// 自己一开始瞎想的。差距啊
reverseList2() {
let currentNode = this.head.next
@ -122,6 +149,8 @@ class LinkedList {
}
// 删除倒数第k个节点
removeByIndexFromEnd(index) {
//务必先判断是否是 环链表
if(this.checkCircle()) return false
let pos = 1
this.reverseList()
let currentNode = this.head.next

View File

@ -0,0 +1,56 @@
/**
* 使用前后栈实现浏览器的前进后退
*
* Author nameczz
*/
const stack = require('./StackBasedOnLinkedList')
class SampleBrowser {
constructor() {
this.normalStack = new stack.CreatedStack()
this.backStack = new stack.CreatedStack()
}
// 正常浏览页面
pushNormal(name) {
this.normalStack.push(name)
this.backStack.clear()
this.displayAllStack()
}
// 后退
back() {
const value = this.normalStack.pop()
if (value !== -1) {
this.backStack.push(value)
this.displayAllStack()
} else {
console.log('无法后退')
}
}
// 前进
front() {
const value = this.backStack.pop()
if (value !== -1) {
this.normalStack.push(value)
this.displayAllStack()
} else {
console.log('无法前进')
}
}
// 打印栈内数据
displayAllStack() {
console.log('---后退页面---')
this.backStack.display()
console.log('---浏览页面---')
this.normalStack.display()
}
}
// Test
const browser = new SampleBrowser()
browser.pushNormal('www.google.com')
browser.pushNormal('www.baidu.com')
browser.pushNormal('www.github.com')
// 后退
browser.back()
browser.back()
browser.front()
browser.pushNormal('www.new.com')

View File

@ -0,0 +1,62 @@
/**
* 基于链表实现的栈
*
* Author: nameczz
*/
class Node {
constructor(element) {
this.element = element
this.next = null
}
}
class StackBasedLinkedList {
constructor() {
this.top = null
}
push(value) {
const node = new Node(value)
if (this.top === null) {
this.top = node
} else {
node.next = this.top
this.top = node
}
}
pop() {
if (this.top === null) {
return -1
}
const value = this.top.element
this.top = this.top.next
return value
}
// 为了实现浏览器前进后退
clear() {
this.top = null
}
display() {
if (this.top !== null) {
let temp = this.top
while (temp !== null) {
console.log(temp.element)
temp = temp.next
}
}
}
}
// Test
const newStack = new StackBasedLinkedList()
newStack.push(1)
newStack.push(2)
newStack.push(3)
// 获取元素
let res = 0
console.log('-------获取pop元素------')
while (res !== -1) {
res = newStack.pop()
console.log(res)
}
exports.CreatedStack = StackBasedLinkedList

View File

@ -0,0 +1,71 @@
/**
* 基于链表实现的循环队列
*
* Author: nameczz
*/
class Node {
constructor(element) {
this.element = element
this.next = null
}
}
class CircularQueue {
constructor() {
this.head = null
this.tail = null
}
enqueue(value) {
if (this.head === null) {
this.head = new Node(value)
this.head.next = this.head
this.tail = this.head
} else {
const flag = this.head === this.tail
this.tail.next = new Node(value)
this.tail.next.next = this.head
this.tail = this.tail.next
if (flag) {
this.head.next = this.tail
}
}
}
dequeue() {
if (this.head === this.tail) {
const value = this.head.element
this.head = null
return value
} else if (this.head !== null) {
const value = this.head.element
this.head = this.head.next
this.tail.next = this.head
return value
} else {
return -1
}
}
display() {
let res = 0
console.log('-------获取dequeue元素------')
while (res !== -1) {
res = this.dequeue()
console.log(res)
}
}
}
// Test
const newCircularQueue = new CircularQueue()
// 插入元素
newCircularQueue.enqueue(1)
newCircularQueue.enqueue(2)
newCircularQueue.enqueue(3)
// 获取元素
newCircularQueue.display()
newCircularQueue.enqueue(1)
newCircularQueue.display()
// exports.CreatedStack = StackBasedLinkedList

View File

@ -0,0 +1,52 @@
/**
* 基于链表实现的队列
*
* Author: nameczz
*/
class Node {
constructor(element) {
this.element = element
this.next = null
}
}
class QueueBasedOnLinkedList {
constructor() {
this.head = null
this.tail = null
}
enqueue(value) {
if (this.head === null) {
this.head = new Node(value)
this.tail = this.head
} else {
this.tail.next = new Node(value)
this.tail = this.tail.next
}
}
dequeue() {
if (this.head !== null) {
const value = this.head.element
this.head = this.head.next
return value
} else {
return -1
}
}
}
// Test
const newQueue = new QueueBasedOnLinkedList()
// 插入元素
newQueue.enqueue(1)
newQueue.enqueue(2)
newQueue.enqueue(3)
// 获取元素
let res = 0
console.log('-------获取dequeue元素------')
while (res !== -1) {
res = newQueue.dequeue()
console.log(res)
}

0
notes/.gitkeep Normal file
View File

View File

@ -0,0 +1,28 @@
# 递归
## 三个条件
* 可分解为子问题
* 子问题与原问题解法一致,只有规模上的不同
* 有终止条件
## 写递归代码
* 整理出递推公式
* 确定好终止条件
* 「翻译」成代码
关键:
> 只要遇到递归,我们就把它抽象成一个递推公式,不用想一层层的调用关系,不要试图用人脑去分解每一个步骤。
## 警惕
* 堆栈溢出 <- 递归深度过大
* 重复计算 <- 递归过程中的不同分支重复计算相同子问题
* 保存子问题结果map/dict
* 空间复杂度高 <- 递归函数调用带来的消耗
## 递归改写非递归
本质:人肉模拟函数调用堆栈。

View File

@ -133,7 +133,7 @@ class SingleLinkedList
$preNode = $this->head;
// 遍历找到前置节点 要用全等判断是否是同一个对象
// http://php.net/manual/zh/language.oop5.object-comparison.php
while ($curNode !== $node) {
while ($curNode !== $node && $curNode != null) {
$preNode = $curNode;
$curNode = $curNode->next;
}

0
php/08_stack/.gitkeep Normal file
View File

View File

@ -0,0 +1,159 @@
<?php
/**
* User: lide01
* Date: 2018/10/11 19:37
* Desc:
*/
namespace Algo_08;
use Algo_06\SingleLinkedListNode;
class StackOnLinkedList
{
/**
* 头指针
*
* @var SingleLinkedListNode
*/
public $head;
/**
* 栈长度
*
* @var
*/
public $length;
/**
*
* StackOnLinkedList constructor.
*/
public function __construct()
{
$this->head = new SingleLinkedListNode();
$this->length = 0;
}
/**
* 出栈
*
* @return bool
*/
public function pop()
{
if (0 == $this->length) {
return false;
}
$this->head->next = $this->head->next->next;
$this->length--;
return true;
}
/**
* 入栈
*
* @param $data
*
* @return SingleLinkedListNode|bool
*/
public function push($data)
{
return $this->pushData($data);
}
/**
* 入栈 node
*
* @param SingleLinkedListNode $node
*
* @return bool
*/
public function pushNode(SingleLinkedListNode $node)
{
if (null == $node) {
return false;
}
$node->next = $this->head->next;
$this->head->next = $node;
$this->length++;
return true;
}
/**
* 入栈 data
*
* @param $data
*
* @return SingleLinkedListNode|bool
*/
public function pushData($data)
{
$node = new SingleLinkedListNode($data);
if (!$this->pushNode($node)) {
return false;
}
return $node;
}
/**
* 获取栈顶元素
*
* @return SingleLinkedListNode|bool|null
*/
public function top()
{
if (0 == $this->length) {
return false;
}
return $this->head->next;
}
/**
* 打印栈
*/
public function printSelf()
{
if (0 == $this->length) {
echo 'empty stack' . PHP_EOL;
return;
}
echo 'head.next -> ';
$curNode = $this->head;
while ($curNode->next) {
echo $curNode->next->data . ' -> ';
$curNode = $curNode->next;
}
echo 'NULL' . PHP_EOL;
}
/**
* 获取栈长度
*
* @return int
*/
public function getLength()
{
return $this->length;
}
/**
* 判断栈是否为空
*
* @return bool
*/
public function isEmpty()
{
return $this->length > 0 ? false : true;
}
}

32
php/08_stack/main.php Normal file
View File

@ -0,0 +1,32 @@
<?php
/**
* User: lide01
* Date: 2018/10/11 20:01
* Desc:
*/
namespace Algo_08;
require_once '../vendor/autoload.php';
$stack = new StackOnLinkedList();
$stack->pushData(1);
$stack->pushData(2);
$stack->pushData(3);
$stack->pushData(4);
var_dump($stack->getLength());
$stack->printSelf();
$topNode = $stack->top();
var_dump($topNode->data);
$stack->pop();
$stack->printSelf();
$stack->pop();
$stack->printSelf();
var_dump($stack->getLength());
$stack->pop();
$stack->pop();
$stack->printSelf();

View File

@ -1,16 +1,20 @@
## 数据结构与算法之美PHP实现
### 项目运行
* 依赖composer自动加载php目录下执行`composer dump-autoload`
* 依赖composer自动加载php目录下执行`composer dump-autoload` || `sh buildAutoLoad.sh`
* 项目代码均在mac&php7环境下跑通
### 项目实现
#### 06
#### 06_linkedlist
* 单链表php实现
* 回文判断
#### 07
#### 07_linkedlist
* reverse 单链表反转
* checkCircle 链表中环的检测
* mergerSortedList 两个有序的链表合并
* deleteLastKth 删除链表倒数第n个结点
* findMiddleNode 求链表的中间结点
* findMiddleNode 求链表的中间结点
#### 08_stack
* 链栈实现

78
php/Stack/Compute.php Normal file
View 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);');

View File

@ -6,7 +6,8 @@
"autoload": {
"psr-4": {
"Algo_06\\": "06_linkedlist/",
"Algo_07\\": "07_linkedlist/"
"Algo_07\\": "07_linkedlist/",
"Algo_08\\": "08_stack/"
}
}
}

View File

@ -39,7 +39,10 @@ class MyArray:
def insert_to_tail(self, value: int) -> bool:
if self._count == self._capacity: return False
self._data.append(value)
if self._count == len(self._data):
self._data.append(value)
else:
self._data[self._count] = value
self._count += 1
return True
@ -57,4 +60,6 @@ if __name__ == "__main__":
a.insert_to_tail(i)
a.delete(2)
print(a)
a.insert_to_tail(7)
print(a)

View File

@ -55,7 +55,7 @@ def merge_sorted_list(l1: Node, l2: Node) -> Optional[Node]:
current = current._next
current._next = p1 if p1 else p2
return fake_head._next
return p1 or p2
return l1 or l2
# Remove nth node from the end
# 删除倒数第n个节点。假设n大于0

View File

@ -16,9 +16,16 @@ class ArrayQueue:
self._tail = 0
def enqueue(self, item: str) -> bool:
if self._tail == self._capacity: return False
if self._tail == self._capacity:
if self._head == 0:
return False
else:
for i in range(0, self._tail - self._head):
self._data[i] = self._items[i + self._head]
self._tail = self._tail - self._head
self._head = 0
self._items.append(item)
self._items.insert(self._tail, item)
self._tail += 1
return True

View File

@ -0,0 +1,51 @@
"""
Author: Wenru
"""
from typing import Optional
class DynamicArrayQueue:
def __init__(self, capacity: int):
self._items = []
self._capacity = capacity
self._head = 0
self._tail = 0
def enqueue(self, item: str) -> bool:
if self._tail == self._capacity:
if self._head == 0: return False
self._items[0 : self._tail - self._head] = self._items[self._head : self._tail]
self._tail -= self._head
self._head = 0
if self._tail == len(self._items):
self._items.append(item)
else:
self._items[self._tail] = item
self._tail += 1
return True
def dequeue(self) -> Optional[str]:
if self._head != self._tail:
item = self._items[self._head]
self._head += 1
return item
def __repr__(self) -> str:
return " ".join(item for item in self._items[self._head:self._tail])
if __name__ == "__main__":
q = DynamicArrayQueue(10)
for i in range(10):
q.enqueue(str(i))
print(q)
for _ in range(3):
q.dequeue()
print(q)
q.enqueue("7")
q.enqueue("8")
print(q)

View File

@ -0,0 +1,58 @@
"""
Queue based upon linked list
Author: Wenru
"""
from typing import Optional
class Node:
def __init__(self, data: str, next=None):
self.data = data
self._next = next
class LinkedQueue:
def __init__(self):
self._head: Optional[Node] = None
self._tail: Optional[Node] = None
def enqueue(self, value: str):
new_node = Node(value)
if self._tail:
self._tail._next = new_node
else:
self._head = new_node
self._tail = new_node
def dequeue(self) -> Optional[str]:
if self._head:
value = self._head.data
self._head = self._head._next
if not self._head:
self._tail = None
return value
def __repr__(self) -> str:
values = []
current = self._head
while current:
values.append(current.data)
current = current._next
return "->".join(value for value in values)
if __name__ == "__main__":
q = LinkedQueue()
for i in range(10):
q.enqueue(str(i))
print(q)
for _ in range(3):
q.dequeue()
print(q)
q.enqueue("7")
q.enqueue("8")
print(q)

View File

@ -0,0 +1,77 @@
//
// Created by Jiandan on 2018/10/10.
// Copyright (c) 2018 Jiandan. All rights reserved.
//
import Foundation
// <Element> Swift
public struct MyArray<Element> {
private var data: [Element]
private var capacity = 0 //
private var count = 0 //
///
/// - parameter defaultElement:
/// - parameter capacity:
init(defaultElement: Element, capacity: Int) {
data = [Element](repeating: defaultElement, count: capacity)
self.capacity = capacity
}
// index
func find(at index: Int) -> Element? {
// index [0, count)
guard index >= 0, index < count else {
return nil
}
return data[index]
}
// index
mutating func delete(at index: Int) -> Bool {
// index [0, count)
guard index >= 0, index < count else {
return false
}
// [index, count - 1) index
for i in index ..< count - 1 {
data[i] = data[i+1]
}
count -= 1
return true
}
// index
mutating func insert(value: Element, at index: Int) -> Bool {
// index [0, count)
guard index >= 0, index < count, count < capacity else {
return false
}
// count - 1 ~ index
for i in (index ... count - 1).reversed() {
data[i + 1] = data[i]
}
data[index] = value
count += 1
return true
}
//
mutating func add(value: Element) -> Bool {
guard count < capacity else {
return false
}
data[count] = value
count += 1
return true
}
func printAll() {
print("\(data)")
}
}

View File

@ -0,0 +1,112 @@
//
// Created by Jiandan on 2018/10/11.
// Copyright (c) 2018 Jiandan. All rights reserved.
//
import Foundation
///
struct ArrayQueue<T>: Queue {
typealias Element = T
///
private var items: [Element]
///
private var capacity = 0
///
private var head = 0
///
private var tail = 0
///
/// - parameter defaultElement:
/// - parameter capacity:
init(defaultElement: Element, capacity: Int) {
self.capacity = capacity
items = [Element](repeating: defaultElement, count: capacity)
}
// MARK: Protocol: Queue
var isEmpty: Bool { return head == tail }
var size: Int { return tail - head }
var peek: Element? { return isEmpty ? nil : items[head] }
//
// mutating func enqueue(newElement: Element) -> Bool {
// //
// if tail == capacity {
// return false
// }
//
// items[tail] = newElement
// tail += 1
// return true
// }
//
mutating func enqueue(newElement: Element) -> Bool {
// tail == capacity
if tail == capacity {
//
if head == 0 { return false }
//
for i in head ..< tail {
items[i - head] = items[i]
}
// head tail
tail -= head
head = 0
}
items[tail] = newElement
tail += 1
return true
}
mutating func dequeue() -> Element? {
if isEmpty {
return nil
}
let item = items[head]
head += 1
return item
}
}
/// 使2 Swift Array
/// iOS
struct ArrayQueue2<T>: Queue {
typealias Element = T
///
var inArray = [Element]()
///
var outArray = [Element]()
var isEmpty: Bool { return inArray.isEmpty && outArray.isEmpty }
var size: Int { return inArray.count + outArray.count }
// outArray inArray outArray
var peek: Element? { return outArray.isEmpty ? inArray.first : outArray.last }
mutating func enqueue(newElement: Element) -> Bool {
// inArray
inArray.append(newElement)
return true
}
mutating func dequeue() -> Element? {
if outArray.isEmpty {
// inArray outArray
outArray = inArray.reversed()
// inArray
inArray.removeAll()
}
// outArray
return outArray.popLast()
}
}

View File

@ -0,0 +1,63 @@
//
// Created by Jiandan on 2018/10/11.
// Copyright (c) 2018 Jiandan. All rights reserved.
//
import Foundation
///
struct CircularQueue<T>: Queue {
typealias Element = T
///
private var items: [Element]
///
private var capacity = 0
///
private var head = 0
///
private var tail = 0
///
/// - parameter defaultElement:
/// - parameter capacity:
init(defaultElement: Element, capacity: Int) {
self.capacity = capacity
items = [Element](repeating: defaultElement, count: capacity)
}
// MARK: Protocol: Queue
var isEmpty: Bool { return head == tail }
var size: Int {
if tail >= head {
return tail - head
} else {
return (tail + 1) + (capacity - head)
}
}
var peek: Element? { return isEmpty ? nil : items[head] }
mutating func enqueue(newElement: Element) -> Bool {
//
if (tail + 1) % capacity == head {
return false
}
items[tail] = newElement
tail = (tail + 1) % capacity
return true
}
mutating func dequeue() -> Element? {
if isEmpty {
return nil
}
let item = items[head]
head = (head + 1) % capacity
return item
}
}

View File

@ -0,0 +1,21 @@
//
// Created by Jiandan on 2018/10/11.
// Copyright (c) 2018 Jiandan. All rights reserved.
//
import Foundation
protocol Queue {
///
associatedtype Element
///
var isEmpty: Bool { get }
///
var size: Int { get }
///
var peek: Element? { get }
///
mutating func enqueue(newElement: Element) -> Bool
///
mutating func dequeue() -> Element?
}

View File

@ -0,0 +1,61 @@
//
// Created by Jiandan on 2018/10/11.
// Copyright (c) 2018 Jiandan. All rights reserved.
//
import Foundation
class Node<T> {
var value: T?
var next: Node?
init(value: T) {
self.value = value
}
}
struct QueueBasedOnLinkedList<T>: Queue {
typealias Element = T
///
var head: Node<Element>?
///
var tail: Node<Element>?
// MARK: Protocol: Queue
var isEmpty: Bool { return head == nil }
var size: Int {
var count = 0
while head?.next != nil {
count += 1
}
return count
}
var peek: Element? { return head?.value }
mutating func enqueue(newElement: Element) -> Bool {
if isEmpty {
//
let node = Node(value: newElement)
head = node
tail = node
} else {
tail!.next = Node(value: newElement)
tail = tail!.next
}
return true
}
mutating func dequeue() -> Element? {
if isEmpty {
return nil
}
let node = head
head = head!.next
return node?.value
}
}