commit
8ba56f1652
@ -1,4 +1,5 @@
|
|||||||
# 数据结构和算法必知必会的50个代码实现
|
# 数据结构和算法必知必会的50个代码实现
|
||||||
|
## (关注“小争哥”公众号,获取我的更多技术、非技术分享)
|
||||||
|
|
||||||
## 数组
|
## 数组
|
||||||
* 实现一个支持动态扩容的数组
|
* 实现一个支持动态扩容的数组
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void dlist_init(stDlistHead *dlist)
|
void dlist_init(stDlistHead *dlist) //链表初始化
|
||||||
{
|
{
|
||||||
dlist->size = 0;
|
dlist->size = 0;
|
||||||
dlist->head = NULL;
|
dlist->head = NULL;
|
||||||
@ -19,7 +19,7 @@ void dlist_init(stDlistHead *dlist)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dlist_destory(stDlistHead *dlist)
|
void dlist_destory(stDlistHead *dlist) //删除链表
|
||||||
{
|
{
|
||||||
stDlistNode *pNode = NULL;
|
stDlistNode *pNode = NULL;
|
||||||
|
|
||||||
@ -36,11 +36,11 @@ void dlist_destory(stDlistHead *dlist)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dlist_insert_head(stDlistHead *dlist,stDlistNode *pNode,int data)
|
int dlist_insert_head(stDlistHead *dlist,stDlistNode *pNode,int data) //插入头结点,操作的链表,操作的节点,数据
|
||||||
{
|
{
|
||||||
if(pNode == NULL)
|
if(pNode == NULL) //当只传递一个数据时
|
||||||
{
|
{
|
||||||
pNode = (stDlistNode *)malloc(sizeof(stDlistNode));
|
pNode = (stDlistNode *)malloc(sizeof(stDlistNode)); //新建节点,为节点分配空间(malloc()可能需要#include<malloc.h>)
|
||||||
if (pNode == NULL)
|
if (pNode == NULL)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
@ -51,23 +51,23 @@ int dlist_insert_head(stDlistHead *dlist,stDlistNode *pNode,int data)
|
|||||||
pNode->prev = NULL;
|
pNode->prev = NULL;
|
||||||
pNode->next = NULL;
|
pNode->next = NULL;
|
||||||
|
|
||||||
if (dlist->size == 0)
|
if (dlist->size == 0) //如果链表长度为0,即链表当前无节点,
|
||||||
{
|
{
|
||||||
dlist->head = pNode;
|
dlist->head = pNode;
|
||||||
dlist->tail = pNode;
|
dlist->tail = pNode;
|
||||||
}
|
}
|
||||||
else
|
else //如果链表已有节点,则令新插入节点为头节点
|
||||||
{
|
{
|
||||||
pNode->next = dlist->head;
|
pNode->next = dlist->head;
|
||||||
dlist->head->prev = pNode;
|
dlist->head->prev = pNode;
|
||||||
dlist->head = pNode;
|
dlist->head = pNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
dlist->size++;
|
dlist->size++; //每成功调用一次,链表长度+1
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
stDlistNode * dlist_remove_tail(stDlistHead *dlist)
|
stDlistNode * dlist_remove_tail(stDlistHead *dlist) //删除尾部节点,并返回删除节点
|
||||||
{
|
{
|
||||||
stDlistNode *pNode = NULL;
|
stDlistNode *pNode = NULL;
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ stDlistNode * dlist_remove_tail(stDlistHead *dlist)
|
|||||||
return pNode;
|
return pNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dlist_remove_node(stDlistHead * dlist,stDlistNode *pNode)
|
void dlist_remove_node(stDlistHead * dlist,stDlistNode *pNode) //删除指定节点
|
||||||
{
|
{
|
||||||
if ((dlist == NULL)||(pNode == NULL))
|
if ((dlist == NULL)||(pNode == NULL))
|
||||||
{
|
{
|
||||||
@ -119,12 +119,12 @@ void dlist_remove_node(stDlistHead * dlist,stDlistNode *pNode)
|
|||||||
|
|
||||||
if (dlist->size == 0)
|
if (dlist->size == 0)
|
||||||
{
|
{
|
||||||
memset(dlist,0,sizeof(stDlistHead));
|
memset(dlist,0,sizeof(stDlistHead)); //将dlist占用内存块的所有值置为0,也就是清空head,tail指针内容
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
stDlistNode * dlist_search(stDlistHead * dlist,int data)
|
stDlistNode * dlist_search(stDlistHead * dlist,int data) //根据值搜索节点,并返回
|
||||||
{
|
{
|
||||||
stDlistNode *pNode = dlist->head;
|
stDlistNode *pNode = dlist->head;
|
||||||
while(pNode != NULL)
|
while(pNode != NULL)
|
||||||
@ -139,30 +139,30 @@ stDlistNode * dlist_search(stDlistHead * dlist,int data)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dlist_dump(stDlistHead *dlist)
|
void dlist_dump(stDlistHead *dlist) //显示链表中的数据
|
||||||
{
|
{
|
||||||
int no = 0;
|
int no = 0;
|
||||||
stDlistNode *pNode = dlist->head;
|
stDlistNode *pNode = dlist->head;
|
||||||
while(pNode != NULL)
|
while(pNode != NULL)
|
||||||
{
|
{
|
||||||
printf("\r\n [%d] = %d",no++,pNode->data);
|
printf("\r\n [%d] = %d",no++,pNode->data);
|
||||||
pNode = pNode->next;
|
pNode = pNode->next; //将pNode的下一个节点赋值给pNode,推进循环
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Lru_dlist(stDlistHead *dlist,int data)
|
void Lru_dlist(stDlistHead *dlist,int data) //LRU(最近最少使用)缓存淘汰算法
|
||||||
{
|
{
|
||||||
stDlistNode *pNode = NULL;
|
stDlistNode *pNode = NULL;
|
||||||
|
|
||||||
pNode = dlist_search(dlist,data);
|
pNode = dlist_search(dlist,data);
|
||||||
if (pNode != NULL)
|
if (pNode != NULL) //如果在链表中找到这个值,则删除储存这个值的节点,之后吧这个节点放在头部
|
||||||
{
|
{
|
||||||
dlist_remove_node(dlist,pNode);
|
dlist_remove_node(dlist,pNode);
|
||||||
}
|
}
|
||||||
else if(dlist->size >= 4)
|
else if(dlist->size >= 4) //没在链表中找到,且链表长度大于4,则从链表中删除尾部节点,将新数据放在头部
|
||||||
{
|
{
|
||||||
pNode = dlist_remove_tail(dlist);
|
pNode = dlist_remove_tail(dlist);
|
||||||
|
|
||||||
|
@ -7,17 +7,17 @@
|
|||||||
************************************************************************/
|
************************************************************************/
|
||||||
#include<stdio.h>
|
#include<stdio.h>
|
||||||
|
|
||||||
typedef struct DlistNode
|
typedef struct DlistNode //双向链表中每一个节点
|
||||||
{
|
{
|
||||||
struct DlistNode *prev;
|
struct DlistNode *prev; //节点前项指针
|
||||||
struct DlistNode *next;
|
struct DlistNode *next; //节点后项指针
|
||||||
int data;
|
int data; //数据
|
||||||
}stDlistNode;
|
}stDlistNode;
|
||||||
|
|
||||||
typedef struct Dlisthead
|
typedef struct Dlisthead //定义链表总体
|
||||||
{
|
{
|
||||||
int size;
|
int size; //链表长度
|
||||||
stDlistNode *head;
|
stDlistNode *head; //头指针
|
||||||
stDlistNode *tail;
|
stDlistNode *tail; //尾部指针
|
||||||
}stDlistHead;
|
}stDlistHead;
|
||||||
|
|
||||||
|
268
c-cpp/24_binarysearchtree/binary_search_tree.cpp
Normal file
268
c-cpp/24_binarysearchtree/binary_search_tree.cpp
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
typedef int DataType;
|
||||||
|
|
||||||
|
struct tree_node
|
||||||
|
{
|
||||||
|
DataType data;
|
||||||
|
tree_node* left=NULL;
|
||||||
|
tree_node* right=NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
class binary_search_tree{
|
||||||
|
private:
|
||||||
|
tree_node* root;
|
||||||
|
int num;
|
||||||
|
public:
|
||||||
|
binary_search_tree() :num(0)
|
||||||
|
{
|
||||||
|
root = new tree_node;
|
||||||
|
root->left = NULL;
|
||||||
|
root->right = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool find(DataType it,tree_node* root)
|
||||||
|
{
|
||||||
|
if (NULL == root)return false;
|
||||||
|
if (it == root->data) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (it > root->data)
|
||||||
|
{
|
||||||
|
return find(it, root->right);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return find(it, root->left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool find_data(DataType it)
|
||||||
|
{
|
||||||
|
return find(it, root);
|
||||||
|
/*
|
||||||
|
tree_node* p = root;
|
||||||
|
while (p != NULL)
|
||||||
|
{
|
||||||
|
if (it < p->data)p = p->left;
|
||||||
|
else if (it>p->data)p = p->right;
|
||||||
|
else return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void insert_data(DataType it)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (0==num)
|
||||||
|
{
|
||||||
|
root->data = it;
|
||||||
|
num++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tree_node* p = root;
|
||||||
|
while (p != NULL)
|
||||||
|
{
|
||||||
|
if (it < p->data)
|
||||||
|
{
|
||||||
|
if (NULL == p->left)
|
||||||
|
{
|
||||||
|
p->left = new tree_node;
|
||||||
|
p->left->data = it;
|
||||||
|
num++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p = p->left;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (NULL == p->right)
|
||||||
|
{
|
||||||
|
p->right = new tree_node;
|
||||||
|
p->right->data = it;
|
||||||
|
num++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p = p->right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void delet(DataType it)
|
||||||
|
{
|
||||||
|
if (NULL == root)return;
|
||||||
|
tree_node* p = root;
|
||||||
|
tree_node* pp = NULL;//pp记录的是p的父节点
|
||||||
|
while (p != NULL&&p->data != it)
|
||||||
|
{
|
||||||
|
pp = p;
|
||||||
|
if (it > p->data)p = p->right;
|
||||||
|
else
|
||||||
|
p = p->left;
|
||||||
|
}
|
||||||
|
if (p == NULL)return;//没有找到
|
||||||
|
//删除的节点有两个子节点
|
||||||
|
if (p->left != NULL&&p->right != NULL)
|
||||||
|
{
|
||||||
|
tree_node* minP = p->right;
|
||||||
|
tree_node* minPP = p;//记录P的父节点
|
||||||
|
while (minP->left != NULL)//寻找右子树最小节点
|
||||||
|
{
|
||||||
|
minPP = minP;
|
||||||
|
minP = minP->left;
|
||||||
|
}
|
||||||
|
p->data = minP->data;//将minP替换到p中
|
||||||
|
//将p换到叶节点上,使用叶节点方法进行删除
|
||||||
|
p = minP;
|
||||||
|
pp = minPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除节点是叶节点或者是仅有一个节点
|
||||||
|
tree_node* child;
|
||||||
|
if (p->left != NULL) child = p->left;
|
||||||
|
else if (p->right != NULL) child = p->right;
|
||||||
|
else child = NULL;
|
||||||
|
|
||||||
|
if (NULL == pp) root = child;//删除的是根节点
|
||||||
|
else if (p == pp->left)pp->left = child;
|
||||||
|
else pp->right = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataType get_max()
|
||||||
|
{
|
||||||
|
if (NULL == root)return NULL;
|
||||||
|
tree_node* tmp=root;
|
||||||
|
while (tmp->right != NULL)
|
||||||
|
{
|
||||||
|
tmp = tmp->right;
|
||||||
|
}
|
||||||
|
return tmp->data;
|
||||||
|
}
|
||||||
|
DataType get_min()
|
||||||
|
{
|
||||||
|
if (NULL == root)return NULL;
|
||||||
|
tree_node* tmp=root;
|
||||||
|
while (tmp->left != NULL)
|
||||||
|
{
|
||||||
|
tmp = tmp->left;
|
||||||
|
}
|
||||||
|
return tmp->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataType get_prenode(DataType it)
|
||||||
|
{
|
||||||
|
if (NULL == root)return NULL;
|
||||||
|
if (it == root->data) return NULL;
|
||||||
|
tree_node* p=root;
|
||||||
|
tree_node* pp=NULL;
|
||||||
|
while ((p->data != it)&&(p!=NULL))
|
||||||
|
{
|
||||||
|
pp = p;
|
||||||
|
if (p->data < it)
|
||||||
|
{
|
||||||
|
p=p->right;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = p->left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ((NULL==p)?NULL:pp->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
DataType get_postnode(DataType it)
|
||||||
|
{
|
||||||
|
if (NULL == root)return -1;
|
||||||
|
tree_node* p = root;
|
||||||
|
while ((p->data != it) && (p != NULL))
|
||||||
|
{
|
||||||
|
if (p->data < it)
|
||||||
|
{
|
||||||
|
p = p->left;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = p->right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NULL == p)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (p->left!=NULL)
|
||||||
|
{
|
||||||
|
return p->left->data;
|
||||||
|
}
|
||||||
|
else if (p->right!=-NULL)
|
||||||
|
{
|
||||||
|
return p->right->data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mid_order(tree_node* rt)
|
||||||
|
{
|
||||||
|
if (NULL == rt)return;
|
||||||
|
mid_order(rt->left);
|
||||||
|
cout << rt->data;
|
||||||
|
mid_order(rt->right);
|
||||||
|
}
|
||||||
|
void order()
|
||||||
|
{
|
||||||
|
if (NULL == root)return;
|
||||||
|
return mid_order(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_high(tree_node* rt)
|
||||||
|
{
|
||||||
|
int lhigh = 0;
|
||||||
|
int rhigh = 0;
|
||||||
|
if (NULL == rt)return 0;
|
||||||
|
lhigh = get_high(rt->left);
|
||||||
|
rhigh = get_high(rt->right);
|
||||||
|
return ((lhigh > rhigh) ? (lhigh + 1) : (rhigh + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
int high()
|
||||||
|
{
|
||||||
|
if (NULL == root) return 1;
|
||||||
|
return get_high(root);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
binary_search_tree my_tree;
|
||||||
|
|
||||||
|
my_tree.insert_data(5);
|
||||||
|
my_tree.insert_data(4);
|
||||||
|
my_tree.insert_data(6);
|
||||||
|
my_tree.insert_data(10);
|
||||||
|
my_tree.insert_data(3);
|
||||||
|
my_tree.insert_data(8);
|
||||||
|
my_tree.insert_data(1);
|
||||||
|
if (my_tree.find_data(3))
|
||||||
|
{
|
||||||
|
cout << "找到了数字3" << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout << "没有找到数字3" << endl;
|
||||||
|
}
|
||||||
|
my_tree.delet(4);
|
||||||
|
cout << "Max" << my_tree.get_max() << endl;
|
||||||
|
cout << "Min" << my_tree.get_min() << endl;
|
||||||
|
cout << "pre node of 5 is " <<my_tree.get_prenode(5) <<endl;
|
||||||
|
cout << "post node of 5 is " << my_tree.get_postnode(5) << endl;
|
||||||
|
my_tree.order();
|
||||||
|
cout << "high of tree is " << my_tree.high() << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
148
go/20_lru/lru_cache.go
Normal file
148
go/20_lru/lru_cache.go
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
package lru_cache
|
||||||
|
|
||||||
|
const (
|
||||||
|
hostbit = uint64(^uint(0)) == ^uint64(0)
|
||||||
|
LENGTH = 100
|
||||||
|
)
|
||||||
|
|
||||||
|
type lruNode struct {
|
||||||
|
prev *lruNode
|
||||||
|
next *lruNode
|
||||||
|
|
||||||
|
key int // lru key
|
||||||
|
value int // lru value
|
||||||
|
|
||||||
|
hnext *lruNode // 拉链
|
||||||
|
}
|
||||||
|
|
||||||
|
type LRUCache struct {
|
||||||
|
node []lruNode // hash list
|
||||||
|
|
||||||
|
head *lruNode // lru head node
|
||||||
|
tail *lruNode // lru tail node
|
||||||
|
|
||||||
|
capacity int //
|
||||||
|
used int //
|
||||||
|
}
|
||||||
|
|
||||||
|
func Constructor(capacity int) LRUCache {
|
||||||
|
return LRUCache{
|
||||||
|
node: make([]lruNode, LENGTH),
|
||||||
|
head: nil,
|
||||||
|
tail: nil,
|
||||||
|
capacity: capacity,
|
||||||
|
used: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *LRUCache) Get(key int) int {
|
||||||
|
if this.tail == nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if tmp := this.searchNode(key); tmp != nil {
|
||||||
|
this.moveToTail(tmp)
|
||||||
|
return tmp.value
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *LRUCache) Put(key int, value int) {
|
||||||
|
// 1. 首次插入数据
|
||||||
|
// 2. 插入数据不在 LRU 中
|
||||||
|
// 3. 插入数据在 LRU 中
|
||||||
|
// 4. 插入数据不在 LRU 中, 并且 LRU 已满
|
||||||
|
|
||||||
|
if tmp := this.searchNode(key); tmp != nil {
|
||||||
|
tmp.value = value
|
||||||
|
this.moveToTail(tmp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.addNode(key, value)
|
||||||
|
|
||||||
|
if this.used > this.capacity {
|
||||||
|
this.delNode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *LRUCache) addNode(key int, value int) {
|
||||||
|
newNode := &lruNode{
|
||||||
|
key: key,
|
||||||
|
value: value,
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp := &this.node[hash(key)]
|
||||||
|
newNode.hnext = tmp.hnext
|
||||||
|
tmp.hnext = newNode
|
||||||
|
this.used++
|
||||||
|
|
||||||
|
if this.tail == nil {
|
||||||
|
this.tail, this.head = newNode, newNode
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.tail.next = newNode
|
||||||
|
newNode.prev = this.tail
|
||||||
|
this.tail = newNode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *LRUCache) delNode() {
|
||||||
|
if this.head == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
prev := &this.node[hash(this.head.key)]
|
||||||
|
tmp := prev.hnext
|
||||||
|
|
||||||
|
for tmp != nil && tmp.key != this.head.key {
|
||||||
|
prev = tmp
|
||||||
|
tmp = tmp.hnext
|
||||||
|
}
|
||||||
|
if tmp == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
prev.hnext = tmp.hnext
|
||||||
|
this.head = this.head.next
|
||||||
|
this.head.prev = nil
|
||||||
|
this.used--
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *LRUCache) searchNode(key int) *lruNode {
|
||||||
|
if this.tail == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找
|
||||||
|
tmp := this.node[hash(key)].hnext
|
||||||
|
for tmp != nil {
|
||||||
|
if tmp.key == key {
|
||||||
|
return tmp
|
||||||
|
}
|
||||||
|
tmp = tmp.hnext
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *LRUCache) moveToTail(node *lruNode) {
|
||||||
|
if this.tail == node {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if this.head == node {
|
||||||
|
this.head = node.next
|
||||||
|
this.head.prev = nil
|
||||||
|
} else {
|
||||||
|
node.next.prev = node.prev
|
||||||
|
node.prev.next = node.next
|
||||||
|
}
|
||||||
|
|
||||||
|
node.next = nil
|
||||||
|
this.tail.next = node
|
||||||
|
node.prev = this.tail
|
||||||
|
|
||||||
|
this.tail = node
|
||||||
|
}
|
||||||
|
|
||||||
|
func hash(key int) int {
|
||||||
|
if hostbit {
|
||||||
|
return (key ^ (key >> 32)) & (LENGTH - 1)
|
||||||
|
}
|
||||||
|
return (key ^ (key >> 16)) & (LENGTH - 1)
|
||||||
|
}
|
67
go/20_lru/lru_cache_test.go
Normal file
67
go/20_lru/lru_cache_test.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package lru_cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Hostbit(t *testing.T) {
|
||||||
|
fmt.Println(hostbit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_LRU(t *testing.T) {
|
||||||
|
lru := Constructor(2)
|
||||||
|
|
||||||
|
lru.Put(1, 1)
|
||||||
|
lru.Put(2, 2)
|
||||||
|
assert.Equal(t, lru.Get(1), 1) // returns 1
|
||||||
|
lru.Put(3, 3) // evicts key 2
|
||||||
|
assert.Equal(t, lru.Get(2), -1) // returns -1 (not found)
|
||||||
|
lru.Put(4, 4) // evicts key 1
|
||||||
|
assert.Equal(t, lru.Get(1), -1) // returns -1 (not found)
|
||||||
|
assert.Equal(t, lru.Get(3), 3) // returns 3
|
||||||
|
assert.Equal(t, lru.Get(4), 4) // returns 4
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_LRU_PutGet(t *testing.T) {
|
||||||
|
lru := Constructor(1)
|
||||||
|
|
||||||
|
lru.Put(1, 2)
|
||||||
|
assert.Equal(t, lru.Get(1), 2) // returns 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_LRU_PutGetPutGetGet(t *testing.T) {
|
||||||
|
lru := Constructor(1)
|
||||||
|
|
||||||
|
lru.Put(2, 1)
|
||||||
|
assert.Equal(t, lru.Get(2), 1) // returns 1
|
||||||
|
lru.Put(3, 2)
|
||||||
|
assert.Equal(t, lru.Get(2), -1) // returns -1
|
||||||
|
assert.Equal(t, lru.Get(3), 2) // returns 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_LRU_PPGPPG(t *testing.T) {
|
||||||
|
lru := Constructor(2)
|
||||||
|
|
||||||
|
lru.Put(2, 1)
|
||||||
|
lru.Put(2, 2)
|
||||||
|
assert.Equal(t, lru.Get(2), 2) // returns 2
|
||||||
|
lru.Put(1, 4)
|
||||||
|
lru.Put(4, 1)
|
||||||
|
assert.Equal(t, lru.Get(2), -1) // returns -1
|
||||||
|
assert.Equal(t, lru.Get(3), -1) // returns -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_LRU_PPGPPG_2(t *testing.T) {
|
||||||
|
lru := Constructor(2)
|
||||||
|
|
||||||
|
lru.Put(2, 1)
|
||||||
|
lru.Put(2, 2)
|
||||||
|
assert.Equal(t, lru.Get(2), 2) // returns 2
|
||||||
|
lru.Put(1, 1)
|
||||||
|
lru.Put(4, 1)
|
||||||
|
assert.Equal(t, lru.Get(2), -1) // returns -1
|
||||||
|
assert.Equal(t, lru.Get(3), -1) // returns -1
|
||||||
|
}
|
51
java/12_sorts/KthSmallest.java
Normal file
51
java/12_sorts/KthSmallest.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package sort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author wangjunwei87
|
||||||
|
* @since 2019-03-10
|
||||||
|
*/
|
||||||
|
public class KthSmallest {
|
||||||
|
|
||||||
|
public static int kthSmallest(int[] arr, int k) {
|
||||||
|
if (arr == null || arr.length < k) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int partition = partition(arr, 0, arr.length - 1);
|
||||||
|
while (partition + 1 != k) {
|
||||||
|
if (partition + 1 < k) {
|
||||||
|
partition = partition(arr, partition + 1, arr.length - 1);
|
||||||
|
} else {
|
||||||
|
partition = partition(arr, 0, partition - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr[partition];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int partition(int[] arr, int p, int r) {
|
||||||
|
int pivot = arr[r];
|
||||||
|
|
||||||
|
int i = p;
|
||||||
|
for (int j = p; j <= r - 1; j++) {
|
||||||
|
if (arr[j] < pivot) {
|
||||||
|
swap(arr, i, j);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swap(arr, i, r);
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void swap(int[] arr, int i, int j) {
|
||||||
|
if (i == j) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tmp = arr[i];
|
||||||
|
arr[i] = arr[j];
|
||||||
|
arr[j] = tmp;
|
||||||
|
}
|
||||||
|
}
|
54
javascript/42_dynamic_programming/levenshtein_distance.js
Normal file
54
javascript/42_dynamic_programming/levenshtein_distance.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
function lsDist(str1, str2) {
|
||||||
|
var n = str1.length;
|
||||||
|
var m = str2.length;
|
||||||
|
|
||||||
|
var memo = new Array(n);
|
||||||
|
for(let i = 0; i < n; i++) {
|
||||||
|
memo[i] = new Array(m);
|
||||||
|
if (str1[i] === str2[0]) {
|
||||||
|
memo[i][0] = i - 0;
|
||||||
|
} else if(i === 0) {
|
||||||
|
memo[i][0] = 1;
|
||||||
|
} else {
|
||||||
|
memo[i][0] = memo[i - 1][0] + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let j = 0; j < m; j++) {
|
||||||
|
if(str1[0] === str2[j]) {
|
||||||
|
memo[0][j] = j - 0;
|
||||||
|
} else if(j === 0) {
|
||||||
|
memo[0][j] = 1;
|
||||||
|
} else {
|
||||||
|
memo[0][j] = memo[0][j - 1] + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let i = 1; i < n; i++) {
|
||||||
|
for(let j = 1; j < m; j++) {
|
||||||
|
if(str1[i] === str2[j]) {
|
||||||
|
memo[i][j] = Math.min(memo[i - 1][j] + 1, memo[i][j - 1] + 1, memo[i - 1][j - 1 ]);
|
||||||
|
} else {
|
||||||
|
memo[i][j] = Math.min(memo[i - 1][j] + 1, memo[i][j - 1] + 1, memo[i - 1][j - 1 ] + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(memo);
|
||||||
|
|
||||||
|
return memo[n - 1][m - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var s = "mitcmu";
|
||||||
|
var t = "mtacnu";
|
||||||
|
|
||||||
|
console.log( lsDist(s, t) );
|
||||||
|
|
||||||
|
var s = "kitten";
|
||||||
|
var t = "sitting";
|
||||||
|
|
||||||
|
console.log( lsDist(s, t) );
|
||||||
|
|
||||||
|
var s = "flaw";
|
||||||
|
var t = "lawn";
|
||||||
|
console.log( lsDist(s, t) );
|
@ -86,7 +86,11 @@ function squareRoot($number)
|
|||||||
function getDecimalPlaces($number)
|
function getDecimalPlaces($number)
|
||||||
{
|
{
|
||||||
$temp = explode('.', $number);
|
$temp = explode('.', $number);
|
||||||
|
if (isset($temp[1])) {
|
||||||
return strlen($temp[1]);
|
return strlen($temp[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试二分查找给定值
|
// 测试二分查找给定值
|
||||||
|
152
php/24_tree/Tree.php
Normal file
152
php/24_tree/Tree.php
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Algo_24;
|
||||||
|
|
||||||
|
class Tree
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 树的根节点
|
||||||
|
* @var [type]
|
||||||
|
*/
|
||||||
|
public $head = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [__construct description]
|
||||||
|
* @param TreeNode|null $head [description]
|
||||||
|
*/
|
||||||
|
public function __construct($headData = null)
|
||||||
|
{
|
||||||
|
if ($headData != null) {
|
||||||
|
$this->head = new TreeNode($headData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找数据
|
||||||
|
* @param [type] $data [数据]
|
||||||
|
* @return [type] [description]
|
||||||
|
*/
|
||||||
|
public function find($data)
|
||||||
|
{
|
||||||
|
if ($this->head == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$node = $this->head;
|
||||||
|
|
||||||
|
while ($node != null) {
|
||||||
|
if ($node->data == $data) {
|
||||||
|
return $node;
|
||||||
|
} elseif ($data > $node->data) {
|
||||||
|
$node = $node->right;
|
||||||
|
} else {
|
||||||
|
$node = $node->left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入数据
|
||||||
|
* @param [type] $data [数据]
|
||||||
|
* @return [type] [description]
|
||||||
|
*/
|
||||||
|
public function insert($data)
|
||||||
|
{
|
||||||
|
if ($this->head == null) {
|
||||||
|
$this->head = new TreeNode($data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$node = $this->head;
|
||||||
|
|
||||||
|
while ($node != null) {
|
||||||
|
if ($data > $node->data) {
|
||||||
|
if ($node->right == null) {
|
||||||
|
$node->right = new TreeNode($data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$node = $node->right;
|
||||||
|
} else {
|
||||||
|
if ($node->left == null) {
|
||||||
|
$node->left = new TreeNode($data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$node = $node->left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除节点
|
||||||
|
* @param [type] $data [节点]
|
||||||
|
* @return [type] [description]
|
||||||
|
*/
|
||||||
|
public function delete($data)
|
||||||
|
{
|
||||||
|
// 找到需要删除节点
|
||||||
|
$node = $this->head;
|
||||||
|
$pnode = null;
|
||||||
|
while ($node != null) {
|
||||||
|
if ($node->data == $data) {
|
||||||
|
break;
|
||||||
|
} elseif ($data > $node->data) {
|
||||||
|
$pnode = $node;
|
||||||
|
$node = $node->right;
|
||||||
|
} else {
|
||||||
|
$pnode = $node;
|
||||||
|
$node = $node->left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($node == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 要删除的节点有两个子节点
|
||||||
|
// 查找右子树中最小节点
|
||||||
|
if ($node->left != null && $node->right != null) {
|
||||||
|
$minPP = $node;
|
||||||
|
$minP = $node->right;
|
||||||
|
while ($minP->left != null) {
|
||||||
|
$minPP = $minP;
|
||||||
|
$minP = $minP->left;
|
||||||
|
}
|
||||||
|
$node->data = $minP->data;
|
||||||
|
$node = $minP;
|
||||||
|
// 删除掉右子树中的最小节点
|
||||||
|
$minPP->left = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($node->left != null) {
|
||||||
|
$child = $node->left;
|
||||||
|
} elseif ($node->right != null) {
|
||||||
|
$child = $node->right;
|
||||||
|
} else {
|
||||||
|
$child = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($pnode == null) {
|
||||||
|
// 删除的是根节点
|
||||||
|
$node = $child;
|
||||||
|
} elseif ($pnode->left == $node) {
|
||||||
|
$pnode->left = $child;
|
||||||
|
} else {
|
||||||
|
$pnode->right = $child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前序遍历
|
||||||
|
* @return [type] [description]
|
||||||
|
*/
|
||||||
|
public function preOrder($node)
|
||||||
|
{
|
||||||
|
if ($node == null) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
echo $node->data . '->';
|
||||||
|
$this->preOrder($node->left);
|
||||||
|
$this->preOrder($node->right);
|
||||||
|
}
|
||||||
|
}
|
36
php/24_tree/TreeNode.php
Normal file
36
php/24_tree/TreeNode.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Algo_24;
|
||||||
|
|
||||||
|
class TreeNode
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点中的数据
|
||||||
|
* @var [type]
|
||||||
|
*/
|
||||||
|
public $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 左节点
|
||||||
|
* @var [type]
|
||||||
|
*/
|
||||||
|
public $left;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 右节点
|
||||||
|
* @var [type]
|
||||||
|
*/
|
||||||
|
public $right;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [__construct description]
|
||||||
|
* @param [type] $data [description]
|
||||||
|
*/
|
||||||
|
public function __construct($data = null)
|
||||||
|
{
|
||||||
|
$this->data = $data;
|
||||||
|
$this->left = null;
|
||||||
|
$this->right = null;
|
||||||
|
}
|
||||||
|
}
|
25
php/24_tree/main.php
Normal file
25
php/24_tree/main.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Algo_24;
|
||||||
|
|
||||||
|
require_once '../vendor/autoload.php';
|
||||||
|
|
||||||
|
|
||||||
|
$tree = new Tree();
|
||||||
|
|
||||||
|
$tree->insert(20);
|
||||||
|
$tree->insert(30);
|
||||||
|
$tree->insert(10);
|
||||||
|
$tree->insert(21);
|
||||||
|
$tree->insert(22);
|
||||||
|
|
||||||
|
$tree->preOrder($tree->head);
|
||||||
|
echo PHP_EOL;
|
||||||
|
|
||||||
|
var_dump($tree->find(30));
|
||||||
|
echo PHP_EOL;
|
||||||
|
|
||||||
|
|
||||||
|
$tree->delete(30);
|
||||||
|
$tree->preOrder($tree->head);
|
||||||
|
echo PHP_EOL;
|
@ -8,7 +8,8 @@
|
|||||||
"Algo_06\\": "06_linkedlist/",
|
"Algo_06\\": "06_linkedlist/",
|
||||||
"Algo_07\\": "07_linkedlist/",
|
"Algo_07\\": "07_linkedlist/",
|
||||||
"Algo_08\\": "08_stack/",
|
"Algo_08\\": "08_stack/",
|
||||||
"Algo_09\\": "09_queue/"
|
"Algo_09\\": "09_queue/",
|
||||||
|
"Algo_24\\": "24_tree/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ class SinglyLinkedList:
|
|||||||
current = current._next
|
current = current._next
|
||||||
if not current: # node not in the list
|
if not current: # node not in the list
|
||||||
return
|
return
|
||||||
current._next = None
|
current._next = node._next
|
||||||
|
|
||||||
def delete_by_value(self, value: int):
|
def delete_by_value(self, value: int):
|
||||||
if not self._head or not value:
|
if not self._head or not value:
|
||||||
|
@ -21,11 +21,7 @@ class ArrayQueue:
|
|||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
for i in range(0, self._tail - self._head):
|
for i in range(0, self._tail - self._head):
|
||||||
<<<<<<< HEAD
|
|
||||||
self._data[i] = self._items[i + self._head]
|
|
||||||
=======
|
|
||||||
self._items[i] = self._items[i + self._head]
|
self._items[i] = self._items[i + self._head]
|
||||||
>>>>>>> upstream/master
|
|
||||||
self._tail = self._tail - self._head
|
self._tail = self._tail - self._head
|
||||||
self._head = 0
|
self._head = 0
|
||||||
|
|
||||||
@ -38,6 +34,8 @@ class ArrayQueue:
|
|||||||
item = self._items[self._head]
|
item = self._items[self._head]
|
||||||
self._head += 1
|
self._head += 1
|
||||||
return item
|
return item
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return " ".join(item for item in self._items[self._head : self._tail])
|
return " ".join(item for item in self._items[self._head : self._tail])
|
||||||
|
22
python/15_bsearch/bsearch_recursion.py
Normal file
22
python/15_bsearch/bsearch_recursion.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
"""
|
||||||
|
Author: dreamkong
|
||||||
|
"""
|
||||||
|
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
def bsearch(nums: List[int], target: int) -> int:
|
||||||
|
return bsearch_internally(nums, 0, len(nums)-1, target)
|
||||||
|
|
||||||
|
|
||||||
|
def bsearch_internally(nums: List[int], low: int, high: int, target: int) -> int:
|
||||||
|
if low > high:
|
||||||
|
return -1
|
||||||
|
|
||||||
|
mid = low+int((high-low) >> 2)
|
||||||
|
if nums[mid] == target:
|
||||||
|
return mid
|
||||||
|
elif nums[mid] < target:
|
||||||
|
return bsearch_internally(nums, mid+1, high, target)
|
||||||
|
else:
|
||||||
|
return bsearch_internally(nums, low, mid-1, target)
|
@ -4,13 +4,29 @@
|
|||||||
|
|
||||||
def levenshtein_dp(s: str, t: str) -> int:
|
def levenshtein_dp(s: str, t: str) -> int:
|
||||||
m, n = len(s), len(t)
|
m, n = len(s), len(t)
|
||||||
table = [[0] * (n + 1) for _ in range(m + 1)]
|
table = [[0] * (n) for _ in range(m)]
|
||||||
table[0] = [j for j in range(m + 1)]
|
|
||||||
for i in range(m + 1):
|
for i in range(n):
|
||||||
table[i][0] = i
|
if s[0] == t[i]:
|
||||||
for i in range(1, m + 1):
|
table[0][i] = i - 0
|
||||||
for j in range(1, n + 1):
|
elif i != 0:
|
||||||
table[i][j] = min(1 + table[i - 1][j], 1 + table[i][j - 1], int(s[i - 1] != t[j - 1]) + table[i - 1][j - 1])
|
table[0][i] = table[0][i - 1] + 1
|
||||||
|
else:
|
||||||
|
table[0][i] = 1
|
||||||
|
|
||||||
|
for i in range(m):
|
||||||
|
if s[i] == t[0]:
|
||||||
|
table[i][0] = i - 0
|
||||||
|
elif i != 0:
|
||||||
|
table[i][0] = table[i - 1][0] + 1
|
||||||
|
else:
|
||||||
|
table[i][0] = 1
|
||||||
|
|
||||||
|
for i in range(1, m):
|
||||||
|
for j in range(1, n):
|
||||||
|
table[i][j] = min(1 + table[i - 1][j], 1 + table[i][j - 1], int(s[i] != t[j]) + table[i - 1][j - 1])
|
||||||
|
|
||||||
|
print(table)
|
||||||
return table[-1][-1]
|
return table[-1][-1]
|
||||||
|
|
||||||
|
|
||||||
@ -29,3 +45,15 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
print(levenshtein_dp(s, t))
|
print(levenshtein_dp(s, t))
|
||||||
print(common_substring_dp(s, t))
|
print(common_substring_dp(s, t))
|
||||||
|
|
||||||
|
s = "kitten"
|
||||||
|
t = "sitting"
|
||||||
|
|
||||||
|
print(levenshtein_dp(s, t))
|
||||||
|
print(common_substring_dp(s, t))
|
||||||
|
|
||||||
|
s = "flaw"
|
||||||
|
t = "lawn"
|
||||||
|
|
||||||
|
print(levenshtein_dp(s, t))
|
||||||
|
print(common_substring_dp(s, t))
|
@ -14,8 +14,10 @@ struct StackBasedOnLinkedList<Element>: Stack {
|
|||||||
|
|
||||||
var size: Int {
|
var size: Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
while head.next != nil {
|
var cur = head.next
|
||||||
|
while cur != nil {
|
||||||
count += 1
|
count += 1
|
||||||
|
cur = cur?.next
|
||||||
}
|
}
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user