Merge github.com:wangzheng0822/algo

This commit is contained in:
Smallfly 2018-12-11 12:26:52 +08:00
commit f594e28af7
126 changed files with 11786 additions and 469 deletions

View File

@ -6,7 +6,7 @@ using namespace std;
class CElement;
/***
* @brief
* @brief
*/
class CSingleList
{
@ -15,61 +15,61 @@ public:
~CSingleList();
/**
* @brief ..
* @return ,
* @brief ..
* @return ,
*/
CElement* Insert(void* lpData, int iDataSize);
/**
* @brief ..
* @return ,
* @brief ..
* @return ,
*/
CElement* Insert(CElement* lpElement, void* lpData, int iDataSize);
/**
* @brief
* @brief
*/
void Delete(CElement*);
/**
* @brief
* @brief
*/
CElement* Begin();
/**
* @brief
* @brief
*/
CElement* Next();
/***
* @brief
* @brief
*/
CElement* End();
/**
* @brief
* @return TRUEFALSE
* @brief
* @return TRUEFALSE
*/
bool Empty();
/**
* @brief
* @brief
*/
void Reverse();
/**
* @brief
* @return TRUE时表示链表存在环,.
* @brief
* @return TRUE时表示链表存在环,.
*/
bool CheckCircle();
/**
* @brief 2
* @brief 2
*/
void Merge(CSingleList& lst, std::function<int(void* t1, void* t2)>);
/**
* @brief K个结点
* @brief K个结点
*/
void DeleteLastKth(int k);
/**
* @brief
* @brief
*/
CElement* Center();
private:
@ -80,18 +80,18 @@ private:
CSingleList(CSingleList const & rhs);
CSingleList& operator= (CSingleList const& rhs);
private:
/**头结点*/
/**头结点*/
CElement* m_lpHead;
/**哨兵*/
/**哨兵*/
CElement* m_lpSentinel;
/**空结点用于End()返回 */
/**空结点用于End()返回 */
CElement* m_lpNull;
/**当前结点. 枚举时使用. */
/**当前结点. 枚举时使用. */
CElement* m_lpCur;
};
/***
* @brief .
* @brief .
*/
class CElement
{
@ -101,11 +101,11 @@ protected:
~CElement();
public:
/***
* @brief
* @brief
*/
void* GetDataPtr();
protected:
/**下一个结点*/
/**下一个结点*/
CElement* m_lpNext;
void* m_lpData;
};
@ -113,7 +113,7 @@ protected:
void CreateList(CSingleList& lst)
{
//循环插入元素到链表尾
//循环插入元素到链表尾
for(int i=1; i<10;i++)
{
int* p = new int();
@ -134,15 +134,15 @@ void PrintList(CSingleList& lst)
int main()
{
{
/// 链表的基本操作,插入/枚举/删除
/// 链表的基本操作,插入/枚举/删除
CSingleList lst;
CElement* lpElement = NULL;
CreateList(lst);
std::cout<<"枚举链表当前的元素"<<std::endl;
std::cout<<"枚举链表当前的元素"<<std::endl;
PrintList(lst);
std::cout<<"查找指定元素,并在指定元素后面插入新元素"<<std::endl;
std::cout<<"查找指定元素,并在指定元素后面插入新元素"<<std::endl;
lpElement = lst.Begin();
while(lpElement != lst.End())
{
@ -157,10 +157,10 @@ int main()
}
}
std::cout<<"枚举链表当前的元素"<<std::endl;
std::cout<<"枚举链表当前的元素"<<std::endl;
PrintList(lst);
std::cout<<"查找指定元素(数字是7的元素),并删除指定元素"<<std::endl;
std::cout<<"查找指定元素(数字是7的元素),并删除指定元素"<<std::endl;
lpElement = lst.Begin();
while(lpElement != lst.End())
{
@ -172,52 +172,52 @@ int main()
lpElement = lst.Next();
}
}
std::cout<<"枚举链表当前的元素"<<std::endl;
std::cout<<"枚举链表当前的元素"<<std::endl;
PrintList(lst);
}
std::cout<<"--------------------------"<<std::endl;
{
/// 链表的反转
/// 链表的反转
CSingleList lst;
CElement* lpElement = NULL;
CreateList(lst);
std::cout<<"反转"<<std::endl;
std::cout<<"反转"<<std::endl;
lst.Reverse();
PrintList(lst);
}
std::cout<<"--------------------------"<<std::endl;
{
/// 检测环
/// 检测环
CSingleList lst;
CElement* lpElement = NULL;
CreateList(lst);
std::cout<<"检测环"<<std::endl;
std::cout<<"检测环"<<std::endl;
bool bRet = lst.CheckCircle();
if(bRet){
std::cout<<"存在环."<<std::endl;
std::cout<<"存在环."<<std::endl;
}else{
std::cout<<"不存在环."<<std::endl;
std::cout<<"不存在环."<<std::endl;
}
}
std::cout<<"--------------------------"<<std::endl;
{
/// 有序链表合并
/// 有序链表合并
CSingleList lst,lst2;
CElement* lpElement = NULL;
for(int i=1; i<10;i++)
for(int i=1; i<30;i++)
{
int* p = new int();
*p = i;
if(i%2){
if(i%4){
lst2.Insert(p, 4);
}else{
lst.Insert(p, 4);
}
}
std::cout<<"枚举链表当前的元素"<<std::endl;
std::cout<<"枚举链表当前的元素"<<std::endl;
PrintList(lst);
std::cout<<"......"<<std::endl;
PrintList(lst2);
@ -231,31 +231,31 @@ int main()
}
return 0;
});
std::cout<<"合并之后,打印当前链表."<<std::endl;
std::cout<<"合并之后,打印当前链表."<<std::endl;
PrintList(lst);
}
std::cout<<"--------------------------"<<std::endl;
{
/// 删除倒数第K个结点,并查看中间节点
/// 删除倒数第K个结点,并查看中间节点
CSingleList lst;
CreateList(lst);
std::cout<<"删除倒数第0个结点"<<std::endl;
std::cout<<"删除倒数第0个结点"<<std::endl;
lst.DeleteLastKth(0);
PrintList(lst);
CElement* lpCenter = lst.Center();
std::cout<<"中间节点:"<<*((int*)lpCenter->GetDataPtr())<<std::endl;
std::cout<<"中间节点:"<<*((int*)lpCenter->GetDataPtr())<<std::endl;
std::cout<<"删除倒数第1个结点"<<std::endl;
std::cout<<"删除倒数第1个结点"<<std::endl;
lst.DeleteLastKth(1);
PrintList(lst);
lpCenter = lst.Center();
std::cout<<"中间节点:"<<*((int*)lpCenter->GetDataPtr())<<std::endl;
std::cout<<"中间节点:"<<*((int*)lpCenter->GetDataPtr())<<std::endl;
std::cout<<"删除倒数第3个结点"<<std::endl;
std::cout<<"删除倒数第3个结点"<<std::endl;
lst.DeleteLastKth(3);
PrintList(lst);
lpCenter = lst.Center();
std::cout<<"中间节点:"<<*((int*)lpCenter->GetDataPtr())<<std::endl;
std::cout<<"中间节点:"<<*((int*)lpCenter->GetDataPtr())<<std::endl;
}
std::cin.ignore();
@ -316,10 +316,10 @@ CElement* CSingleList::Insert(CElement* lpElement, void* lpData, int iDataSize)
}
void CSingleList::Insert(CElement* lpNewElement, CElement* lpCurElement, bool bBack /*= true*/)
{
if(bBack){//插入到指定元素的后面
if(bBack){//插入到指定元素的后面
lpNewElement->m_lpNext = lpCurElement->m_lpNext;
lpCurElement->m_lpNext = lpNewElement;
}else{//插入到指定元素的前面
}else{//插入到指定元素的前面
CElement* lpIter = m_lpSentinel;
while(NULL != lpIter)
{
@ -443,11 +443,13 @@ bool CSingleList::CheckCircle()
return false;
}
/**
* 2
*/
void CSingleList::Merge(CSingleList& lst, std::function<int(void* t1, void* t2)> fnCompare)
{
CElement* lpL1 = Begin();
CElement* lpL2 = lst.Begin();
CElement* lpTail = NULL;
if(!fnCompare)
{
@ -458,7 +460,26 @@ void CSingleList::Merge(CSingleList& lst, std::function<int(void* t1, void* t2)>
{
if(lpL1 != End())
{
/**
*
*
* 1,2; 1 <- 2, 21
*
* 1212
* 1[A]2[A];
* 11
*/
iRet = fnCompare(lpL1->GetDataPtr(), lpL2->GetDataPtr());
if(iRet < 0){
lpL1 = Next();
while(lpL1 != End()){
iRet = fnCompare(lpL1->GetDataPtr(), lpL2->GetDataPtr());
if(iRet > 0){
break;
}
lpL1 = Next();
}
}
}else{
iRet = -1;
}
@ -468,17 +489,13 @@ void CSingleList::Merge(CSingleList& lst, std::function<int(void* t1, void* t2)>
lpNewElement->m_lpData = lpL2->GetDataPtr();
if(lpL1 != End())
{
Insert(lpNewElement,lpL1, iRet <= 0);
Insert(lpNewElement,lpL1, iRet < 0);
}else{
if(NULL == lpTail)
{
lpTail = Tail();
}
CElement* lpTail = Tail();
Insert(lpNewElement,lpTail);
}
}
lpL2 = lst.Next();
lpL1 = Next();
}
}

View File

@ -0,0 +1,139 @@
/*************************************************************************
> File Name: lisklist.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-07
> Desc:
************************************************************************/
#include<stdio.h>
struct stlistNode
{
int val;
struct listNode *next;
}listNode;
/*反转链表*/
listNode reverseList(listNode *head)
{
listNode *prev = NULL;
listNode *next = NULL;
while(head != NULL)
{
next = head->next;
head->next = prev;
prev = head;
head = next;
}
return prev;
}
/*判断链表是否有环*/
int hasCycle(listNode *head)
{
listNode * fast = head;
listNode * low = head;
while(fast != NULL && fast->next != NULL)
{
low = low->next;
fast = fast->next->next;
if (low == fast)
{
return 1;
}
}
return 0;
}
/*合并有序链表*/
listNode *mergeTwoLists(listNode *l1,listNode *l2)
{
listNode head = {0};
listNode *pRes = &head;
while(1)
{
if(l1 == NULL)
{
pRes->next = l2;
}
if (l2 == NULL)
{
pRes->next = l1;
}
if(l1->val < l2->val)
{
pRes->next = l1;
l1 = l1->next;
}
else
{
pRes->next = l2;
l2 = l2->next;
}
pRes = pRes->next;
}
return head;
}
/*
*n个节点 */
listNode * removeNthFromEnd(listNode*headi,int n)
{
listNode *fast = head;
listNode *prev = NULL;
listNpde *next = head;
int k = n;
/*快指针往后移动k-1*/
while((k > 1) && (fast != NULL))
{
fast = fast->next;
k--;
}
/*说明链表数目不足n个*/
if (fast == NULL)
{
return head;
}
while (fast->next != NULL)
{
fast = fast->next;
prev = next;
next = next->next;
}
if(prev == NULL)
{
head = head->next;
}
else
{
prev->next = prev->next->next;
}
return head;
}
/*求链表的中间节点*/
listNode *middleNode(listNode *head)
{
listNode * fast = head;
listNode * low = head;
while(fast != NULL && fast->next != NULL)
{
low = low->next;
fast = fast->next->next;
}
return low;
}

View File

@ -0,0 +1,57 @@
/*************************************************************************
> File Name: one_two_step.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-19
> Desc:
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/*爬楼梯的问题,解决重复计算,采用数据保存方法*/
int helper(int n ,int *vlaue)
{
if(vlaue[n] != 0)
{
return vlaue[n];
}
vlaue[n] = helper(n - 1,vlaue) + helper(n - 2,vlaue);
return vlaue[n];
}
int climbStaris(int n)
{
int *vlaue = NULL;
int res = 0;
vlaue = (int *)malloc(sizeof(int)*(n+1));
if(vlaue == NULL)
{
return -1;
}
memset(vlaue,0,sizeof(int)*(n + 1));
vlaue[0] = 0;
vlaue[1] = 1;
vlaue[2] = 2;
res = helper(n,vlaue);
free(vlaue);
return res;
}
int main()
{
printf("\r\nnum%d ,%d",5,climbStaris(5));
printf("\r\nnum%d ,%d",6,climbStaris(6));
printf("\r\nnum%d ,%d",7,climbStaris(7));
return 0;
}

View File

@ -0,0 +1,124 @@
/*************************************************************************
> File Name: sorts_jinshaohui.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-19
> Desc:
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SWAP(a,b) \
do{\
(a) ^= (b);\
(b) ^= (a);\
(a) ^= (b);\
}while(0)
/*冒泡排序*/
void bubble_sort(int a[],int size)
{
int i = 0;
int j = 0;
int swap_flg = 0;
if (size < 1)
{
return;
}
for (i = size - 1; i > 0; i--)/*排序的趟数*/
{
swap_flg = 0;/*每次设置交换标识为0*/
for (j = 0; j < i; j++)/*本趟排序的遍历元素个数*/
{
if (a[j] > a[j + 1])
{
SWAP(a[j],a[j+1]);
swap_flg = 1;
}
}
/*本趟数,无数据交换的话,说明已经有序,直接退出*/
if (swap_flg == 0)
{
break;
}
}
return;
}
/*插入排序*/
void insert_sort(int a[],int size)
{
int i = 0;
int j = 0;
int key = 0;
for (i = 1; i < size; i ++)/*需要插入的元素个数*/
{
key = a[i];/*保存插入的元素数据*/
j = i - 1;
/* i 之前的元素都是有序的找到比key小的插入到他后面
* key大的*/
while((j >= 0) && (a[j] > key))
{
a[j + 1] = a[j];
j--;
}
a[j + 1] = key;
}
return;
}
/*选择排序*/
void select_sort(int a[],int size)
{
int i = 0;
int j = 0;
int min = 0;
for (i = 0; i < size - 1; i++)
{
min = i;
for (j = i + 1; j < size; j++)
{
if (a[j] < a[min])
{
min = j;
}
}
if (min != i)
{
SWAP(a[i],a[min]);
}
}
return;
}
void dump(int a[],int size)
{
int i = 0;
printf("\r\n");
for (i = 0; i < size; i++ )
{
printf("%d ",a[i]);
}
printf("\r\n");
return;
}
int main()
{
int a[10] = {9,11,4,15,16,3,20,44,5,10};
//bubble_sort(a,sizeof(a)/sizeof(int));
//insert_sort(a,sizeof(a)/sizeof(int));
select_sort(a,sizeof(a)/sizeof(int));
dump(a,sizeof(a)/sizeof(int));
return 0;
}

View File

@ -0,0 +1,160 @@
/*************************************************************************
> File Name: merge_sort.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-19
> Desc:
************************************************************************/
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#define SORT_MAX (1000000)
void dump(int a[],int size);
void merge_sentry(int a[],int middle,int left,int right)
{
int *pleft = NULL;
int *pright = NULL;
int i = 0;
int j = 0;
int k = 0;
int left_size = middle - left + 1;
int right_size = right - middle;
pleft = (int *)malloc(sizeof(int)*(left_size + 1));
assert(pleft != NULL);
pright = (int *)malloc(sizeof(int)*(right_size + 1));
assert(pright != NULL);
for(i = 0; i < left_size; i ++)
{
pleft[i] = a[left + i];
}
pleft[left_size] = SORT_MAX;
for(i = 0; i < right_size; i ++)
{
pright[i] = a[middle + 1 + i];
}
pright[right_size] = SORT_MAX;
for (k = left,i = 0,j = 0; k <= right; k++)
{
if (pleft[i] <= pright[j])
{
a[k] = pleft[i++];
}
else
{
a[k] = pright[j++];
}
}
free(pleft);
free(pright);
return;
}
/*两个有序数组合并*/
void merge(int a[],int middle,int left,int right)
{
int *tmp = NULL;
int i = 0;
int j = 0;
int k = 0;
tmp = (int*)malloc((right - left + 1)*sizeof(int));
assert(tmp != NULL);
i = left;
j = middle + 1;
while(1)
{
if((i > middle) || (j > right))
{
break;
}
if (a[i] > a[j])
{
tmp[k++] = a[j++];
}
else
{
tmp[k++] = a[i++];
}
}
if (i > middle)
{
while(j <= right)
{
tmp[k++] = a[j++];
}
}
else
{
while(i <= middle)
{
tmp[k++] = a[i++];
}
}
memcpy((a + left),tmp,(right - left + 1)*sizeof(int));
free(tmp);
return ;
}
void merge_sort(int a[],int left,int right)
{
int middle = 0;
if(left >= right)
{
return;
}
middle = (left + right)/2;
merge_sort(a,left,middle);
merge_sort(a,middle + 1,right);
merge_sentry(a,middle,left,right);
return;
}
void dump(int a[],int size)
{
int i = 0;
if(size == 0)
{
return;
}
printf("\r\n");
for (i = 0; i < size; i++ )
{
printf("%d ",a[i]);
}
printf("\r\n");
return;
}
int main()
{
int a[10] = {30,20,10,15,4,8,40,80,20,9};
merge_sort(a,0,9);
dump(a,10);
return 0;
}

View File

@ -0,0 +1,145 @@
/*************************************************************************
> File Name: quick_sort.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-19
> Desc:
************************************************************************/
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
/* SWAP 使用必须主要,不能是同一个数据进行交换*/
#define SWAP(a,b) \
do{\
(a) ^= (b);\
(b) ^= (a);\
(a) ^= (b);\
}while(0)
int partition2(int a[],int left,int right)
{
int i = left;
int j = left;
for(; j < right;j++)
{
if (a[j] < a[right])
{
if(i != j)
{
SWAP(a[i],a[j]);
}
i++;
}
}
if(i != right)
{
SWAP(a[i],a[right]);
}
return i;
}
int partition(int a[],int left,int right)
{
int i = left;
int j = right;
int key = a[left];
while(i < j)
{
while((i < j)&& (a[j] >= key))
{
j--;
}
if (i < j)
{
a[i] = a[j];
}
while((i < j) && a[i] <= key)
{
i++;
}
if (i<j)
{
a[j] = a[i];
}
}
a[i] = key;
return i;
}
void quick_sort(int a[],int left,int right)
{
int q = 0;
/*递归终止条件*/
if (left >= right)
{
return;
}
q = partition2(a,left,right);
quick_sort(a,left,(q - 1));
quick_sort(a,(q + 1),right);
return;
}
void dump(int a[],int size)
{
int i = 0;
printf("\r\n");
for (i = 0; i < size; i++ )
{
printf("%d ",a[i]);
}
printf("\r\n");
return;
}
int helper(int a[],int left,int right,int k)
{
int q = 0;
q = partition(a,left,right);
if (q > (k - 1))
{
return helper(a,left,q-1,k);
}
else if (q < (k - 1))
{
return helper(a,q+1,right,k);
}
return a[q];
}
/*求无序数组中从小到大第K个元素的数值*/
int findKthlagest(int a[],int size,int k)
{
return helper(a,0,size-1,k);
}
int main()
{
int a[10] = {30,20,10,15,4,8,40,80,20,9};
int k;
scanf("%d",&k);
printf("\r\n从小到大排序,第%d个元素数值是%d",k,findKthlagest(a,10,k));
quick_sort(a,0,9);
dump(a,10);
return 0;
}

View File

@ -27,7 +27,11 @@ int partition(int *arr, int p, int r)
for (; j < r; j++) {
if (arr[j] < arr[r]) {
if(i != j)
{
swap(arr + i, arr + j);
}
i++;
}
}

0
c-cpp/13_sorts/.gitkeep Normal file
View File

View File

@ -0,0 +1,43 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/26.
*/
#ifndef SORTS_BUCKET_SORT_HPP_
#define SORTS_BUCKET_SORT_HPP_
#include <iterator>
#include <functional>
#include <algorithm>
#include <vector>
template <size_t BucketSize,
typename IterT,
typename T = typename std::iterator_traits<IterT>::value_type,
typename Compare = std::less<T>>
void bucket_sort(IterT first, IterT last, Compare comp = Compare()) {
const T min = *std::min_element(first, last), max = *std::max_element(first, last);
const T range = max + 1 - min;
const size_t bucket_num = (range - 1) / BucketSize + 1;
std::vector<std::vector<T>> buckets(bucket_num);
for (auto b : buckets) {
b.reserve(2 * BucketSize);
}
for (IterT i = first; i != last; ++i) {
size_t idx = (*i - min) / BucketSize;
buckets[idx].emplace_back(*i);
}
IterT dest = first;
for (auto b : buckets) {
std::sort(b.begin(), b.end(), comp);
std::copy(b.begin(), b.end(), dest);
dest += b.size();
}
return;
}
#endif // SORTS_BUCKET_SORT_HPP_

View File

@ -0,0 +1,33 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/26.
*/
#include <iostream>
#include <vector>
#include <functional>
#include "bucket_sort.hpp"
template <size_t BucketSize,
typename Container,
typename T = typename Container::value_type,
typename Compare = std::less<T>>
void test_bucket_sort(Container cont, Compare comp = Compare()) {
bucket_sort<BucketSize>(cont.begin(), cont.end(), comp);
std::transform(cont.begin(), cont.end(), std::ostream_iterator<T>(std::cout, " "),
[](T i){ return i; });
std::cout << std::endl;
}
int main() {
std::vector<int> test{3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9};
test_bucket_sort<2>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9
test_bucket_sort<3>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9
test_bucket_sort<4>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9
test_bucket_sort<5>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9
test_bucket_sort<6>(test); // 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9
return 0;
}

View File

@ -0,0 +1,40 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/26.
*/
#ifndef SORTS_COUNTING_SORT_HPP_
#define SORTS_COUNTING_SORT_HPP_
#include <iterator>
#include <functional>
#include <algorithm>
#include <vector>
template <typename IterT,
typename T = typename std::iterator_traits<IterT>::value_type>
void counting_sort(IterT first, IterT last) {
const auto len = std::distance(first, last);
if (len < 2) { return; }
const T max = *std::max_element(first, last);
if (max == 0) { return; }
std::vector<size_t> counter(max + 1);
for (IterT i = first; i != last; ++i) {
++counter[*i];
}
for (size_t i = 1; i != max + 1; ++i) {
const size_t j = max - i;
counter[j] += counter[j + 1]; // Liam Huang: count of numbers that is not less than j.
}
std::vector<T> temp(len);
for (IterT i = first; i != last; ++i) {
temp[len - counter[*i]] = *i;
--counter[*i]; // Liam Huang: stable for relative position.
}
std::copy(temp.begin(), temp.end(), first);
}
#endif // SORTS_COUNTING_SORT_HPP_

View File

@ -0,0 +1,36 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/26.
*/
#include <iostream>
#include <vector>
#include <functional>
#include "counting_sort.hpp"
template <typename Container,
typename T = typename Container::value_type>
void test_counting_sort(Container cont) {
counting_sort(cont.begin(), cont.end());
std::transform(cont.begin(), cont.end(), std::ostream_iterator<T>(std::cout, " "),
[](T i){ return i; });
std::cout << std::endl;
}
int main() {
// Liam Huang: pi for test
const std::vector<int> test1{3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3};
const std::vector<int> test2{2, 3, 8, 4, 6, 2, 6, 4, 3, 3, 8, 3, 2, 7, 9};
const std::vector<int> test3{5, 0, 2, 8, 8, 4, 1, 9, 7, 1, 6, 9, 3, 9, 9};
const std::vector<int> test4{3, 7, 5, 1, 0, 5, 8, 2, 0, 9, 7, 4, 9, 4, 4};
const std::vector<int> test5{5, 9, 2, 3, 0, 7, 8, 1, 6, 4, 0, 6, 2, 8, 6};
test_counting_sort(test1); // 1 1 2 3 3 3 4 5 5 5 6 7 8 9 9 9
test_counting_sort(test2); // 2 2 2 3 3 3 3 4 4 6 6 7 8 8 9
test_counting_sort(test3); // 0 1 1 2 3 4 5 6 7 8 8 9 9 9 9
test_counting_sort(test4); // 0 0 1 2 3 4 4 4 5 5 7 7 8 9 9
test_counting_sort(test5); // 0 0 1 2 2 3 4 5 6 6 6 7 8 8 9
return 0;
}

268
c-cpp/13_sorts/sort.c Executable file
View File

@ -0,0 +1,268 @@
/*************************************************************************
> File Name: sort.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-20
> Desc:
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<assert.h>
void dump(int a[],int size)
{
int i = 0;
printf("\r\n");
for(i = 0; i <size; i++)
{
printf("%d ",a[i]);
}
printf("\r\n");
}
/*计数排序时间复杂度0n),非原地排序
*
* max比数组大小size大很多不适合
*
* */
void count_sort(int a[],int size)
{
int i = 0;
int max = 0;
int *count = 0;
int *res = 0;
/*找到最大数*/
for (i = 0 ; i< size; i++)
{
if (a[i] > max)
{
max = a[i];
}
}
count = (int *)malloc(sizeof(int)*(max + 1));
assert(count != NULL);
memset(count,0,sizeof(int)*(max + 1));
/*计数*/
for (i = 0; i < size;i++)
{
count[a[i]]++;
}
/*依次累加*/
for(i = 1 ;i <= max; i ++)
{
count[i] += count[i-1];
}
res = (int *)malloc(sizeof(int)*(size));
assert(res != NULL);
/*核心代码count[a[i] - 1]就是排序好的下标*/
for (i = size-1;i >= 0; i--)
{
res[count[a[i]] -1] = a[i];
count[a[i]]--;
}
memcpy(a,res,size*(sizeof(int)));
free(res);
free(count);
return;
}
int count_sort_test()
{
int a [10]={1,5,6,8,10,9,3,1,2,1};
printf("\r\n conunt sort test ....");
count_sort(a,10);
dump(a,10);
return 0;
}
#define NUM_OF_POS(a,pval) ((a)/pval)%10
void radix_sort(int a[],int size,int num_count)
{
int count[10] = {0}; /*计数*/
int *pres = NULL;
int i = 0;
int j = 0;
int pval = 10;
int index = 0;
int break_flg = 0;
pres = (int *)malloc(sizeof(int)*size);
assert(pres != NULL);
for (i = 0; i < num_count; i ++)
{
memset(count,0,sizeof(int)*10);
/*求当前的基数*/
pval = pow(10,i);
/*计数*/
for (j = 0; j < size; j++)
{
index = NUM_OF_POS(a[j],pval);
count[index]++;
}
/*小的优化可能位数最大的就1其他的位数差很多*/
if(count[0] == 9)
{
break_flg++;
}
if(break_flg >=2)
{
printf("\r\n %i",i);
break;
}
/*累加*/
for(j = 1; j < 10; j ++)
{
count[j] += count[j-1];
}
/*排序必须从后往前,否则不是稳定排序*/
for(j = size -1; j >= 0; j--)
{
index = NUM_OF_POS(a[j],pval);
pres[count[index] - 1] = a[j];
count[index]--;
}
/*本轮排序好的拷贝到a中*/
memcpy(a,pres,sizeof(int)*size);
}
return;
}
void radix_sort_test()
{
int a[10] = {123,12341,1232134,124,236,128,1112313129,98,9,8989};
printf("\r\n radix sort test.....");
radix_sort(a,10,10);
dump(a,10);
return;
}
struct barrel {
int node[10];
int count;/* the num of node */
};
int partition(int a[],int left,int right)
{
int i = left;
int j = right;
int key = a[left];
while(i < j)
{
while((i < j)&& (a[j] >= key))
{
j--;
}
if (i < j)
{
a[i] = a[j];
}
while((i < j) && a[i] <= key)
{
i++;
}
if (i<j)
{
a[j] = a[i];
}
}
a[i] = key;
return i;
}
void quick_sort(int a[],int left,int right)
{
int q = 0;
/*递归终止条件*/
if (left >= right)
{
return;
}
q = partition(a,left,right);
quick_sort(a,left,(q - 1));
quick_sort(a,(q + 1),right);
return;
}
void bucket_sort(int data[], int size)
{
int max, min, num, pos;
int i, j, k;
struct barrel *pBarrel;
max = min = data[0];
for (i = 1; i < size; i++) {
if (data[i] > max) {
max = data[i];
} else if (data[i] < min) {
min = data[i];
}
}
num = (max - min + 1) / 10 + 1;
pBarrel = (struct barrel*)malloc(sizeof(struct barrel) * num);
memset(pBarrel, 0, sizeof(struct barrel) * num);
/* put data[i] into barrel which it belong to */
for (i = 0; i < size; i++) {
k = (data[i] - min + 1) / 10;/* calculate the index of data[i] in barrel */
(pBarrel + k)->node[(pBarrel + k)->count] = data[i];
(pBarrel + k)->count++;
}
pos = 0;
for (i = 0; i < num; i++) {
if ((pBarrel + i)->count != 0)
{
quick_sort((pBarrel+i)->node, 0, ((pBarrel+i)->count)-1);/* sort node in every barrel */
for (j = 0; j < (pBarrel+i)->count; j++) {
data[pos++] = (pBarrel+i)->node[j];
}
}
}
free(pBarrel);
}
void bucket_sort_test()
{
int a[] = {78, 17, 39, 26, 72, 94, 21, 12, 23, 91};
int size = sizeof(a) / sizeof(int);
printf("\r\n bucket sort test ...");
bucket_sort(a, size);
dump(a,size);
}
int main()
{
count_sort_test();
radix_sort_test();
bucket_sort_test();
return 0;
}

View File

@ -0,0 +1,96 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef int(*bs)(int *arr, int size, int val);
int binary_search_r(int *arr, int size, int val)
{
int mid = size / 2;
int idx;
if (arr[mid] == val)
return mid;
// mid == 0 means size == 1
// so the only element in array doesn't equal to val
if (!mid)
return -1;
if (arr[mid] < val) {
idx = binary_search_r(arr + mid + 1, size - mid - 1, val);
if (idx != -1)
idx += mid + 1;
} else {
idx = binary_search_r(arr, mid, val);
}
return idx;
}
int binary_search_i(int *arr, int size, int val)
{
int low = 0, high = size - 1, mid;
while (low <= high) {
mid = (low + high) / 2;
if (arr[mid] == val)
return mid;
if (arr[mid] < val)
low = mid + 1;
else
high = mid - 1;
}
return -1;
}
void iteratioin_test(bs binary_search)
{
int arr[10] = {1, 4, 5, 9, 12, 19, 21, 28, 31, 36};
int idx;
idx = binary_search(arr, 10, 12);
if (idx != -1)
printf("find 12 at %d\n", idx);
else
printf("12 not in arr \n");
idx = binary_search(arr, 10, 13);
if (idx != -1)
printf("find 13 at %d\n", idx);
else
printf("13 not in arr \n");
idx = binary_search(arr, 10, 1);
if (idx != -1)
printf("find 1 at %d\n", idx);
else
printf("1 not in arr \n");
idx = binary_search(arr, 10, 36);
if (idx != -1)
printf("find 36 at %d\n", idx);
else
printf("36 not in arr \n");
idx = binary_search(arr, 10, 31);
if (idx != -1)
printf("find 31 at %d\n", idx);
else
printf("31 not in arr \n");
}
int main()
{
printf("=== Test iteration version:\n");
iteratioin_test(binary_search_i);
printf("=== Test recursive version:\n");
iteratioin_test(binary_search_r);
return 0;
}

View File

@ -8,19 +8,16 @@
#include <iterator>
#include <functional>
enum class BsearchPolicy { FIRST, LAST, UNSPECIFIED };
// Liam Huang: The algorithm works right with iterators that meet the ForwardIterator requirement,
// but with a bad time complexity. For better performance, iterators should meet
// the RandomAccessIterator requirement.
template <typename IterT,
typename ValueT = typename std::iterator_traits<IterT>::value_type,
typename Compare>
typename Compare = std::less<ValueT>>
IterT bsearch(IterT first,
IterT last,
ValueT target,
Compare comp,
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
Compare comp = Compare()) {
IterT result = last;
while (std::distance(first, last) > 0) {
IterT mid = first + std::distance(first, last) / 2;
@ -29,38 +26,12 @@ IterT bsearch(IterT first,
} else if (comp(target, *mid)) {
last = mid;
} else { // equal
if (policy == BsearchPolicy::FIRST) {
if (mid == first or comp(*(mid - 1), *mid)) {
result = mid;
break;
} else {
last = mid;
}
} else if (policy == BsearchPolicy::LAST) {
if (std::distance(mid, last) == 1 or comp(*mid, *(mid + 1))) {
result = mid;
break;
} else {
first = mid + 1;
}
} else {
result = mid;
break;
}
result = mid;
break;
}
}
return result;
}
template <typename IterT,
typename ValueT = typename std::iterator_traits<IterT>::value_type,
typename Compare = std::less<ValueT>>
IterT bsearch(IterT first,
IterT last,
ValueT target,
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
return bsearch(first, last, target, Compare(), policy);
}
#endif // BSEARCH_BSEARCH_HPP_

View File

@ -0,0 +1,88 @@
/*************************************************************************
> File Name: bsearch.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-21
> Desc:
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
int mybsearch(int a[],int size,int value)
{
int mid = 0;
int left = 0;
int right = size - 1;
while(left <= right)
{
/*防止size数量太大是left + right数据翻转导致问题*/
mid = left + ((right - left)>>1);
if (a[mid] == value)
{
return mid;
}
else if (a[mid] < value)
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
return -1;
}
int helper(int a[], int left,int right,int value)
{
int mid = 0;
if (left > right)
{
return -1;
}
/*防止size数量太大是left + right数据翻转导致问题*/
mid = left + ((right - left)>>1);
if (a[mid] == value)
{
return mid;
}
else if (a[mid] < value)
{
return helper(a,mid + 1,right,value);
}
else
{
return helper(a,left,mid - 1,value);
}
return -1;
}
/*递归实现*/
int mybsearch_2(int a[],int size,int value)
{
return helper(a,0,size-1,value);
}
int main()
{
int a[10] = {5,6,8,9,10,11,23,42,53,123};
int data = 0;
int res = 0;
printf("\r\n输入一个整数");
scanf("%d",&data);
res = mybsearch(a,10,data);
printf("data[%d] %s 在数据中,下标是%d",data,(res != -1)?"":"",res);
printf("\r\n输入一个整数");
scanf("%d",&data);
res = mybsearch_2(a,10,data);
printf("data[%d] %s 在数据中,下标是%d",data,(res != -1)?"":"",res);
return;
}

View File

@ -0,0 +1,53 @@
/*************************************************************************
> File Name: sqrt.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-31
> Desc:
************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
/*求解精度设置*/
#define E 0.000001
double mybsearch(double num)
{
double start = 1.0;
double end = num;
double mid = 0.0;
while(1)
{
mid = (start + end)/2;
if(((mid*mid - num) <= E) && ((mid*mid - num) >= -E))
{
return mid;
}
if ((mid*mid - num) > E)
{
end = mid;
}
else
{
start = mid;
}
}
return 0;
}
int main()
{
double num = 0.0;
/*这里需要注意double的输入方式*/
scanf("%lf",&num);
printf("\r\n num %lf的平方根是%lf",num,mybsearch(num));
return 0;
}

View File

@ -8,10 +8,8 @@
#include "bsearch.hpp"
template <typename VecT, typename T = typename VecT::value_type>
void test_bsearch(const VecT& test,
T target,
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
auto it = bsearch(test.begin(), test.end(), target, policy);
void test_bsearch(const VecT& test, T target) {
auto it = bsearch(test.begin(), test.end(), target);
std::cout << std::distance(test.begin(), it) << std::endl;
}
@ -21,17 +19,9 @@ int main() {
test_bsearch(test, 8); // 14
test_bsearch(test, -1); // 14
test_bsearch(test, 0); // 0, 1
test_bsearch(test, 0, BsearchPolicy::FIRST); // 0
test_bsearch(test, 0, BsearchPolicy::LAST); // 1
test_bsearch(test, 4); // 5, 6
test_bsearch(test, 4, BsearchPolicy::FIRST); // 5
test_bsearch(test, 4, BsearchPolicy::LAST); // 6
test_bsearch(test, 5); // 7, 8, 9, 10, 11
test_bsearch(test, 5, BsearchPolicy::FIRST); // 7
test_bsearch(test, 5, BsearchPolicy::LAST); // 11
test_bsearch(test, 7); // 13
test_bsearch(test, 7, BsearchPolicy::FIRST); // 13
test_bsearch(test, 7, BsearchPolicy::LAST); // 13
return 0;
}

View File

190
c-cpp/16_bsearch/bsearch.c Normal file
View File

@ -0,0 +1,190 @@
/*************************************************************************
> File Name: bsearch.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-21
> Desc:
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
/*二分查找算法的变形问题
*1
*2
*3
*4
* */
/*1、查找第一个等于给定数值的元素*/
int mybsearch_1(int a[],int size,int value)
{
int mid = 0;
int left = 0;
int right = size - 1;
while(left <= right)
{
/*防止size数量太大是left + right数据翻转导致问题*/
mid = left + ((right - left)>>1);
if (a[mid] < value)
{
left = mid + 1;
}
else if (a[mid] > value)
{
right = mid - 1;
}
else
{
if ((mid == 0) || (a[mid - 1] != value))
{
return mid;
}
else
{
right = mid - 1;
}
}
}
return -1;
}
/*2、查找最后一个等于给定数值的元素*/
int mybsearch_2(int a[],int size,int value)
{
int mid = 0;
int left = 0;
int right = size - 1;
while(left <= right)
{
/*防止size数量太大是left + right数据翻转导致问题*/
mid = left + ((right - left)>>1);
if (a[mid] < value)
{
left = mid + 1;
}
else if (a[mid] > value)
{
right = mid - 1;
}
else
{
if ((mid == (size - 1)) || (a[mid + 1] != value))
{
return mid;
}
else
{
left = mid + 1;
}
}
}
return -1;
}
/*3、查找第一个大于等于给定数值的元素*/
int mybsearch_3(int a[],int size,int value)
{
int mid = 0;
int left = 0;
int right = size - 1;
while(left <= right)
{
/*防止size数量太大是left + right数据翻转导致问题*/
mid = left + ((right - left)>>1);
if (a[mid] < value)
{
left = mid + 1;
}
else
{
/*a[mid] >= value 当mid==0 或者a[mid-1] > value 说明是第一个大于等于value*/
if ((mid == 0) || (a[mid - 1] < value))
{
return mid;
}
else
{
right = mid - 1;
}
}
}
return -1;
}
/*4、查找第一个小于等于给定数值的元素*/
int mybsearch_4(int a[],int size,int value)
{
int mid = 0;
int left = 0;
int right = size - 1;
while(left <= right)
{
/*防止size数量太大是left + right数据翻转导致问题*/
mid = left + ((right - left)>>1);
if (a[mid] > value)
{
right = mid - 1;
}
else
{
/*a[mid] <= value 时当前mid == size -1 数组中最大的数值;
* a[mid + 1] vlauemid就第一个小于等于value*/
if ((mid == (size - 1)) || (a[mid + 1] > value))
{
return mid;
}
else
{
left = mid + 1;
}
}
}
return -1;
}
int main()
{
int a[10] = {5,6,6,9,10,11,11,22,33,33};
int data = 0;
int i = 0;
int res =0;
printf("\r\n");
for(i = 0; i < 10 ; i++)
{
printf("%d ",a[i]);
}
printf("\r\n");
printf("\r\n输入一个整数");
scanf("%d",&data);
res = mybsearch_1(a,10,data);
printf("第一个等于data[%d],下标是%d",data,res);
printf("\r\n输入一个整数");
scanf("%d",&data);
res = mybsearch_2(a,10,data);
printf("最后一个等于data[%d],下标是%d",data,res);
printf("\r\n输入一个整数");
scanf("%d",&data);
res = mybsearch_2(a,10,data);
printf("第一个大于等于data[%d],下标是%d",data,res);
printf("\r\n输入一个整数");
scanf("%d",&data);
res = mybsearch_2(a,10,data);
printf("第一个小等于data[%d],下标是%d",data,res);
return;
}

View File

@ -0,0 +1,283 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
int binary_search(int *arr, int size, int val)
{
int low = 0, high = size - 1, mid;
while (low <= high) {
mid = (low + high) / 2;
if (arr[mid] == val)
return mid;
if (arr[mid] < val)
low = mid + 1;
else
high = mid - 1;
}
return -1;
}
/*
* find the first index with *val*
*
* This is a little tricky because the calculation of mid is integer based, it
* will be cast to the lower bound of an integer.
*
* In case the [low, high] range is of size 1 or 2 and arr[mid] >= val, we will
* have:
*
* mid = (low + high) / 2 = low
* high = mid - 1 = low - 1 < low, which break the loop
*
*/
int binary_search_first(int *arr, int size, int val)
{
int low = 0, high = size - 1, mid;
while (low <= high) {
mid = (low + high) / 2;
//printf("[%d-%d] %d\n", low, high, mid);
if (arr[mid] >= val)
high = mid - 1;
else
low = mid + 1;
}
//printf("[%d-%d] %d\n", low, high, mid);
if (arr[low] == val)
return low;
else
return -1;
}
int binary_search_last(int *arr, int size, int val)
{
int low = 0, high = size - 1, mid;
while (low <= high) {
mid = (low + high) / 2;
if (arr[mid] <= val)
low = mid + 1;
else
high = mid - 1;
}
if (arr[high] == val)
return high;
else
return -1;
}
int binary_search_first_r(int *arr, int size, int val)
{
int mid = size / 2;
int idx;
if (size <= 0)
return -1;
// we find *val* at mid, try first half
if (arr[mid] == val) {
idx = binary_search_first_r(arr, mid, val);
return idx != -1 ? idx : mid;
}
// mid == 0 means size == 1
// so the only element in array doesn't equal to val
if (!mid)
return -1;
if (arr[mid] < val) {
idx = binary_search_first_r(arr + mid + 1, size - mid - 1, val);
if (idx != -1)
idx += mid + 1;
} else {
idx = binary_search_first_r(arr, mid, val);
}
return idx;
}
int binary_search_last_r(int *arr, int size, int val)
{
int mid = size / 2;
int idx;
if (size <= 0)
return -1;
// we find *val* at mid, try last half
if (arr[mid] == val) {
idx = binary_search_last_r(arr+mid+1, size-mid-1, val);
if (idx != -1)
mid += idx + 1;
return mid;
}
// mid == 0 means size == 1
// so the only element in array doesn't equal to val
if (!mid)
return -1;
if (arr[mid] < val) {
idx = binary_search_last_r(arr + mid + 1, size - mid - 1, val);
if (idx != -1)
idx += mid + 1;
} else {
idx = binary_search_last_r(arr, mid, val);
}
return idx;
}
int binary_search_first_bigger(int *arr, int size, int val)
{
int low = 0, high = size - 1, mid;
while (low <= high) {
mid = (low + high) / 2;
if (arr[mid] >= val) {
if (mid == 0 || arr[mid-1] < val)
return mid;
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
int binary_search_first_bigger_r(int *arr, int size, int val)
{
int mid = size / 2;
int idx;
if (size <= 0)
return -1;
if (arr[mid] >= val) {
// find one bigger than val, try first half
idx = binary_search_first_bigger_r(arr, mid, val);
if (idx == -1)
idx = mid;
} else {
// the bigger one may sit in second half
idx = binary_search_first_bigger_r(arr + mid + 1, size - mid - 1, val);
if (idx != -1)
idx += mid + 1;
}
return idx;
}
int binary_search_last_smaller(int *arr, int size, int val)
{
int low = 0, high = size - 1, mid;
while (low <= high) {
mid = (low + high) / 2;
if (arr[mid] <= val) {
if (mid == 0 || arr[mid+1] > val)
return mid;
low = mid + 1;
} else {
high = mid - 1;
}
}
return -1;
}
int binary_search_last_smaller_r(int *arr, int size, int val)
{
int mid = size / 2;
int idx;
if (size <= 0)
return -1;
if (arr[mid] <= val) {
// find one smaller than val, try second half
idx = binary_search_last_smaller_r(arr + mid + 1, size - mid - 1, val);
if (idx != -1)
idx += mid + 1;
else
idx = mid;
} else {
// the smaller one may sit in first half
idx = binary_search_last_smaller_r(arr, mid, val);
}
return idx;
}
int main()
{
int arr[10] = {1, 4, 5, 9, 12, 14, 19, 19, 31, 36};
int idx;
printf("Test Array:\n");
for (idx = 0; idx < 10; idx++)
printf("%8d", arr[idx]);
printf("\n");
idx = binary_search_first(arr, 10, 19);
if (idx != -1)
printf("first 19 at %d\n", idx);
else
printf("19 not in arr \n");
idx = binary_search_first_r(arr, 10, 19);
if (idx != -1)
printf("first 19 at %d\n", idx);
else
printf("19 not in arr \n");
idx = binary_search_last(arr, 10, 19);
if (idx != -1)
printf("last 19 at %d\n", idx);
else
printf("19 not in arr \n");
idx = binary_search_last_r(arr, 10, 19);
if (idx != -1)
printf("last 19 at %d\n", idx);
else
printf("19 not in arr \n");
idx = binary_search_first_bigger(arr, 10, 12);
if (idx != -1)
printf("first bigger 12 at %d\n", idx);
else
printf("12 not in arr \n");
idx = binary_search_first_bigger_r(arr, 10, 12);
if (idx != -1)
printf("first bigger 12 at %d\n", idx);
else
printf("12 not in arr \n");
idx = binary_search_last_smaller(arr, 10, 12);
if (idx != -1)
printf("last smaller 12 at %d\n", idx);
else
printf("12 not in arr \n");
idx = binary_search_last_smaller_r(arr, 10, 12);
if (idx != -1)
printf("last smaller 12 at %d\n", idx);
else
printf("12 not in arr \n");
return 0;
}

View File

@ -0,0 +1,90 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/26.
*/
#ifndef BSEARCH_BSEARCH_VARIENTS_HPP_
#define BSEARCH_BSEARCH_VARIENTS_HPP_
#include <iterator>
#include <functional>
enum class BsearchPolicy { UNSPECIFIED, FIRST, LAST, FIRST_NOT_LESS, LAST_NOT_GREATER };
// Liam Huang: The algorithm works right with iterators that meet the ForwardIterator requirement,
// but with a bad time complexity. For better performance, iterators should meet
// the RandomAccessIterator requirement.
template <typename IterT,
typename ValueT = typename std::iterator_traits<IterT>::value_type,
typename Compare>
IterT bsearch(IterT first,
IterT last,
ValueT target,
Compare comp,
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
IterT result = last;
while (std::distance(first, last) > 0) {
IterT mid = first + std::distance(first, last) / 2;
if (policy == BsearchPolicy::FIRST_NOT_LESS) {
if (!comp(*mid, target)) {
if (mid == first or comp(*(mid - 1), target)) {
result = mid;
break;
} else {
last = mid;
}
} else {
first = mid + 1;
}
} else if (policy == BsearchPolicy::LAST_NOT_GREATER) {
if (comp(target, *mid)) {
last = mid;
} else {
if (std::distance(mid, last) == 1 or comp(target, *(mid + 1))) {
result = mid;
break;
} else {
first = mid + 1;
}
}
} else { // policy == UNSPECIFIED or FIRST or LAST
if (comp(*mid, target)) {
first = mid + 1;
} else if (comp(target, *mid)) {
last = mid;
} else { // equal
if (policy == BsearchPolicy::FIRST) {
if (mid == first or comp(*(mid - 1), *mid)) {
result = mid;
break;
} else {
last = mid;
}
} else if (policy == BsearchPolicy::LAST) {
if (std::distance(mid, last) == 1 or comp(*mid, *(mid + 1))) {
result = mid;
break;
} else {
first = mid + 1;
}
} else {
result = mid;
break;
}
}
}
}
return result;
}
template <typename IterT,
typename ValueT = typename std::iterator_traits<IterT>::value_type,
typename Compare = std::less<ValueT>>
IterT bsearch(IterT first,
IterT last,
ValueT target,
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
return bsearch(first, last, target, Compare(), policy);
}
#endif // BSEARCH_BSEARCH_VARIENTS_HPP_

View File

@ -0,0 +1,41 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/26.
*/
#include <iostream>
#include <vector>
#include "bsearch_varients.hpp"
template <typename VecT, typename T = typename VecT::value_type>
void test_bsearch(const VecT& test,
T target,
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
auto it = bsearch(test.begin(), test.end(), target, policy);
std::cout << std::distance(test.begin(), it) << std::endl;
}
int main() {
std::vector<int> test{0, 0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 5, 6, 8}; // std::less<int>()
test_bsearch(test, 8); // 14
test_bsearch(test, -1); // 14
test_bsearch(test, 0); // 0, 1
test_bsearch(test, 0, BsearchPolicy::FIRST); // 0
test_bsearch(test, 0, BsearchPolicy::LAST); // 1
test_bsearch(test, 4); // 5, 6
test_bsearch(test, 4, BsearchPolicy::FIRST); // 5
test_bsearch(test, 4, BsearchPolicy::LAST); // 6
test_bsearch(test, 5); // 7, 8, 9, 10, 11
test_bsearch(test, 5, BsearchPolicy::FIRST); // 7
test_bsearch(test, 5, BsearchPolicy::LAST); // 11
test_bsearch(test, 7, BsearchPolicy::FIRST_NOT_LESS); // 13
test_bsearch(test, 7, BsearchPolicy::LAST_NOT_GREATER); // 12
test_bsearch(test, 7, BsearchPolicy::FIRST); // 14
test_bsearch(test, 8); // 13
test_bsearch(test, 8, BsearchPolicy::FIRST); // 13
test_bsearch(test, 8, BsearchPolicy::LAST); // 13
return 0;
}

View File

View File

@ -0,0 +1,363 @@
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <cstring>
#include <random>
#include <ctime>
using namespace std;
/**
*
*
*
* C++.
* JAVA版本 AuthorZHENG
*
* Authorpuhuaqiang
*
* :
*
* K级 1 9
* K-1 1 5 9
* K-2 1 3 5 7 9
* ... ....
* 0() 1 2 3 4 5 6 7 8 9
*/
const int MAX_LEVEL = 16;
/**
* @brief
*/
class CNode
{
public:
CNode();
~CNode();
std::string toString();
/**
* @brief
*/
CNode** GetIdxList();
/**
* @brief
*/
void SetData(int v);
/**
* @brief
*/
int GetData();
/**
* @brief
*/
void SetLevel(int l);
private:
/**当前节点的值*/
int m_data;
/**
* .
* 2 N1 N2
* 1 N1 N2
* N1是本节点, m_lpForwards[x] N2
*
* [0] .
*/
CNode* m_lpForwards[MAX_LEVEL];
/**当前节点的所在的最大索引级别*/
int m_iMaxLevel;
};
/**
* @brief
*/
class CSkipList
{
public:
CSkipList();
~CSkipList();
/**
* @brief
* @param v
*/
CNode* Find(int v);
/**
* @brief
* @param v
*/
void Insert(int v);
/**
* @brief
* @param v
*/
int Delete(int v);
void PrintAll();
/**
* @brief
* @param l -1 >=0
*/
void PrintAll(int l);
/**
* @brief ,K级的随机函数
* @return K
*/
int RandomLevel();
private:
int levelCount;
/**
*
* /()
*/
CNode* m_lpHead;
};
int main()
{
CSkipList skipList;
/// 插入原始值
for(int i=1; i< 50; i++){
if((i%3) == 0){
skipList.Insert(i);
}
}
for(int i=1; i< 50; i++){
if((i%3) == 1){
skipList.Insert(i);
}
}
skipList.PrintAll();
std::cout<<std::endl;
/// 打印所有等级结构
skipList.PrintAll(-1);
/// 查找
std::cout<<std::endl;
CNode* lpNode = skipList.Find(27);
if(NULL != lpNode){
std::cout<<"查找值为27的节点,找到该节点,节点值:"<<lpNode->GetData()<<std::endl;
}else{
std::cout<<"查找值为27的节点,未找到该节点"<<std::endl;
}
/// 删除
std::cout<<std::endl;
int ret = skipList.Delete(46);
if(0 == ret){
std::cout<<"查找值为46的节点,找到该节点,并删除成功"<<std::endl;
}else{
std::cout<<"查找值为46的节点,找到该节点,删除失败"<<std::endl;
}
std::cout<<std::endl;
//打印所有等级结构
skipList.PrintAll(-1);
std::cin.ignore();
return 0;
}
CNode::CNode()
{
m_data = -1;
m_iMaxLevel = 0;
for(int i=0; i<MAX_LEVEL; i++){
m_lpForwards[i] = NULL;
}
}
CNode::~CNode()
{
}
CNode** CNode::GetIdxList()
{
return m_lpForwards;
}
void CNode::SetData(int v)
{
m_data = v;
}
int CNode::GetData()
{
return m_data;
}
void CNode::SetLevel(int l)
{
m_iMaxLevel = l;
}
std::string CNode::toString()
{
char tmp[32];
std::string ret;
ret.append("{ data: ");
sprintf(tmp, "%d", m_data);
ret.append(tmp);
ret.append("; levels: ");
sprintf(tmp, "%d", m_iMaxLevel);
ret.append(tmp);
ret.append(" }");
return ret;
}
CSkipList::CSkipList()
{
levelCount = 1;
m_lpHead = new CNode();
}
CSkipList::~CSkipList()
{
}
CNode* CSkipList::Find(int v)
{
CNode* lpNode = m_lpHead;
/**
* .
* K -> k-1 -> k-2 ...->0
*/
for(int i=levelCount-1; i>=0; --i){
/**
* v的节点(lpNode).
*/
while((NULL != lpNode->GetIdxList()[i]) && (lpNode->GetIdxList()[i]->GetData() < v)){
lpNode = lpNode->GetIdxList()[i];
}
}
/**
* lpNode v的节点, lpNode的下一个节点就等于或大于v的节点
*/
if((NULL != lpNode->GetIdxList()[0]) && (lpNode->GetIdxList()[0]->GetData() == v)){
return lpNode->GetIdxList()[0];
}
return NULL;
}
void CSkipList::Insert(int v)
{
/// 新节点
CNode* lpNewNode = new CNode();
if(NULL == lpNewNode){
return;
}
/**
*
* 3, 123
*/
int level = RandomLevel();
lpNewNode->SetData(v);
lpNewNode->SetLevel(level);
/**
*
*
*/
CNode *lpUpdateNode[level];
for(int i=0; i<level; i++){
/// 每个索引链表的头节点
lpUpdateNode[i] =m_lpHead;
}
CNode* lpFind = m_lpHead;
for(int i= level-1; i >= 0; --i){
/**
*
* eg. 1 1 7 10
* 6
* lpFind->GetIdxList()[i]->GetData() : lpFind在第1级索引的下一个节点的数据
* "lpFind->GetIdxList()[i]->GetData() < v",
* lpFind节点的后面, lpFind->GetIdxList()[i]
* lpFind就是1 lpFind->GetIdxList()[i] 7
*/
while((NULL != lpFind->GetIdxList()[i]) && (lpFind->GetIdxList()[i]->GetData() < v)){
lpFind = lpFind->GetIdxList()[i];
}
/// lpFind 是新节点在 第i级索引链表的后一个节点
lpUpdateNode[i] = lpFind;
}
for(int i=0; i<level; ++i){
/**
*
* eg 1 1 7 10
* 6.
* lpUpdateNode[i] 1; lpUpdateNode[i]->GetIdxList()[i]7
*
* 2 6 17
*/
lpNewNode->GetIdxList()[i] = lpUpdateNode[i]->GetIdxList()[i];
lpUpdateNode[i]->GetIdxList()[i] = lpNewNode;
}
if(levelCount < level){
levelCount = level;
}
}
int CSkipList::Delete(int v)
{
int ret = -1;
CNode *lpUpdateNode[levelCount];
CNode *lpFind = m_lpHead;
for(int i=levelCount-1; i>= 0; --i){
/**
* v的节点(lpFind).
*/
while((NULL != lpFind->GetIdxList()[i]) && (lpFind->GetIdxList()[i]->GetData() < v)){
lpFind = lpFind->GetIdxList()[i];
}
lpUpdateNode[i] = lpFind;
}
/**
* lpFind v的节点, lpFind的下一个节点就等于或大于v的节点
*/
if((NULL != lpFind->GetIdxList()[0]) && (lpFind->GetIdxList()[0]->GetData() == v)){
for(int i=levelCount-1; i>=0; --i){
if((NULL != lpUpdateNode[i]->GetIdxList()[i]) && (v == lpUpdateNode[i]->GetIdxList()[i]->GetData())){
lpUpdateNode[i]->GetIdxList()[i] = lpUpdateNode[i]->GetIdxList()[i]->GetIdxList()[i];
ret = 0;
}
}
}
return ret;
}
void CSkipList::PrintAll()
{
CNode* lpNode = m_lpHead;
while(NULL != lpNode->GetIdxList()[0]){
std::cout<<lpNode->GetIdxList()[0]->toString().data()<<std::endl;
lpNode = lpNode->GetIdxList()[0];
}
}
void CSkipList::PrintAll(int l)
{
for(int i=MAX_LEVEL-1; i>=0;--i){
CNode* lpNode = m_lpHead;
std::cout<<""<<i<<"级:"<<std::endl;
if((l < 0) || ((l >= 0) && (l == i))){
while(NULL != lpNode->GetIdxList()[i]){
std::cout<<lpNode->GetIdxList()[i]->GetData()<<" ";
lpNode = lpNode->GetIdxList()[i];
}
std::cout<<std::endl;
if(l >= 0){
break;
}
}
}
}
int GetRandom()
{
static int _count = 1;
std::default_random_engine generator(time(0) + _count);
std::uniform_int_distribution<int> distribution(1,99999/*0x7FFFFFFF*/);
int dice_roll = distribution(generator);
_count += 100;
return dice_roll;
}
int CSkipList::RandomLevel()
{
int level = 1;
for(int i=1; i<MAX_LEVEL; ++i){
if(1 == (GetRandom()%3)){
level++;
}
}
return level;
}

View File

@ -0,0 +1,214 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
// https://www.youtube.com/watch?v=2g9OSRKJuzM&t=17s
#define MAX_LEVEL 15
struct node {
int val;
int max_level;
struct node *forward[MAX_LEVEL];
};
struct skip_list {
struct node head;
int max_level;
int max_level_nodes;
};
void node_init(struct node* node)
{
memset(node, 0, sizeof(struct node));
}
void skip_list_init(struct skip_list* sl)
{
node_init(&sl->head);
sl->max_level = 0;
sl->max_level_nodes = 0;
}
void random_init()
{
static bool done = false;
if (done)
return;
srandom(time(NULL));
done = true;
}
int random_level(void)
{
int i, level = 1;
random_init();
for (i = 1; i < MAX_LEVEL; i++)
if (random() % 2 == 1)
level++;
return level;
}
void random_level_test()
{
printf("random level %d\n", random_level());
printf("random level %d\n", random_level());
printf("random level %d\n", random_level());
printf("random level %d\n", random_level());
printf("random level %d\n", random_level());
}
void insert(struct skip_list *sl, int val)
{
int level = random_level();
struct node *update[MAX_LEVEL];
struct node *new, *p;
int i;
new = (struct node*)malloc(sizeof(struct node));
if (!new)
return;
new->max_level = level;
new->val = val;
for (int i = 0; i < MAX_LEVEL; i++)
update[i] = &sl->head;
p = &sl->head;
for (i = level - 1; i >= 0; i--) {
while(p->forward[i] && p->forward[i]->val < val)
p = p->forward[i];
update[i] = p;
}
for (i = 0; i < level; i++) {
new->forward[i] = update[i]->forward[i];
update[i]->forward[i] = new;
}
if (sl->max_level < level) {
sl->max_level = level;
sl->max_level_nodes = 1;
} else if (sl->max_level == level)
sl->max_level_nodes++;
}
struct node *find(struct skip_list* sl, int val)
{
struct node *node = &sl->head;
int i;
for (i = sl->max_level - 1; i >= 0; i--) {
while (node->forward[i] && node->forward[i]->val < val)
node = node->forward[i];
}
if (node->forward[0] && node->forward[0]->val == val) {
return node->forward[0];
}
else
return NULL;
}
void delete(struct skip_list* sl, int val)
{
struct node *update[MAX_LEVEL];
struct node *p;
int i;
p = &sl->head;
for (i = sl->max_level; i >= 0; i--) {
while (p->forward[i] && p->forward[i]->val < val)
p = p->forward[i];
update[i] = p;
}
if (p->forward[0] == NULL || p->forward[0]->val != val)
return;
if (p->forward[0]->max_level == sl->max_level)
sl->max_level_nodes--;
for (i = sl->max_level-1; i >= 0; i--) {
if (update[i]->forward[i] && update[i]->forward[i]->val == val)
update[i]->forward[i] = update[i]->forward[i]->forward[i];
}
// fixup max_level and max_level_nodes
if (sl->max_level_nodes == 0) {
//sl->max_level--;
p = &sl->head;
// skip (max_level - 1), direct test (max_level - 2)
// since no nodes on (max_level - 1)
for (i = sl->max_level - 2; i >= 0; i--) {
while (p->forward[i]) {
sl->max_level_nodes++;
p = p->forward[i];
}
if (sl->max_level_nodes) {
sl->max_level = i + 1;
break;
} else
sl->max_level = i;
}
}
}
void print_sl(struct skip_list* sl)
{
struct node *node;
int level;
printf("%d level skip list with %d nodes on top\n",
sl->max_level, sl->max_level_nodes);
for (level = sl->max_level - 1; level >= 0; level--) {
node = &sl->head;
printf("Level[%02d]:", level);
while (node->forward[level]) {
printf("%4d", node->forward[level]->val);
node = node->forward[level];
}
printf("\n");
}
}
int main()
{
struct skip_list sl;
struct node *node = NULL;
int i;
skip_list_init(&sl);
print_sl(&sl);
for (i = 0; i < 10; i++)
insert(&sl, i);
print_sl(&sl);
node = find(&sl, 8);
if (node)
printf("find 8 in sl %d\n", node->val);
else
printf("8 not in sl\n");
for (i = 0; i < 10; i++) {
delete(&sl, i);
print_sl(&sl);
}
return 0;
}

View File

@ -0,0 +1,186 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/29.
*/
#ifndef SKIPLIST_SKIPLIST_HPP_
#define SKIPLIST_SKIPLIST_HPP_
#include <functional>
#include <type_traits>
#include <vector>
#include <chrono>
#include <random>
#include <initializer_list>
#include <limits>
#include <iostream>
template <typename Value>
class skiplist {
public:
using value_type = Value;
using hash_type = std::hash<value_type>;
using key_type = typename hash_type::result_type;
using size_type = size_t;
private:
struct InternalNode {
value_type value;
const key_type key;
std::vector<InternalNode*> forwards; // pointers to successor nodes
InternalNode(const key_type& k, const size_type lv)
: value(), key(k), forwards(lv, nullptr) {}
InternalNode(const value_type& v, const size_type lv)
: value(v), key(hash_type()(value)), forwards(lv, nullptr) {}
};
using node_type = InternalNode;
private:
const size_type MAX_LEVEL = 16;
const double PROBABILITY = 0.5;
const unsigned int seed =
std::chrono::system_clock::now().time_since_epoch().count();
mutable
std::default_random_engine generator = std::default_random_engine(seed);
mutable
std::binomial_distribution<size_type> distribution =
std::binomial_distribution<size_type>(MAX_LEVEL - 1, PROBABILITY);
node_type* head = nullptr;
node_type* nil = nullptr;
static const value_type default_value;
public:
skiplist() {
key_type head_key = std::numeric_limits<key_type>::min();
key_type nil_key = std::numeric_limits<key_type>::max();
head = new node_type(head_key, MAX_LEVEL);
nil = new node_type(nil_key, MAX_LEVEL);
std::fill(head->forwards.begin(), head->forwards.end(), nil);
}
skiplist(std::initializer_list<value_type> init) : skiplist() {
for (const value_type& v : init) {
insert(v);
}
}
skiplist(const skiplist& other) = delete;
skiplist(skiplist&& other) :
MAX_LEVEL(std::move(other.MAX_LEVEL)),
PROBABILITY(std::move(other.PROBABILITY)),
seed(std::move(other.seed)),
generator(std::move(other.generator)),
distribution(std::move(other.distribution)),
head(other.head),
nil(other.nil) {
other.head = nullptr;
other.nil = nullptr;
}
~skiplist() {
node_type* node = head;
while (nullptr != node and nullptr != node->forwards[0]) {
node_type* tmp = node;
node = node->forwards[0];
delete tmp;
}
delete node;
}
skiplist& operator=(const skiplist& other) = delete;
skiplist& operator=(skiplist&& other) = delete;
private:
inline size_type get_random_level() const {
return distribution(generator);
}
static size_type get_node_level(const node_type* node) {
return node->forwards.size();
}
static node_type* make_node(const value_type& v, const size_type lv) {
return new node_type(v, lv);
}
/**
* @brief returns a pointer to the first node such that
* node->key == hash_type()(v) and node->value == v.
*/
node_type* get_first_equal(const value_type& v) const {
const key_type target = hash_type()(v);
node_type* x = head;
for (size_type i = get_node_level(head); i > 0; --i) {
while (x->forwards[i - 1]->key < target or
x->forwards[i - 1]->key == target and x->forwards[i - 1]->value != v) {
x = x->forwards[i - 1];
}
}
return x->forwards[0];
}
/**
* @brief returns a collection of nodes.
* returns[i] is the pointer to the last node at level i + 1
* such that returns[i]->key < hash_type()(v) or
* returns[i]->key == hash_type()(v) but returns[i]->value != v.
*/
std::vector<node_type*> get_predecessors(const value_type& v) const {
const key_type target = hash_type()(v);
std::vector<node_type*> results(get_node_level(head), nullptr);
node_type* x = head;
for (size_type i = get_node_level(head); i > 0; --i) {
while (x->forwards[i - 1]->key < target or
x->forwards[i - 1]->key == target and x->forwards[i - 1]->value != v) {
x = x->forwards[i - 1];
}
results[i - 1] = x;
}
return results;
}
public:
const value_type& find(const value_type& target) {
node_type* x = get_first_equal(target);
if (nullptr != x and nil != x and x->value == target) {
return x->value;
} else {
return default_value;
}
}
void insert(const value_type& value) {
std::vector<node_type*> preds = get_predecessors(value);
const size_type new_node_lv = get_random_level();
node_type* new_node = make_node(value, new_node_lv);
for (size_type i = 0; i != new_node_lv; ++i) {
new_node->forwards[i] = preds[i]->forwards[i];
preds[i]->forwards[i] = new_node;
}
}
void erase(const value_type& value) {
std::vector<node_type*> preds = get_predecessors(value);
node_type* node = preds[0]->forwards[0];
if (node == nil or node->value != value) { return; }
for (size_type i = 0; i != get_node_level(node); ++i) {
preds[i]->forwards[i] = node->forwards[i];
}
delete node;
}
void print(std::ostream& os) const {
node_type* list = head->forwards[0];
os << "{";
while (list != nil) {
os << "key: " << list->key << " value: " << list->value
<< " level: " << get_node_level(list);
list = list->forwards[0];
if (list != nil) os << " : ";
os << "\n";
}
os << "}\n";
}
};
template <typename Value>
const typename skiplist<Value>::value_type skiplist<Value>::default_value =
typename skiplist<Value>::value_type();
#endif // SKIPLIST_SKIPLIST_HPP_

View File

@ -0,0 +1,346 @@
/*************************************************************************
> File Name: skiplist.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-31
> Desc:
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include"./skiplist.h"
/*创建node节点*/
node* skip_list_create_node(int level,int key,int value)
{
node * tmp = NULL;
tmp =(node *)malloc(sizeof(node) + level*sizeof(node *));
assert(tmp != NULL);
memset(tmp,0,sizeof(node) + level*sizeof(node*));
tmp->key = key;
tmp->value = value;
tmp->max_level = level;
return tmp;
}
/*创建跳表的表头max_level层数*/
skiplist * skip_list_create(int max_level)
{
int i = 0;
skiplist * list = NULL;
list = (skiplist *)malloc (sizeof(skiplist));
assert(list != NULL);
list->level = 1;
list->count = 0;
list->head = skip_list_create_node(max_level,0,0);
if(list->head == NULL)
{
free(list);
return NULL;
}
return list;
}
/*skiplist 销毁*/
void skip_list_destory(skiplist * list)
{
int i = 0;
node * tmp = NULL;
if((list == NULL) || (list->head == NULL))
{
return;
}
while(list->head->next[0] != NULL)
{
tmp = list->head->next[0];
list->head->next[0] = tmp->next[0];
free(tmp);
}
free(list->head);
free(list);
return;
}
/*插入元素获得层数,是随机产生的*/
int skip_list_level(skiplist * list)
{
int i = 0;
int level = 1;
for (i = 1; i < list->head->max_level; i++)
{
if ((rand()%2) == 1)
{
level++;
}
}
return level;
}
int skip_list_insert(skiplist *list,int key,int value)
{
int i = 0;
int level = 0;
node **update = NULL;/*用来更新每层的指针*/
node *tmp = NULL;
node *prev = NULL;
if (list == NULL)
{
return 1;
}
/*申请update空间用于保存每层的指针*/
update = (node **)malloc(sizeof(node *)*list->head->max_level);
if (update == NULL)
{
return 2;
}
/*逐层查询节点的*/
prev = list->head;
for (i = (list->level -1); i >= 0; i--)
{
/*初始化每level层的头指针*/
while(((tmp = prev->next[i]) != NULL) && (tmp->key < key))
{
prev = tmp;
}
update[i] = prev;
}
/*当前key已经存在返回错误*/
if ((tmp!= NULL) && (tmp->key == key))
{
return 3;
}
/*获取插入元素的随机层数,并更新跳表的最大层数*/
level = skip_list_level(list);
/*创建当前数据节点*/
tmp = skip_list_create_node(level,key,value);
if (tmp == NULL)
{
return 4;
}
/*更新最大层数*/
if (level > list->level)
{
for (i = list->level;i < level; i ++)
{
update[i] = list->head;
}
list->level = level;
}
/*逐层更新节点的指针*/
for(i = 0; i < level; i++)
{
tmp->next[i] = update[i]->next[i];
update[i]->next[i] = tmp;
}
list->count++;
return 0;
}
int skip_list_delete(skiplist * list, int key ,int *value)
{
int i = 0;
node **update = NULL;/*用来更新每层的指针*/
node *tmp = NULL;
node *prev = NULL;
if ((list == NULL) && (value == NULL)&& (list->count == 0))
{
return 1;
}
/*申请update空间用于保存每层的指针*/
update = (node **)malloc(sizeof(node *)*list->level);
if (update == NULL)
{
return 2;
}
/*逐层查询节点的*/
prev = list->head;
for (i = (list->level -1); i >= 0; i--)
{
/*初始化每level层的头指针*/
while(((tmp = prev->next[i]) != NULL) && (tmp->key < key))
{
prev = tmp;
}
update[i] = prev;
}
if ((tmp != NULL)
&& (tmp->key == key))
{
*value = tmp->value;
/*逐层删除*/
for(i = 0; i < list->level; i++)
{
if(update[i]->next[i] == tmp)
{
update[i]->next[i] = tmp->next[i];
}
}
free(tmp);
tmp = NULL;
/*更新level的层数*/
for (i = list->level - 1; i >= 0; i++)
{
if (list->head->next[i] == NULL )
{
list->level--;
}
else
{
break;
}
}
list->count--;
}
else
{
return 3;/*未找到节点*/
}
return 0 ;
}
/*查询当前key是否在跳表中如果存在返回查询的value数值不存在返回-1*/
int skip_list_search(skiplist *list,int key,int *value)
{
int i = 0;
node *prev = NULL;
node *tmp = NULL;
if((list == NULL) || (list->count == 0) || (value == NULL))
{
return 1;
}
prev = list->head;
for(i = list->level - 1; i >= 0; i--)
{
while(((tmp = prev->next[i]) != NULL) && (tmp->key <= key))
{
if (tmp->key == key)
{
*value = tmp->value;
return 0;
}
prev = tmp;
}
}
return -1;
}
void skip_list_dump(skiplist *list)
{
int i = 0;
node *ptmp = NULL;
printf("\r\n----------------------------------------------");
printf("\r\n skip list level[%d],count[%d]",list->level,list->count);
for(i = list->level - 1; i >= 0; i --)
{
ptmp = list->head->next[i];
printf("\r\n level[%d]:",i);
while(ptmp != NULL)
{
printf("%d-%d ",ptmp->key,ptmp->value);
ptmp = ptmp->next[i];
}
}
printf("\r\n----------------------------------------------");
return;
}
int main()
{
int res = 0;
int key = 0;
int value = 0;
skiplist *list = NULL;
list = skip_list_create(5);
assert(list != NULL);
while(1)
{
printf("\r\n 请输入key 和 value当key = 1000时退出输入");
scanf("%d%d",&key,&value);
if (key == 1000)
{
break;
}
res = skip_list_insert(list,key,value);
if (res != 0)
{
printf("\r\n skip list insert %d,failed,res=%d.",key,res);
}
}
skip_list_dump(list);
while(1)
{
printf("\r\n 通过key 查询value的数值当key = 1000时退出查询");
scanf("%d",&key);
if(key == 1000)
{
break;
}
res = skip_list_search(list,key,&value);
if (res != 0)
{
printf("\r\n skip list search %d,failed,res=%d.",key,res);
}
else
{
printf("\r\n skip list search %d,sucessful,value=%d.",key,value);
}
}
skip_list_dump(list);
while(1)
{
printf("\r\n 通过key 删除节点当key = 1000时退出删除");
scanf("%d",&key);
if(key == 1000)
{
break;
}
res = skip_list_delete(list,key,&value);
if (res != 0)
{
printf("\r\n skip list search %d,failed,res=%d.",key,res);
}
else
{
printf("\r\n skip list search %d,sucessful,value=%d.",key,value);
}
}
skip_list_dump(list);
skip_list_destory(list);
return 0;
}

View File

@ -0,0 +1,33 @@
/*************************************************************************
> File Name: skiplist.h
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-31
> Desc:
************************************************************************/
#ifndef __SKIP_LIST_H__
#define __SKIP_LIST_H__
typedef struct _node
{
int key; /*key是唯一的*/
int value; /*存储的内容*/
int max_level; /*当前节点最大层数*/
struct _node *next[0];/*level层链表结构*/
}node;
typedef struct _skiplist
{
int level;
int count;
node *head;
}skiplist;
/*根据当前结构体元素的地址,获取到结构体首地址*/
#define offsetof(TYPE,MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container(ptr,type,member) ({\
const typeof( ((type *)0)->member) *__mptr = (ptr);\
(type *) ( (char *)__mptr - offsetof(type,member));})
#endif

View File

@ -0,0 +1,67 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/30.
*/
#include <iostream>
#include <string>
#include "skiplist.hpp"
int main() {
// 1. Initialize a skip list for test
// * default constructor
// * constructor with initializer list
// * insert
skiplist<std::string> ss{"1", "2", "3", "4", "5"};
// 1a. show
// * print
ss.print(std::cout);
std::cout << std::endl;
// 2. move construction
// * move constructor
skiplist<std::string> s(std::move(ss));
// 2a. show
// * print
s.print(std::cout);
std::cout << std::endl;
// 3.a find something doesn't exist.
// * find
auto f = s.find("0");
if (!f.empty()) {
std::cout << "Node found!\nvalue: " << f << '\n';
} else {
std::cout << "Node NOT found!\n";
}
// 3.b find something does exist.
// * find
auto ff = s.find("1");
if (!ff.empty()) {
std::cout << "Node found!\tvalue: " << ff << '\n';
} else {
std::cout << "Node NOT found!\n";
}
// 4. insert() - reassign
s.insert("TEST");
// 4a. print()
s.print(std::cout);
std::cout << std::endl;
// 5. erase()
s.erase("TEST");
// 5a. print();
s.print(std::cout);
std::cout << std::endl;
std::cout << "\nDone!\n";
return 0;
// 6. destructor
}

View File

@ -0,0 +1,362 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/30.
*/
#ifndef SKIPLIST_SKIPLIST_TR_HPP_
#define SKIPLIST_SKIPLIST_TR_HPP_
#ifdef LIAM_UT_DEBUG_
#include <assert.h>
#include <iostream>
#endif
#include <set>
#include <vector>
#include <list>
#include <functional>
#include <type_traits>
#include <random>
#include <limits>
#include <algorithm>
#include <initializer_list>
#include <iterator>
namespace skiplist_detail {
template <typename Key, typename Value>
struct InternalNode {
using iterator = typename std::list<InternalNode>::iterator;
const Key key;
std::multiset<Value> values;
std::vector<iterator> forwards;
InternalNode() = delete;
explicit InternalNode(const Key& k) : key(k) {}
};
template <typename IntType>
class random_level {
private:
mutable std::random_device rd;
mutable std::mt19937 gen = std::mt19937(rd());
mutable std::binomial_distribution<IntType> dist;
public:
random_level(IntType max_level, double prob) : dist(max_level - 1, prob) {}
inline IntType operator()() const { return dist(gen); }
};
} // namespace skiplist_detail
enum class erase_policy { ALL, SINGLE };
template <typename Value,
typename Hash = std::hash<Value>,
size_t Factor = 2>
class skiplist {
public:
using value_type = Value;
using size_type = size_t;
using hasher = Hash;
using hash_type = typename Hash::result_type;
using compare = std::less<hash_type>;
using node_type = skiplist_detail::InternalNode<hash_type, value_type>;
using container = std::list<node_type>;
using iterator = typename container::iterator;
using const_iterator = typename container::const_iterator;
static_assert(std::is_same<iterator, typename node_type::iterator>::value,
"STATIC ASSERT FAILED! iterator type differs.");
private:
size_type max_lv_ = 2;
double prob_ = 0.5;
mutable skiplist_detail::random_level<size_type> rl_;
container cont_;
public:
skiplist() : rl_(max_lv_, prob_) {
init_internally();
}
explicit skiplist(const size_type max_lv, const double prob = 0.5)
: max_lv_(max_lv), prob_(prob), rl_(max_lv_, prob_) {
init_internally();
}
skiplist(skiplist&& other) = default;
skiplist& operator=(skiplist&& other) = default;
~skiplist() = default;
template <typename InputIt>
skiplist(InputIt first, InputIt last) : skiplist() {
using value_type_in_iter = typename std::iterator_traits<InputIt>::value_type;
static_assert(std::is_same<value_type, value_type_in_iter>::value,
"STATIC ASSERT FAILED! Value in InputIt should be the same to value_type.");
for (InputIt i = first; i != last; ++i) {
insert(*i);
}
}
skiplist(std::initializer_list<value_type> init) : skiplist(init.begin(), init.end()) {}
private: // noncopyable
skiplist(const skiplist&) = delete;
skiplist& operator=(const skiplist&) = delete;
private:
void init_internally() {
const hash_type tail_key = std::numeric_limits<hash_type>::max();
node_type tail(tail_key);
tail.forwards.resize(max_lv_, cont_.end());
iterator tail_iter = cont_.insert(cont_.begin(), std::move(tail));
const hash_type head_key = std::numeric_limits<hash_type>::min();
node_type head(head_key);
head.forwards.resize(max_lv_, tail_iter);
cont_.insert(cont_.begin(), std::move(head));
#ifdef LIAM_UT_DEBUG_
assert(cont_.begin()->key == head_key);
for (auto it : cont_.begin()->forwards) {
assert(it->key == tail_key);
}
for (auto it : std::next(cont_.begin())->forwards) {
assert(it == cont_.end());
}
std::cerr << "UT_DEBUG: all assert in init_internally() success!\n";
#endif
return;
}
/**
* @brief return a const_iterator points to the last element
* such that its hash_key <= target_hash_key
*/
const_iterator find_helper(const hash_type& key) const {
#ifdef LIAM_UT_DEBUG_
std::cerr << "Keys contained in the list: ";
for (auto node : cont_) {
std::cerr << node.key << ' ';
}
std::cerr << '\n';
std::cerr << "Target key: " << key << '\n';
#endif
const_iterator iter = begin();
for (size_type i = 0; i != max_lv_; ++i) {
size_type focus = max_lv_ - 1 - i;
// invariant: iter->key <= key
while (not compare()(key, iter->forwards[focus]->key)) {
#ifdef LIAM_UT_DEBUG_
std::cerr << "i: " << i << " focus: " << focus << ". "
<< "since iter->forwards[focus]->key[" << iter->forwards[focus]->key
<< "] <= key[" << key << "], ";
#endif
iter = iter->forwards[focus];
#ifdef LIAM_UT_DEBUG_
std::cerr << "step forward iter to [" << iter->key << "]\n";
#endif
}
// result: iter->key <= key < iter->forwards[focus]->key
#ifdef LIAM_UT_DEBUG_
std::cerr << "The following fact holds at level " << focus
<< ": iter->key[" << iter->key << "] <= key["
<< key << "] < iter->forwards[focus]->key[" << iter->forwards[focus]->key
<<"].\n";
#endif
}
return iter;
}
std::vector<iterator> find_predecessors(const hash_type& key, const size_type& lv) {
#ifdef LIAM_UT_DEBUG_
std::cerr << "Keys contained in the list: ";
for (auto node : cont_) {
std::cerr << node.key << ' ';
}
std::cerr << '\n';
std::cerr << "Target key: " << key << '\n';
#endif
std::vector<iterator> res;
res.resize(lv + 1);
iterator iter = begin();
for (size_type i = 0; i != max_lv_; ++i) {
size_type focus = max_lv_ - 1 - i;
#ifdef LIAM_UT_DEBUG_
std::cerr << "i: " << i << " focus: " << focus << ".\n";
#endif
// invariant: iter->key < key
while (compare()(iter->forwards[focus]->key, key)) {
#ifdef LIAM_UT_DEBUG_
std::cerr << "since iter->forwards[focus]->key[" << iter->forwards[focus]->key
<< "] < key[" << key << "], ";
#endif
iter = iter->forwards[focus];
#ifdef LIAM_UT_DEBUG_
std::cerr << "step forward iter to [" << iter->key << "]\n";
#endif
}
// result: iter->key < key <= iter->forwards[focus]->key
#ifdef LIAM_UT_DEBUG_
std::cerr << "The following fact holds at level " << focus
<< ": iter->key[" << iter->key << "] < key[" << key
<< "] <= iter->forwards[focus]->key[" << iter->forwards[focus]->key
<<"].\n";
#endif
if (focus < lv + 1) {
res[focus] = iter;
#ifdef LIAM_UT_DEBUG_
std::cerr << "predecessor at level [" << focus
<< "] has been recorded, while level upper limit is " << lv <<".\n";
#endif
}
}
return res;
}
public:
size_type size() const {
return cont_.size() - 2;
}
bool empty() const {
return size() == 0;
}
iterator begin() {
return cont_.begin();
}
const_iterator begin() const {
return cont_.cbegin();
}
const_iterator cbegin() const {
return cont_.cbegin();
}
iterator end() {
return cont_.end();
}
const_iterator end() const {
return cont_.cend();
}
const_iterator cend() const {
return cont_.cend();
}
void grow(const size_type new_max_lv) {
if (max_lv_ < new_max_lv) {
#ifdef LIAM_UT_DEBUG_
std::cerr << "grow from [" << max_lv_ << "] to ["
<< new_max_lv << "]!\n";
#endif
max_lv_ = new_max_lv;
iterator tail = std::prev(cont_.end());
auto beg_tail = tail->forwards.end();
tail->forwards.resize(max_lv_, cont_.end());
iterator head = cont_.begin();
auto beg_head = head->forwards.end();
head->forwards.resize(max_lv_, tail);
return;
} else {
#ifdef LIAM_UT_DEBUG_
std::cerr << "abandon growing!\n";
#endif
return;
}
}
void grow() {
grow(Factor * max_lv_);
}
size_type capability() const {
return std::pow(Factor, max_lv_);
}
public:
const_iterator find(const value_type& target) const {
#ifdef LIAM_UT_DEBUG_
std::cerr << "finding [" << target << "]!\n";
#endif
const hash_type key = hasher()(target);
const_iterator iter = find_helper(key);
return (iter->key == key) ? iter : cont_.end();
}
void insert(const value_type& target) {
#ifdef LIAM_UT_DEBUG_
std::cerr << "inserting [" << target << "]!\n";
#endif
if (size() > static_cast<double>(Factor - 1) / Factor * capability()) {
#ifdef LIAM_UT_DEBUG_
std::cerr << "size[" << size() << "], Factor[" << Factor << "], capability[" << capability() << "]!\n";
#endif
grow();
}
const hash_type key = hasher()(target);
const size_type lv = rl_();
std::vector<iterator> predecessors = find_predecessors(key, lv);
if (predecessors[0]->forwards[0]->key == key) { // key already in skiplist
#ifdef LIAM_UT_DEBUG_
std::cerr << "key [" << key << "] already in the skiplist, insert directly!\n";
#endif
predecessors[0]->forwards[0]->values.insert(target);
return;
} else {
#ifdef LIAM_UT_DEBUG_
std::cerr << "key [" << key << "] not in the skiplist, insert a new node!\n";
#endif
node_type node(key);
node.forwards.resize(lv + 1);
node.values.insert(target);
iterator inserted = cont_.insert(predecessors[0]->forwards[0], std::move(node));
for (size_type i = 0; i != lv + 1; ++i) {
inserted->forwards[i] = predecessors[i]->forwards[i];
predecessors[i]->forwards[i] = inserted;
}
#ifdef LIAM_UT_DEBUG_
assert(inserted->forwards[0] == std::next(inserted));
#endif
return;
}
}
void erase(const value_type& target,
const erase_policy policy = erase_policy::ALL) {
#ifdef LIAM_UT_DEBUG_
std::cerr << "erasing [" << target << "]!\n";
#endif
const hash_type key = hasher()(target);
std::vector<iterator> predecessors = find_predecessors(key, max_lv_);
if (predecessors[0]->forwards[0]->key == key) { // hit
#ifdef LIAM_UT_DEBUG_
std::cerr << "key [" << key << "] is in the skiplist!\n";
#endif
iterator found = predecessors[0]->forwards[0];
for (auto iter = found->values.begin(); iter != found->values.end(); ) {
if (policy == erase_policy::ALL) {
if (*iter == target) {
iter = found->values.erase(iter);
} else {
++iter;
}
} else if (policy == erase_policy::SINGLE) {
if (*iter == target) {
found->values.erase(iter);
break;
}
}
}
#ifdef LIAM_UT_DEBUG_
std::cerr << "target(s) removed!\n";
#endif
if (found->values.empty()) {
const size_type lvp1 = found->forwards.size(); // lv plus 1
for (size_type i = 0; i != lvp1; ++i) {
predecessors[i]->forwards[i] = found->forwards[i];
}
cont_.erase(found);
#ifdef LIAM_UT_DEBUG_
std::cerr << "empty node removed!\n";
#endif
return;
} else {
return;
}
} else {
#ifdef LIAM_UT_DEBUG_
std::cerr << "key [" << key << "] is not in the skiplist, do nothing!\n";
#endif
return;
}
}
};
#endif // SKIPLIST_SKIPLIST_TR_HPP_

View File

@ -0,0 +1,107 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/30.
*/
#include <assert.h>
#include <iostream>
#include <map>
#include <string>
#include "skiplist_tr.hpp"
int main() {
// 1. UT for skiplist_detail::random_level
skiplist_detail::random_level<size_t> rl(5, 0.5);
std::map<size_t, size_t> hist;
for (size_t i = 0; i != 10000; ++i) {
++hist[rl()];
}
for (auto p : hist) {
std::cout << p.first << ' ' << std::string(p.second / 100, '*') << '\n';
}
// 2. UT for skiplist(), init_internally(), size(), empty()
skiplist<std::string> sl_default;
assert(sl_default.empty());
// 2.1. UT for grow with abandon
sl_default.grow(1);
assert(sl_default.capability() == 4);
// 2.2. UT for grow
sl_default.grow(10);
assert(sl_default.capability() == 1024);
// 3. UT for constructor of initializer_list and InputIt, init_internally(), insert(),
// find_predecessors()
skiplist<std::string> sl{"hello", "world", "!"};
assert(not sl.empty());
assert(3 == sl.size());
// 4. UT for find() find_helper()
auto search = sl_default.find("nonexist");
assert(search == sl_default.cend());
assert(search == sl_default.end());
search = sl.find("hello");
assert(search != sl.cend());
assert(search != sl.end());
search = sl.find("nonexist");
assert(search == sl.cend());
assert(search == sl.end());
// 5. UT for insert(), find_predecessors()
// 5.1. UT for insert a already-exist item
sl.insert("hello");
search = sl.find("hello");
assert(search != sl.cend());
assert(search != sl.end());
// 5.2. UT for insert a new incoming item
search = sl.find("now exist");
assert(search == sl.cend());
assert(search == sl.end());
sl.insert("now exist");
search = sl.find("now exist");
assert(search != sl.cend());
assert(search != sl.end());
// 6. UT for erase(), find_predecessors()
sl.insert("hello");
sl.insert("hello");
sl.insert("hello");
sl.insert("hello");
// 6.1. UT for erase single item
sl.erase("hello", erase_policy::SINGLE);
search = sl.find("hello");
assert(search != sl.cend());
assert(search != sl.end());
// 6.2. UT for erase all items
sl.erase("hello", erase_policy::ALL);
search = sl.find("hello");
assert(search == sl.cend());
assert(search == sl.end());
// 6.3 UT for erase non-exist item
sl.erase("nonexist");
// 7. UT for insert() behind erase()
// 7.1. different word
sl.insert("world");
search = sl.find("world");
assert(search != sl.cend());
assert(search != sl.end());
assert(search->values.count("world") == 2);
// 7.1. same word, also UT for grow()
search = sl.find("hello");
assert(search == sl.cend());
assert(search == sl.end());
sl.insert("hello");
sl.insert("hello");
sl.insert("hello");
sl.insert("hello");
sl.insert("hello");
search = sl.find("hello");
assert(search != sl.cend());
assert(search != sl.end());
assert(search->values.count("hello") == 5);
return 0;
// 8. UT for ~skiplist()
}

View File

@ -0,0 +1,364 @@
/*************************************************************************
> File Name: listhash.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-11-07
> Desc:
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include"listhash.h"
#ifdef MEMORY_TEST
#include<mcheck.h>
#endif
hashtab * hashtab_create(int size,hash_key_func hash_value,
keycmp_func keycmp,hash_node_free_func hash_node_free)
{
hashtab * h = NULL;
int i = 0;
if ((size < 0) || (hash_value == NULL) || (keycmp == NULL))
{
return NULL;
}
h = (hashtab *)malloc(sizeof(hashtab));
if (h == NULL)
{
return NULL;
}
h->htables = (hashtab_node **)malloc(size * sizeof(hashtab_node*));
if (h->htables == NULL)
{
return NULL;
}
h->size = size;
h->nel = 0;
h->hash_value = hash_value;
h->keycmp = keycmp;
h->hash_node_free = hash_node_free;
for (i = 0; i < size; i++)
{
h->htables[i] = NULL;
}
return h;
}
void hashtab_destory(hashtab *h)
{
int i = 0;
hashtab_node * cur = NULL;
hashtab_node * tmp = NULL;
if (h == NULL)
{
return;
}
for (i = 0; i <h->size; i++)
{
cur = h->htables[i];
while (cur != NULL)
{
tmp = cur;
cur = cur->next;
h->hash_node_free(tmp);
}
h->htables[i] = NULL;
}
free(h->htables);
free(h);
return;
}
int hashtab_insert(hashtab * h,void *key,void *data)
{
unsigned int hvalue = 0;
int i = 0;
hashtab_node *cur = NULL;
hashtab_node *prev = NULL;
hashtab_node *newnode = NULL;
if ((h == NULL) || (key == NULL) || (data == NULL))
{
return 1;
}
/*获取hash 数值*/
hvalue = h->hash_value(h,key);
cur = h->htables[hvalue];
/*hash桶中元素是从小到大排列的找到要插入的位置*/
while((cur != NULL) && (h->keycmp(h,key,cur->key) > 0))
{
prev = cur;
cur = cur->next;
}
/*如果key和当前key比对一致直接返回数据已经存在*/
if ((cur != NULL) && (h->keycmp(h,key,cur->key) == 0))
{
return 2;
}
newnode = (hashtab_node *)malloc(sizeof(hashtab_node));
if (newnode == NULL)
{
return 3;
}
newnode->key = key;
newnode->data = data;
if (prev == NULL)
{
newnode->next = h->htables[hvalue];
h->htables[hvalue] = newnode;
}
else
{
newnode->next = prev->next;
prev->next = newnode;
}
h->nel++;
return 0;
}
hashtab_node *hashtab_delete(hashtab *h, void *key)
{
int hvalue = 0;
int i = 0;
hashtab_node *cur = NULL;
hashtab_node *prev = NULL;
if ((h == NULL) || (key == NULL))
{
return NULL;
}
/*获取hash 数值*/
hvalue = h->hash_value(h,key);
cur = h->htables[hvalue];
/*hash桶中元素是从小到大排列的找到要插入的位置*/
while((cur != NULL) && (h->keycmp(h,key,cur->key) >= 0))
{
if (h->keycmp(h,key,cur->key) == 0)
{
if (prev == NULL)
{
h->htables[hvalue] = cur->next;
}
else
{
prev->next = cur->next;
}
return cur;
}
prev = cur;
cur = cur->next;
}
return NULL;
}
void *hashtab_search(hashtab*h,void *key)
{
int hvalue = 0;
int i = 0;
hashtab_node *cur = NULL;
if ((h == NULL) || (key == NULL))
{
return NULL;
}
/*获取hash 数值*/
hvalue = h->hash_value(h,key);
cur = h->htables[hvalue];
/*hash桶中元素是从小到大排列的找到要插入的位置*/
while((cur != NULL) && (h->keycmp(h,key,cur->key) >= 0))
{
if (h->keycmp(h,key,cur->key) == 0)
{
return cur->data;
}
cur = cur->next;
}
return NULL;
}
void hashtab_dump(hashtab *h)
{
int i = 0;
hashtab_node * cur = NULL;
if (h == NULL)
{
return ;
}
printf("\r\n----开始--size[%d],nel[%d]------------",h->size,h->nel);
for( i = 0; i < h->size; i ++)
{
printf("\r\n htables[%d]:",i);
cur = h->htables[i];
while((cur != NULL))
{
printf("key[%s],data[%s] ",cur->key,cur->data);
cur = cur->next;
}
}
printf("\r\n----结束--size[%d],nel[%d]------------",h->size,h->nel);
}
struct test_node
{
char key[80];
char data[80];
};
unsigned int siample_hash(const char *str)
{
register unsigned int hash = 0;
register unsigned int seed = 131;
while(*str)
{
hash = hash*seed + *str++;
}
return hash & (0x7FFFFFFF);
}
int hashtab_hvalue(hashtab *h,const void *key)
{
return (siample_hash(key) % h->size);
}
int hashtab_keycmp(hashtab *h,const void *key1,const void *key2)
{
return strcmp(key1,key2);
}
void hashtab_node_free(hashtab_node*node)
{
struct test_node * ptmp = NULL;
ptmp = container(node->key,struct test_node,key);
free(ptmp);
free(node);
}
int main ()
{
int i = 0;
int res = 0;
char *pres = NULL;
hashtab_node * node = NULL;
struct test_node *p = NULL;
hashtab *h = NULL;
#ifdef MEMORY_TEST
setenv("MALLOC_TRACE","1.txt",1);
mtrace();
#endif
h = hashtab_create(5,hashtab_hvalue,hashtab_keycmp,hashtab_node_free);
assert(h!= NULL);
while(1)
{
p = (struct test_node*)malloc(sizeof(struct test_node));
assert(p != NULL);
printf("\r\n 请输入key 和value当可以等于\"quit\"时退出");
scanf("%s",p->key);
scanf("%s",p->data);
if(strcmp(p->key,"quit") == 0)
{
free(p);
break;
}
res = hashtab_insert(h,p->key,p->data);
if (res != 0)
{
free(p);
printf("\r\n key[%s],data[%s] insert failed %d",p->key,p->data,res);
}
else
{
printf("\r\n key[%s],data[%s] insert success %d",p->key,p->data,res);
}
}
hashtab_dump(h);
while(1)
{
p = (struct test_node*)malloc(sizeof(struct test_node));
assert(p != NULL);
printf("\r\n 请输入key 查询value的数值当可以等于\"quit\"时退出");
scanf("%s",p->key);
if(strcmp(p->key,"quit") == 0)
{
free(p);
break;
}
pres = hashtab_search(h,p->key);
if (pres == NULL)
{
printf("\r\n key[%s] search data failed",p->key);
}
else
{
printf("\r\n key[%s],search data[%s] success",p->key,pres);
}
free(p);
}
hashtab_dump(h);
while(1)
{
p = (struct test_node*)malloc(sizeof(struct test_node));
assert(p != NULL);
printf("\r\n 请输入key 删除节点的数值,当可以等于\"quit\"时退出");
scanf("%s",p->key);
if(strcmp(p->key,"quit") == 0)
{
free(p);
break;
}
node = hashtab_delete(h,p->key);
if (node == NULL)
{
printf("\r\n key[%s] delete node failed ",p->key);
}
else
{
printf("\r\n key[%s],delete data[%s] success",node->key,node->data);
h->hash_node_free(node);
}
free(p);
hashtab_dump(h);
}
hashtab_destory(h);
#ifdef MEMORY_TEST
muntrace();
#endif
return 0;
}

View File

@ -0,0 +1,53 @@
/*************************************************************************
> File Name: listhash.h
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-11-06
> Desc: linux内核模块hashtab编写用户层hashtab接口
linux-4.19.1\security\selinux\ss\hashtab.c
linux-4.19.1\security\selinux\ss\hashtab.h
************************************************************************/
#ifndef __HASHTAB_H__
#define __HASHTAB_H__
typedef struct _hashtab_node
{
void * key;
void * data;
struct _hashtab_node *next;
}hashtab_node;
typedef struct _hashtab
{
hashtab_node **htables; /*哈希桶*/
int size; /*哈希桶的最大数量*/
int nel; /*哈希桶中元素的个数*/
int (*hash_value)(struct _hashtab *h,const void *key); /*哈希函数*/
int (*keycmp)(struct _hashtab *h,const void *key1,const void *key2);/*哈希key比较函数当哈希数值一致时使用*/
void (*hash_node_free)(hashtab_node *node);
}hashtab;
#define HASHTAB_MAX_NODES (0xffffffff)
typedef int (*hash_key_func)(struct _hashtab *h,const void *key); /*哈希函数*/
typedef int (*keycmp_func)(struct _hashtab *h,const void *key1,const void *key2);/*哈希key比较函数当哈希数值一致时使用*/
typedef void (*hash_node_free_func)(hashtab_node *node);
/*根据当前结构体元素的地址,获取到结构体首地址*/
#define offsetof(TYPE,MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container(ptr,type,member) ({\
const typeof( ((type *)0)->member) *__mptr = (ptr);\
(type *) ( (char *)__mptr - offsetof(type,member));})
hashtab * hashtab_create(int size,hash_key_func hash_value,
keycmp_func keycmp,hash_node_free_func hash_node_free);
void hashtab_destory(hashtab *h);
int hashtab_insert(hashtab * h,void *key,void *data);
hashtab_node *hashtab_delete(hashtab *h, void *key);
void *hashtab_search(hashtab*h,void *key);
#endif

View File

@ -0,0 +1,186 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
/* One implementation of hash table with linear probing. */
#define HASH_SHIFT 4
#define HASH_SIZE (1 << HASH_SHIFT)
#define HASH_MASK (HASH_SIZE - 1)
struct hash_table {
unsigned int used;
unsigned long entry[HASH_SIZE];
};
void hash_table_reset(struct hash_table *table)
{
int i;
table->used = 0;
for (i = 0; i < HASH_SIZE; i++)
table->entry[i] = ~0;
}
unsigned int hash_function(unsigned long value)
{
return value & HASH_MASK;
}
void dump_hash_table(struct hash_table *table)
{
int i;
for (i = 0; i < HASH_SIZE; i++) {
if (table->entry[i] == ~0)
printf("%2u: nil \n", i);
else
printf("%2u:%10lu -> %2u\n",
i, table->entry[i],
hash_function(table->entry[i]));
}
}
void hash_function_test()
{
int i;
srandom(time(NULL));
for (i = 0; i < 10; i++) {
unsigned long val = random();
printf("%10lu -> %2u\n", val, hash_function(val));;
}
}
unsigned int next_probe(unsigned int prev_key)
{
return (prev_key + 1) & HASH_MASK;
}
void next_probe_test()
{
int i;
unsigned int key1, key2;
key1 = 0;
for (i = 0; i < HASH_SIZE; i++) {
key2 = next_probe(key1);
printf("%2u -> %2u\n", key1, key2);
key1 = key2;
}
}
void hash_table_add(struct hash_table *table, unsigned long value)
{
unsigned int key = hash_function(value);
if (table->used >= HASH_SIZE)
return;
while (table->entry[key] != ~0)
key = next_probe(key);
table->entry[key] = value;
table->used++;
}
unsigned int hash_table_slot(struct hash_table *table, unsigned long value)
{
int i;
unsigned int key = hash_function(value);
for (i = 0; i < HASH_SIZE; i++) {
if (table->entry[key] == value || table->entry[key] == ~0)
break;
key = next_probe(key);
}
return key;
}
bool hash_table_find(struct hash_table *table, unsigned long value)
{
return table->entry[hash_table_slot(table, value)] == value;
}
void hash_table_del(struct hash_table *table, unsigned long value)
{
unsigned int i, j, k;
if (!hash_table_find(table, value))
return;
i = j = hash_table_slot(table, value);
while (true) {
table->entry[i] = ~0;
do {
j = next_probe(j);
if (table->entry[j] == ~0)
return;
k = hash_function(table->entry[j]);
} while ((i <= j) ? (i < k && k <= j) : (i < k || k <= j));
table->entry[i] = table->entry[j];
i = j;
}
table->used++;
}
void hash_table_add_test()
{
struct hash_table table;
hash_table_reset(&table);
hash_table_add(&table, 87645);
printf("Table has%s 87645\n",
hash_table_find(&table, 87645) ? "":"n't");
printf("Table has%s 87647\n",
hash_table_find(&table, 87647) ? "":"n't");
}
void hash_table_del_test1()
{
struct hash_table table;
hash_table_reset(&table);
hash_table_add(&table, 0x1ff0);
hash_table_add(&table, 0x2ff0);
hash_table_add(&table, 0x3ff0);
dump_hash_table(&table);
printf("=== Remove 0x1ff0\n");
hash_table_del(&table, 0x1ff0);
dump_hash_table(&table);
}
void hash_table_del_test2()
{
struct hash_table table;
hash_table_reset(&table);
hash_table_add(&table, 0x1ff0);
hash_table_add(&table, 0x1ff1);
hash_table_add(&table, 0x1ff2);
hash_table_add(&table, 0x2ff0);
dump_hash_table(&table);
printf("=== Remove 0x1ff0\n");
hash_table_del(&table, 0x1ff0);
dump_hash_table(&table);
}
int main()
{
//hash_function_test();
//next_probe_test();
//hash_table_add_test();
hash_table_del_test2();
return 0;
}

114
c-cpp/19_Dlisthash/Dlist.h Executable file
View File

@ -0,0 +1,114 @@
/*************************************************************************
> File Name: Dlist.h
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-11-08
> Desc: linux内核源码双向链表实现include/linux/list.h
************************************************************************/
#ifndef _LIST_HEAD_H
#define _LIST_HEAD_H
// 双向链表节点
struct list_head {
struct list_head *next, *prev;
};
// 初始化节点设置name节点的前继节点和后继节点都是指向name本身。
#define LIST_HEAD_INIT(name) { &(name), &(name) }
// 定义表头(节点)新建双向链表表头name并设置name的前继节点和后继节点都是指向name本身。
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
// 初始化节点将list节点的前继节点和后继节点都是指向list本身。
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
// 添加节点将new插入到prev和next之间。
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
// 添加new节点将new添加到head之后是new称为head的后继节点。
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
// 添加new节点将new添加到head之前即将new添加到双链表的末尾。
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
// 从双链表中删除entry节点。
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
// 从双链表中删除entry节点。
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
}
// 从双链表中删除entry节点。
static inline void __list_del_entry(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
}
// 从双链表中删除entry节点并将entry节点的前继节点和后继节点都指向entry本身。
static inline void list_del_init(struct list_head *entry)
{
__list_del_entry(entry);
INIT_LIST_HEAD(entry);
}
// 用new节点取代old节点
static inline void list_replace(struct list_head *old,
struct list_head *new)
{
new->next = old->next;
new->next->prev = new;
new->prev = old->prev;
new->prev->next = new;
}
// 双链表是否为空
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
// 获取"MEMBER成员"在"结构体TYPE"中的位置偏移
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
// 根据"结构体(type)变量"中的"域成员变量(member)的指针(ptr)"来获取指向整个结构体变量的指针
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
// 遍历双向链表
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
#endif

View File

@ -0,0 +1,398 @@
/*************************************************************************
> File Name: LinkedHashMap.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-11-08
> Desc:
************************************************************************/
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include "Dlist.h"
#include "LinkedHashMap.h"
LinkedHashMap *LinkedHashMap_Create(int size,int nel_max,
hash_value_func hash_value,keycmp_func keycmp,
hash_node_free_func hash_node_free)
{
int i = 0;
LinkedHashMap *h = NULL;
if ((size <= 0) || (hash_value == NULL) || (keycmp == NULL))
{
return NULL;
}
h = (LinkedHashMap *)malloc(sizeof(LinkedHashMap));
if (h == NULL)
{
return NULL;
}
h->hTabs = (LiskedHashMapNode**)malloc(sizeof(LiskedHashMapNode*) *size);
if (h->hTabs == NULL)
{
return NULL;
}
h->size = size;
h->nel = 0;
h->nel_max = nel_max;
h->hash_value = hash_value;
h->keycmp = keycmp;
h->hash_node_free = hash_node_free;
for (i = 0; i < size; i++)
{
h->hTabs[i] = NULL;
}
INIT_LIST_HEAD(&(h->header));
return h;
}
void LinkedHashMap_destory(LinkedHashMap *h)
{
struct list_head * pos = NULL;
struct list_head * next = NULL;
LiskedHashMapNode * ptmp = NULL;
if (h == NULL)
{
return;
}
list_for_each_safe(pos,next,&h->header)
{
ptmp = container_of(pos,LiskedHashMapNode,Dlist_node);
/*从双向链表中删除*/
list_del_init(pos);
if (h->hash_node_free != NULL)
{
h->hash_node_free(ptmp,1);
}
}
free(h->hTabs);
free(h);
return;
}
int LinkedHashMap_insert(LinkedHashMap *h,void *key,void *data)
{
int i = 0;
int hPos = 0;
struct list_head *pos = NULL;
LiskedHashMapNode *cur = NULL;
LiskedHashMapNode *prev = NULL;
hPos = h->hash_value(h,key);
cur = h->hTabs[hPos];
while((cur != NULL)&& (h->keycmp(h,key,cur->key) != 0))
{
prev = cur;
cur = cur->next;
}
if(cur == NULL)
{
/*链表节点满时,取表头节点,从当前哈希表和双向链表中都删除*/
if(h->nel_max == h->nel)
{
cur = LinkedHashMap_delete(h,list_entry(h->header.next,LiskedHashMapNode,Dlist_node)->key);
assert(cur != NULL);
/*释放节点key 和data的内容*/
h->hash_node_free(cur,0);
}
else/*链表不满时,创建新的节点*/
{
cur = (LiskedHashMapNode *)malloc(sizeof(LiskedHashMapNode));
if (cur == NULL)
{
return 1;
}
}
/*插入到hash桶中*/
if(prev == NULL)
{
cur->next = h->hTabs[hPos];
h->hTabs[hPos] = cur;
}
else
{
cur->next = prev->next;
prev->next= cur;
}
h->nel++;
}
else
{
/*从双向链表中删除*/
list_del_init(&(cur->Dlist_node));
/*只删除key 和data的内存*/
h->hash_node_free(cur,0);
}
/*赋值*/
cur->key = key;
cur->data = data;
/*加的双向链表尾部*/
list_add_tail(&(cur->Dlist_node),&(h->header));
return 0;
}
LiskedHashMapNode * LinkedHashMap_delete(LinkedHashMap *h,void *key)
{
int hPos = 0;
struct list_head *pos = NULL;
LiskedHashMapNode *cur = NULL;
LiskedHashMapNode *prev = NULL;
/*查找当前节点*/
hPos = h->hash_value(h,key);
cur = h->hTabs[hPos];
while((cur != NULL)&& (h->keycmp(h,key,cur->key) != 0))
{
prev = cur;
cur = cur->next;
}
if (cur == NULL)
{
return NULL;
}
/*从哈希桶中删除*/
if(prev == NULL)
{
h->hTabs[hPos] = cur->next;
}
else
{
prev->next = cur->next;
}
/*从双向链表中删除*/
list_del_init(&(cur->Dlist_node));
h->nel--;
return cur;
}
void *LinkedHashMap_search(LinkedHashMap *h,void *key)
{
int hPos = 0;
LiskedHashMapNode *cur = NULL;
/*查找当前节点*/
hPos = h->hash_value(h,key);
cur = h->hTabs[hPos];
while((cur != NULL)&& (h->keycmp(h,key,cur->key) != 0))
{
cur = cur->next;
}
if (cur == NULL)
{
return NULL;
}
/*从双向链表中删除节点,加入尾部*/
if (h->header.prev != &(cur->Dlist_node))
{
list_del_init(&(cur->Dlist_node));
list_add_tail(&(cur->Dlist_node),&(h->header));
}
return cur->data;
}
void LinkedHashMap__dump(LinkedHashMap *h)
{
int i = 0;
LiskedHashMapNode * cur = NULL;
struct list_head *pos = NULL;
if (h == NULL)
{
return ;
}
printf("\r\n----开始--size[%d],nel[%d]------------",h->size,h->nel);
for( i = 0; i < h->size; i ++)
{
printf("\r\n htables[%d]:",i);
cur = h->hTabs[i];
while((cur != NULL))
{
printf("key[%s],data[%s] ",cur->key,cur->data);
cur = cur->next;
}
}
printf("\r\n--------------------------------------------------------\r\n");
list_for_each(pos,&(h->header))
{
cur = list_entry(pos,LiskedHashMapNode,Dlist_node);
printf("key[%s] ",cur->key);
}
printf("\r\n----结束--size[%d],nel[%d]------------",h->size,h->nel);
}
struct test_node
{
char key[80];
char data[80];
};
unsigned int siample_hash(const char *str)
{
register unsigned int hash = 0;
register unsigned int seed = 131;
while(*str)
{
hash = hash*seed + *str++;
}
return hash & (0x7FFFFFFF);
}
int hashtab_hvalue(LinkedHashMap *h,const void *key)
{
return (siample_hash(key) % h->size);
}
int hashtab_keycmp(LinkedHashMap *h,const void *key1,const void *key2)
{
return strcmp(key1,key2);
}
void hashtab_node_free(LiskedHashMapNode *node,int flg)
{
struct test_node * ptmp = NULL;
ptmp = list_entry(node->key,struct test_node,key);
free(ptmp);
if (flg)
{
free(node);
}
}
int main ()
{
int i = 0;
int res = 0;
char *pres = NULL;
LiskedHashMapNode * node = NULL;
struct test_node *p = NULL;
LinkedHashMap *h = NULL;
setenv("MALLOC_TRACE","1.txt",1);
mtrace();
h = LinkedHashMap_Create(3,6,hashtab_hvalue,hashtab_keycmp,hashtab_node_free);
assert(h!= NULL);
while(1)
{
p = (struct test_node*)malloc(sizeof(struct test_node));
assert(p != NULL);
printf("\r\n 请输入key 和value当可以等于\"quit\"时退出");
scanf("%s",p->key);
scanf("%s",p->data);
if(strcmp(p->key,"quit") == 0)
{
free(p);
break;
}
res = LinkedHashMap_insert(h,p->key,p->data);
if (res != 0)
{
free(p);
printf("\r\n key[%s],data[%s] insert failed %d",p->key,p->data,res);
}
else
{
printf("\r\n key[%s],data[%s] insert success %d",p->key,p->data,res);
}
LinkedHashMap__dump(h);
}
while(1)
{
p = (struct test_node*)malloc(sizeof(struct test_node));
assert(p != NULL);
printf("\r\n 请输入key 查询value的数值当可以等于\"quit\"时退出");
scanf("%s",p->key);
if(strcmp(p->key,"quit") == 0)
{
free(p);
break;
}
pres = LinkedHashMap_search(h,p->key);
if (pres == NULL)
{
printf("\r\n key[%s] search data failed",p->key);
}
else
{
printf("\r\n key[%s],search data[%s] success",p->key,pres);
}
free(p);
LinkedHashMap__dump(h);
}
while(1)
{
p = (struct test_node*)malloc(sizeof(struct test_node));
assert(p != NULL);
printf("\r\n 请输入key 删除节点的数值,当可以等于\"quit\"时退出");
scanf("%s",p->key);
if(strcmp(p->key,"quit") == 0)
{
free(p);
break;
}
node = LinkedHashMap_delete(h,p->key);
if (node == NULL)
{
printf("\r\n key[%s] delete node failed ",p->key);
}
else
{
printf("\r\n key[%s],delete data[%s] success",node->key,node->data);
h->hash_node_free(node,1);
}
free(p);
LinkedHashMap__dump(h);
}
LinkedHashMap_destory(h);
muntrace();
return 0;
}

View File

@ -0,0 +1,40 @@
/*************************************************************************
> File Name: LinkedHashMap.h
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-11-08
> Desc:
************************************************************************/
#ifndef __LINKED_HASH_MAP__
#define __LINKED_HASH_MAP__
/*数据存放节点*/
typedef struct _lisked_hash_map_node
{
void *key; /*键*/
void *data; /*数据*/ZZ
struct _lisked_hash_map_node *next; /*哈希冲突时,用来挂接后续节点*/
struct list_head Dlist_node;/*用来挂接双向链表*/
}LiskedHashMapNode;
typedef struct _lisked_hash_map
{
LiskedHashMapNode **hTabs;/*哈希桶*/
struct list_head header;/*双向循环链表头*/
int size; /**/
int nel_max; /*支持最大节点数*/
int nel; /*当前节点数*/
int (*hash_value)(struct _lisked_hash_map *h,const void *key); /*哈希函数*/
int (*keycmp)(struct _lisked_hash_map *h,const void *key1,const void *key2);/*哈希key比较函数当哈希数值一致时使用*/
void (*hash_node_free)(LiskedHashMapNode *node,int flg);/*用来释放节点内存*/
}LinkedHashMap;
typedef int (*hash_value_func)(struct _lisked_hash_map *h,const void *key); /*哈希函数*/
typedef int (*keycmp_func)(struct _lisked_hash_map *h,const void *key1,const void *key2);/*哈希key比较函数当哈希数值一致时使用*/
typedef void (*hash_node_free_func)(LiskedHashMapNode *node,int flg);
LiskedHashMapNode * LinkedHashMap_delete(LinkedHashMap *h,void *key);
#endif

View File

@ -0,0 +1,83 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
/* Implement binary tree in array */
#define MAX_TREE_NODES (1 << 8)
struct node {
int data;
};
struct binary_tree {
union {
unsigned long nodes;
struct node *n[MAX_TREE_NODES];
};
};
void init_binary_tree(struct binary_tree *tree)
{
int i;
for(i = 0; i < MAX_TREE_NODES; i++) {
tree->n[i] = NULL;
}
}
struct node* create_node(int data)
{
struct node* n;
n = malloc(sizeof(struct node));
if (n)
n->data = data;
return n;
}
void fake_a_tree(struct binary_tree* tree)
{
/* data is in ordered */
int i, data[10] = {7, 4, 9, 2, 6, 8, 10, 1, 3, 5};
init_binary_tree(tree);
/* root start at 1 */
for (i = 0; i < 10; i++)
tree->n[i+1] = create_node(data[i]);
tree->nodes = 10;
}
void _in_order(struct binary_tree* tree, int index)
{
if (!tree->n[index])
return;
/* left child at (index << 1) */
_in_order(tree, index << 1);
printf("[%2d]: %4d\n", index, tree->n[index]->data);
/* right child at (index << 1) + 1 */
_in_order(tree, (index << 1) + 1);
}
void in_order(struct binary_tree* tree)
{
_in_order(tree, 1);
}
int main()
{
struct binary_tree tree;
fake_a_tree(&tree);
in_order(&tree);
return 0;
}

View File

@ -0,0 +1,213 @@
/*************************************************************************
> File Name: binarytree.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-11-12
> Desc:
************************************************************************/
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include"list_queue.h"
typedef struct _treenode
{
int data;
struct _treenode *lchild;
struct _treenode *rchild;
}Tnode,Tree;
void binarytree_create(Tree **Root)
{
int a = 0;
printf("\r\n输入节点数值((当输入为100时当前节点创建完成))):");
scanf("%d",&a);
if (a == 100)
{
*Root = NULL;
}
else
{
*Root = (Tnode *)malloc(sizeof(Tnode));
if (*Root == NULL)
{
return;
}
(*Root)->data = a;
printf("\r\n create %d 的左孩子:",a);
binarytree_create(&((*Root)->lchild));
printf("\r\n create %d 的右孩子:",a);
binarytree_create(&((*Root)->rchild));
}
return ;
}
void binarytree_destory(Tree *root)
{
if (root == NULL)
{
return;
}
binarytree_destory(root->lchild);
binarytree_destory(root->rchild);
free(root);
}
/*先序遍历:根结点--》左子树---》右子树*/
void binarytree_preorder(Tree *root)
{
if (root == NULL)
{
return;
}
printf(" %d ",root->data);
binarytree_preorder(root->lchild);
binarytree_preorder(root->rchild);
return;
}
/*中序遍历:左子树--》跟节点---》右子树*/
void binarytree_inorder(Tree *root)
{
if (root == NULL)
{
return;
}
binarytree_inorder(root->lchild);
printf(" %d ",root->data);
binarytree_inorder(root->rchild);
return;
}
/*后序遍历:左子树---》右子树-》根节点*/
void binarytree_postorder(Tree *root)
{
if (root == NULL)
{
return;
}
binarytree_postorder(root->lchild);
binarytree_postorder(root->rchild);
printf(" %d ",root->data);
return;
}
void binarytree_levelorder(Tree * root)
{
list_queue *queue = NULL;
Tnode * node = NULL;
if(root == NULL)
{
return;
}
queue = list_queue_create();
/*根节点先入队*/
list_queue_enqueue(queue,(void *)root);
while(!list_queue_is_empty(queue))
{
list_queue_dequeue(queue,(void *)&node);
printf(" %d ",node->data);
if(node->lchild != NULL)
{
list_queue_enqueue(queue,(void *)node->lchild);
}
if(node->rchild != NULL)
{
list_queue_enqueue(queue,(void *)node->rchild);
}
}
free(queue);
}
/*打印叶子节点*/
void binarytree_printfleaf(Tree *root)
{
if (root == NULL)
{
return;
}
if ((root->lchild == NULL) && (root->rchild == NULL))
{
printf(" %d ",root->data);
}
else
{
binarytree_printfleaf(root->lchild);
binarytree_printfleaf(root->rchild);
}
}
/*打印叶子的个数*/
int binarytree_getleafnum(Tree*root)
{
if (root == NULL)
{
return 0;
}
if ((root->lchild == NULL) && (root->rchild == NULL))
{
return 1;
}
return binarytree_getleafnum(root->lchild) + binarytree_getleafnum(root->rchild);
}
/*打印数的高度*/
int binarytree_gethigh(Tree *root)
{
int lhigh = 0;
int rhigh = 0;
if (root == NULL)
{
return 0;
}
lhigh = binarytree_gethigh(root->lchild);
rhigh = binarytree_gethigh(root->rchild);
return ((lhigh > rhigh)?(lhigh + 1):(rhigh + 1));
}
int main()
{
Tree *root = NULL;
setenv("MALLOC_TRACE","1.txt",1);
mtrace();
printf("\r\n创建二叉树:");
binarytree_create(&root);
printf("\r\n先序遍历二叉树:");
binarytree_preorder(root);
printf("\r\n中序遍历二叉树:");
binarytree_inorder(root);
printf("\r\n后序遍历二叉树:");
binarytree_postorder(root);
printf("\r\n层次遍历二叉树:");
binarytree_levelorder(root);
printf("\r\n打印二叉树叶子节点:");
binarytree_printfleaf(root);
printf("\r\n打印二叉树叶子节点个数:%d",binarytree_getleafnum(root));
printf("\r\n打印二叉树高度:%d",binarytree_gethigh(root));
binarytree_destory(root);
muntrace();
return 0;
}

View File

@ -0,0 +1,85 @@
/*************************************************************************
> File Name: list_queue.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-13
> Desc:
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"./list_queue.h"
/*创建队列头*/
list_queue *list_queue_create()
{
list_queue * queue = NULL;
queue = (list_queue *)malloc(sizeof(list_queue));
if(queue == NULL)
{
return NULL;
}
queue->num = 0;
queue->head = NULL;
queue->tail = NULL;
return queue;
}
int list_queue_enqueue(list_queue *queue,void *data)
{
queue_node *ptmp = NULL;
if(queue == NULL)
{
return -1;
}
ptmp = (queue_node *)malloc(sizeof(queue_node));
if (ptmp == NULL)
{
return -1;
}
ptmp->data = data;
ptmp->next = NULL;
if (queue->head == NULL)
{
queue->head = ptmp;
}
else
{
queue->tail->next = ptmp;
}
queue->tail = ptmp;
queue->num++;
return 0;
}
/*出队*/
int list_queue_dequeue(list_queue *queue,void **data)
{
queue_node * ptmp = NULL;
if ((queue == NULL) || (data == NULL) || list_queue_is_empty(queue))
{
return -1;
}
*data = queue->head->data;
ptmp = queue->head;
queue->head = queue->head->next;
queue->num--;
if (queue->head == NULL)
{
queue->tail = NULL;
}
free(ptmp);
return 0;
}

View File

@ -0,0 +1,30 @@
/*************************************************************************
> File Name: list_queue.h
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-10-13
> Desc:
************************************************************************/
#ifndef LINK_LIST_QUEUE_H
#define LINK_LIST_QUEUE_H
typedef struct _list_queue_node
{
void *data;
struct _list_queue_node *next;
}queue_node;
typedef struct _list_queue
{
int num;
queue_node *head;
queue_node *tail;
}list_queue;
#define list_queue_is_empty(queue) ((queue->num) == 0)
list_queue *list_queue_create();
int list_queue_enqueue(list_queue *queue,void *data);
int list_queue_dequeue(list_queue *queue,void **data);
#endif

View File

@ -0,0 +1,322 @@
/*************************************************************************
> File Name: binarysearchtree.c
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-11-12
> Desc:
************************************************************************/
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include"binarysearchtree.h"
bstree *bstree_create(compare_fuc compare,destory_fuc destory)
{
bstree *tree = NULL;
tree = (bstree*)malloc(sizeof(bstree));
if (tree == NULL)
{
return NULL;
}
tree->size = 0;
tree->compare = compare;
tree->destory = destory;
tree->root = NULL;
return tree;
}
bstree_node *bstree_search(bstree *tree,mytype data)
{
bstree_node *node = NULL;
int res = 0;
if ((tree == NULL) || (bstree_is_empty(tree)))
{
return NULL;
}
node = tree->root;
while(node != NULL)
{
res = tree->compare(data,node->data);
if(res == 0)
{
return node;
}
else if (res > 0)
{
node = node->rchild;
}
else
{
node = node->lchild;
}
}
return NULL;
}
int bstree_insert(bstree * tree, mytype data)
{
bstree_node *node = NULL;
bstree_node *tmp = NULL;
int res = 0;
if (tree == NULL)
{
return -1;
}
node = (bstree_node *)malloc(sizeof(bstree_node));
if (node == NULL)
{
return -2;
}
node->data = data;
node->lchild = NULL;
node->rchild = NULL;
/*如果二叉树为空,直接挂到根节点*/
if (bstree_is_empty(tree))
{
tree->root = node;
tree->size++;
return 0;
}
tmp = tree->root;
while(tmp != NULL)
{
res = tree->compare(data,tmp->data);
if (res > 0) /*去右孩子查找*/
{
if (tmp->rchild == NULL)
{
tmp->rchild = node;
tree->size++;
return 0;
}
tmp = tmp->rchild;
}
else /*去左孩子查找*/
{
if(tmp->lchild == NULL)
{
tmp->lchild = node;
tree->size++;
return 0;
}
tmp = tmp->lchild;
}
}
return -3;
}
int bstree_delete(bstree *tree,mytype data)
{
bstree_node *node = NULL;/*要删除的节点*/
bstree_node *pnode = NULL;/*要删除节点的父节点*/
bstree_node *minnode = NULL;/*要删除节点的父节点*/
bstree_node *pminnode = NULL;/*要删除节点的父节点*/
mytype tmp = 0;
int res = 0;
if ((tree == NULL) || (bstree_is_empty(tree)))
{
return -1;
}
node = tree->root;
while ((node != NULL) && ((res = tree->compare(data,node->data)) != 0))
{
pnode = node;
if(res > 0)
{
node = node->rchild;
}
else
{
node = node->lchild;
}
}
/*说明要删除的节点不存在*/
if (node == NULL)
{
return -2;
}
/*1、如果要删除node有2个子节点需要找到右子树的最小节点minnode
* minnode和node节点数据minnode节点就是要删除的节点
* node和pnode节点指向要删除的节点*/
if ((node->lchild != NULL) && (node->rchild != NULL))
{
minnode = node->rchild;
pminnode = node;
while(minnode->lchild != NULL)
{
pminnode = minnode;
minnode = minnode->lchild;
}
/*node 节点和minnode节点数据互换*/
tmp = node->data;
node->data = minnode->data;
minnode->data = tmp;
/*更新要删除的节点和其父节点*/
node = minnode;
pnode = pminnode;
}
/*2、当前要删除的节点只有左孩子或者右孩子时直接父节点的直向删除的节点*/
if (node->lchild != NULL)
{
minnode = node->lchild;
}
else if (node->rchild != NULL)
{
minnode = node->rchild;
}
else
{
minnode = NULL;
}
if (pnode == NULL)/*当要删除的时根节点时,*/
{
tree->root = minnode;
}
else if (pnode->lchild == node)
{
pnode->lchild = minnode;
}
else
{
pnode->rchild = minnode;
}
tree->size--;
free (node);
return 0;
}
/*采用递归方式删除节点*/
void bstree_destory_node(bstree *tree,bstree_node *root)
{
if (root == NULL)
{
return;
}
bstree_destory_node(tree,root->lchild);
bstree_destory_node(tree,root->rchild);
free(root);
}
/*二叉搜索树销毁*/
void bstree_destory(bstree *tree)
{
bstree_destory_node(tree,tree->root);
free(tree);
return;
}
/*中序遍历打印树节点*/
void bstree_inorder_node(bstree_node *root)
{
bstree_node *node = NULL;
if (root == NULL)
{
return;
}
bstree_inorder_node(root->lchild);
printf(" %d ",root->data);
bstree_inorder_node(root->rchild);
return;
}
void bstree_dump(bstree *tree)
{
bstree_node *node = NULL;
if ((tree == NULL) || (bstree_is_empty(tree)))
{
printf("\r\n 当前树是空树");
}
printf("\r\nSTART-----------------%d------------\r\n",tree->size);
bstree_inorder_node(tree->root);
printf("\r\nEND---------------------------------",tree->size);
}
int bstree_compare(mytype key1,mytype key2)
{
if (key1 == key2)
{
return 0;
}
else if (key1 > key2)
{
return 1;
}
else
{
return -1;
}
}
int main()
{
bstree *tree = NULL;
bstree_node *node = NULL;
mytype data = 0;
int res = 0;
setenv("MALLOC_TRACE","1.txt",1);
mtrace();
tree = bstree_create(bstree_compare,NULL);
assert(tree != NULL);
while(1)
{
printf("\r\n插入一个数字输入100时退出");
scanf("%d",&data);
if(data == 100)break;
res = bstree_insert(tree,data);
printf("\r\n %d 插入%s成功",data,(res != 0)?(""):(" "));
}
bstree_dump(tree);
while(1)
{
printf("\r\n查询一个数字输入100时退出");
scanf("%d",&data);
if(data == 100)break;
node = bstree_search(tree,data);
printf("\r\n %d %s存在树中",data,(node == NULL)?(""):(" "));
}
bstree_dump(tree);
while(1)
{
printf("\r\n删除一个数字输入100时退出");
scanf("%d",&data);
if(data == 100)break;
res = bstree_delete(tree,data);
printf("\r\n %d 删除%s成功",data,(res != 0)?(""):(" "));
bstree_dump(tree);
}
bstree_destory(tree);
muntrace();
return 0;
}

View File

@ -0,0 +1,34 @@
/*************************************************************************
> File Name: binarysearchtree.h
> Author: jinshaohui
> Mail: jinshaohui789@163.com
> Time: 18-11-12
> Desc:
************************************************************************/
#ifndef __BINARY_SEARCH_TREE__
#define __BINARY_SEARCH_TREE__
typedef int mytype;
typedef struct _bstree_node
{
mytype data;
struct _bstree_node *lchild;
struct _bstree_node *rchild;
}bstree_node;
typedef struct _bstree
{
int size;
int (*compare)(mytype key1,mytype key2);
int (*destory)(mytype data);
bstree_node *root;
}bstree;
typedef int (*compare_fuc)(mytype key1,mytype key2);
typedef int (*destory_fuc)(mytype data);
#define bstree_is_empty(tree) (tree->size == 0)
bstree *bstree_create(compare_fuc compare,destory_fuc destory);
#endif

View File

@ -0,0 +1,197 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
enum child_dir {
left_child,
right_child,
root,
};
struct node {
unsigned long data;
struct node *left;
struct node *right;
};
struct root {
struct node *r;
};
void dump(struct node *node, int level, enum child_dir dir)
{
if (!node)
return;
dump(node->right, level + 1, right_child);
if (dir == left_child)
printf("%*s\n", level*3, "|");
printf("%*s - %05lu\n", level*3, " ", node->data);
if (dir == right_child)
printf("%*s\n", level*3, "|");
dump(node->left, level + 1, left_child);
}
struct node* find(struct root *root, unsigned long data)
{
struct node* n = root->r;
while (n) {
if (n->data == data)
return n;
if (data < n->data)
n = n->left;
else
n = n->right;
}
return NULL;
}
struct node* new_node(unsigned long data)
{
struct node *n;
n = malloc(sizeof(struct node));
n->data = data;
n->left = n->right = NULL;
return n;
}
void insert(struct root *root, struct node *new)
{
struct node *parent;
if (!root->r) {
root->r = new;
return;
}
parent = root->r;
while (true) {
/* Don't support duplicate data */
if (new->data == parent->data)
break;
if (new->data < parent->data) {
if (!parent->left) {
parent->left = new;
break;
}
parent = parent->left;
} else {
if (!parent->right) {
parent->right = new;
break;
}
parent = parent->right;
}
}
}
struct node* delete(struct root *root, unsigned long data)
{
struct node *n = root->r, **p = &root->r;
struct node *child;
while (n && n->data != data) {
if (data < n->data) {
p = &n->left;
n = n->left;
} else {
p = &n->right;
n = n->right;
}
}
if (!n)
return NULL;
if (n->left && n->right) {
struct node *rn = n->right, **rp = &n->right;
while (rn->left) {
rp = &rn->left;
rn = rn->left;
}
n->data = rn->data;
n = rn;
p = rp;
}
child = n->left ? n->left : n->right;
*p = child;
return NULL;
}
void insert_test()
{
struct root tree;
struct node* n;
tree.r = NULL;
insert(&tree, new_node(9));
insert(&tree, new_node(5));
insert(&tree, new_node(2));
insert(&tree, new_node(8));
insert(&tree, new_node(18));
insert(&tree, new_node(13));
insert(&tree, new_node(21));
insert(&tree, new_node(20));
dump(tree.r, 0, root);
n = find(&tree, 18);
if (n && n->data == 18)
printf("Get 18\n");
}
void delete_test()
{
struct root tree;
struct node* n;
tree.r = NULL;
insert(&tree, new_node(9));
insert(&tree, new_node(5));
insert(&tree, new_node(2));
insert(&tree, new_node(8));
insert(&tree, new_node(18));
insert(&tree, new_node(13));
insert(&tree, new_node(21));
insert(&tree, new_node(20));
dump(tree.r, 0, root);
delete(&tree, 20);
printf("Delete 20\n");
dump(tree.r, 0, root);
delete(&tree, 9);
printf("Delete 9\n");
dump(tree.r, 0, root);
}
int main()
{
//insert_test();
delete_test();
return 0;
}

160
c-cpp/28_heap/heap.c Normal file
View File

@ -0,0 +1,160 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
/* Implement heap */
#define MAX_HEAP_SIZE (1 << 8)
struct element {
int data;
};
struct heap {
union {
unsigned long elements;
struct element *elem[MAX_HEAP_SIZE];
};
};
void init_heap(struct heap *heap)
{
int i;
for(i = 0; i < MAX_HEAP_SIZE; i++) {
heap->elem[i] = NULL;
}
}
void dump_heap(struct heap *heap, int index)
{
struct element *elem;
int level;
if (index > heap->elements)
return;
elem = heap->elem[index];
level = fls(index);
dump_heap(heap, index * 2 + 1);
if (!(index % 2) && index != 1)
printf("%*s\n", level*3, "|");
printf("%*s - %05d\n", level*3, " ", elem->data);
if (index % 2 && index != 1)
printf("%*s\n", level*3, "|");
dump_heap(heap, index * 2);
}
void dump(struct heap *heap, int elements)
{
int i;
for (i = 1; i <= elements; i++)
printf("[%02d]: %4d\n", i, heap->elem[i]->data);
}
struct element* create_element(int data)
{
struct element *elem;
elem = malloc(sizeof(struct element));
if (elem)
elem->data = data;
return elem;
}
void fake_a_heap(struct heap *heap)
{
/* data is in ordered */
int i, data[10] = {7, 4, 9, 2, 6, 8, 10, 1, 3, 5};
init_heap(heap);
/* root start at 1 */
for (i = 0; i < 10; i++)
heap->elem[i+1] = create_element(data[i]);
heap->elements = 10;
}
void swap(struct heap *heap, int i, int j)
{
struct element *tmp;
tmp = heap->elem[j];
heap->elem[j] = heap->elem[i];
heap->elem[i] = tmp;
}
void heapify(struct heap *heap, int parent)
{
struct element **elem = heap->elem;
int elements = heap->elements;
int left, right, max;
while (true) {
left = parent * 2;
right = left + 1;
max = parent;
if (left <= elements && elem[max]->data < elem[left]->data)
max = left;
if (right <= elements && elem[max]->data < elem[right]->data)
max = right;
if (max == parent)
break;
swap(heap, max, parent);
parent = max;
}
}
void build_heap(struct heap *heap)
{
int i;
for (i = heap->elements / 2; i >= 1; i--)
heapify(heap, i);
}
int heap_sort(struct heap *heap)
{
int elements = heap->elements;
while (heap->elements) {
swap(heap, 1, heap->elements);
heap->elements--;
heapify(heap, 1);
}
return elements;
}
int main()
{
struct heap heap;
int elements;
fake_a_heap(&heap);
dump_heap(&heap, 1);
printf("After Heapify:\n");
build_heap(&heap);
dump_heap(&heap, 1);
printf("After Heap sort:\n");
elements = heap_sort(&heap);
dump(&heap, elements);
return 0;
}

197
c-cpp/bst.c Normal file
View File

@ -0,0 +1,197 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
enum child_dir {
left_child,
right_child,
root,
};
struct node {
unsigned long data;
struct node *left;
struct node *right;
};
struct root {
struct node *r;
};
void dump(struct node *node, int level, enum child_dir dir)
{
if (!node)
return;
dump(node->right, level + 1, right_child);
if (dir == left_child)
printf("%*s\n", level*3, "|");
printf("%*s - %05lu\n", level*3, " ", node->data);
if (dir == right_child)
printf("%*s\n", level*3, "|");
dump(node->left, level + 1, left_child);
}
struct node* find(struct root *root, unsigned long data)
{
struct node* n = root->r;
while (n) {
if (n->data == data)
return n;
if (data < n->data)
n = n->left;
else
n = n->right;
}
return NULL;
}
struct node* new_node(unsigned long data)
{
struct node *n;
n = malloc(sizeof(struct node));
n->data = data;
n->left = n->right = NULL;
return n;
}
void insert(struct root *root, struct node *new)
{
struct node *parent;
if (!root->r) {
root->r = new;
return;
}
parent = root->r;
while (true) {
/* Don't support duplicate data */
if (new->data == parent->data)
break;
if (new->data < parent->data) {
if (!parent->left) {
parent->left = new;
break;
}
parent = parent->left;
} else {
if (!parent->right) {
parent->right = new;
break;
}
parent = parent->right;
}
}
}
struct node* delete(struct root *root, unsigned long data)
{
struct node *n = root->r, **p = &root->r;
struct node *child;
while (n && n->data != data) {
if (data < n->data) {
p = &n->left;
n = n->left;
} else {
p = &n->right;
n = n->right;
}
}
if (!n)
return NULL;
if (n->left && n->right) {
struct node *rn = n->right, **rp = &n->right;
while (rn->left) {
rp = &rn->left;
rn = rn->left;
}
n->data = rn->data;
n = rn;
p = rp;
}
child = n->left ? n->left : n->right;
*p = child;
return NULL;
}
void insert_test()
{
struct root tree;
struct node* n;
tree.r = NULL;
insert(&tree, new_node(9));
insert(&tree, new_node(5));
insert(&tree, new_node(2));
insert(&tree, new_node(8));
insert(&tree, new_node(18));
insert(&tree, new_node(13));
insert(&tree, new_node(21));
insert(&tree, new_node(20));
dump(tree.r, 0, root);
n = find(&tree, 18);
if (n && n->data == 18)
printf("Get 18\n");
}
void delete_test()
{
struct root tree;
struct node* n;
tree.r = NULL;
insert(&tree, new_node(9));
insert(&tree, new_node(5));
insert(&tree, new_node(2));
insert(&tree, new_node(8));
insert(&tree, new_node(18));
insert(&tree, new_node(13));
insert(&tree, new_node(21));
insert(&tree, new_node(20));
dump(tree.r, 0, root);
delete(&tree, 20);
printf("Delete 20\n");
dump(tree.r, 0, root);
delete(&tree, 9);
printf("Delete 9\n");
dump(tree.r, 0, root);
}
int main()
{
//insert_test();
delete_test();
return 0;
}

63
f21 Normal file
View File

@ -0,0 +1,63 @@
// A Stack based C++ program to find next
// greater element for all array elements
// in same order as input.
#include <bits/stdc++.h>
using namespace std;
/* prints element and NGE pair for all
elements of arr[] of size n */
void printNGE(int arr[], int n)
{
stack<int> s;
unordered_map<int, int> mp;
/* push the first element to stack */
s.push(arr[0]);
// iterate for rest of the elements
for (int i = 1; i < n; i++) {
if (s.empty()) {
s.push(arr[i]);
continue;
}
/* if stack is not empty, then
pop an element from stack.
If the popped element is smaller
than next, then
a) print the pair
b) keep popping while elements are
smaller and stack is not empty */
while (s.empty() == false && s.top() < arr[i]) {
mp[s.top()] = arr[i];
s.pop();
}
/* push next to stack so that we can find
next smaller for it */
s.push(arr[i]);
}
/* After iterating over the loop, the remaining
elements in stack do not have the next smaller
element, so print -1 for them */
while (s.empty() == false) {
mp[s.top()] = -1;
s.pop();
}
for (int i=0; i<n; i++)
cout << arr[i] << " ---> " << mp[arr[i]] << endl;
}
/* Driver program to test above functions */
int main()
{
int arr[] = { 11, 13, 21, 3 };
int n = sizeof(arr) / sizeof(arr[0]);
printNGE(arr, n);
return 0;
}

View File

@ -34,7 +34,7 @@ func (this *Array) Len() uint {
//判断索引是否越界
func (this *Array) isIndexOutOfRange(index uint) bool {
if index >= this.length {
if index >= uint(cap(this.data)) {
return true
}
return false

View File

@ -45,3 +45,111 @@ func bs(a []int, v int, low, high int) int {
return bs(a, v, mid+1, high)
}
}
//查找第一个等于给定值的元素
func BinarySearchFirst(a []int, v int) int {
n := len(a)
if n == 0 {
return -1
}
low := 0
high := n - 1
for low <= high {
mid := (low + high) >> 1
if a[mid] > v {
high = mid - 1
} else if a[mid] < v {
low = mid + 1
} else {
if mid == 0 || a[mid-1] != v {
return mid
} else {
high = mid - 1
}
}
}
return -1
}
//查找最后一个值等于给定值的元素
func BinarySearchLast(a []int, v int) int {
n := len(a)
if n == 0 {
return -1
}
low := 0
high := n - 1
for low <= high {
mid := (low + high) >> 1
if a[mid] > v {
high = mid - 1
} else if a[mid] < v {
low = mid + 1
} else {
if mid == n-1 || a[mid+1] != v {
return mid
} else {
low = mid + 1
}
}
}
return -1
}
//查找第一个大于等于给定值的元素
func BinarySearchFirstGT(a []int, v int) int {
n := len(a)
if n == 0 {
return -1
}
low := 0
high := n - 1
for low <= high {
mid := (high + low) >> 1
if a[mid] > v {
high = mid - 1
} else if a[mid] < v {
low = mid + 1
} else {
if mid != n-1 && a[mid+1] > v {
return mid + 1
} else {
low = mid + 1
}
}
}
return -1
}
//查找最后一个小于等于给定值的元素
func BinarySearchLastLT(a []int, v int) int {
n := len(a)
if n == 0 {
return -1
}
low := 0
high := n - 1
for low <= high {
mid := (low + high) >> 1
if a[mid] > v {
high = mid - 1
} else if a[mid] < v {
low = mid + 1
} else {
if mid == 0 || a[mid-1] < v {
return mid - 1
} else {
high = mid - 1
}
}
}
return -1
}

View File

@ -25,3 +25,79 @@ func TestBinarySearchRecursive(t *testing.T) {
t.Fatal(BinarySearch(a, 4))
}
}
func TestBinarySearchFirst(t *testing.T) {
var a []int
a = []int{1, 2, 2, 2, 3, 4}
if BinarySearchFirst(a, 2) != 1 {
t.Fatal(BinarySearchFirst(a, 2))
}
a = []int{1, 2, 2, 2, 3, 4}
if BinarySearchFirst(a, 3) != 4 {
t.Fatal(BinarySearchFirst(a, 3))
}
}
func TestBinarySearchLast(t *testing.T) {
var a []int
a = []int{1, 2, 2, 2, 3, 4}
if BinarySearchLast(a, 2) != 3 {
t.Fatal(BinarySearchLast(a, 2))
}
a = []int{1, 2, 2, 2, 3, 4}
if BinarySearchLast(a, 3) != 4 {
t.Fatal(BinarySearchLast(a, 3))
}
}
func TestBinarySearchFirstGT(t *testing.T) {
var a []int
a = []int{1, 2, 2, 2, 3, 4}
if BinarySearchFirstGT(a, 2) != 4 {
t.Fatal(BinarySearchFirstGT(a, 2))
}
a = []int{1, 2, 2, 2, 3, 4}
if BinarySearchFirstGT(a, 1) != 1 {
t.Fatal(BinarySearchFirstGT(a, 1))
}
a = []int{1, 2, 2, 2, 3, 4}
if BinarySearchFirstGT(a, 3) != 5 {
t.Fatal(BinarySearchFirstGT(a, 3))
}
a = []int{1, 2, 2, 2, 3, 4}
if BinarySearchFirstGT(a, 4) != -1 {
t.Fatal(BinarySearchFirstGT(a, 4))
}
}
func TestBinarySearchLastLT(t *testing.T) {
var a []int
a = []int{1, 2, 2, 2, 3, 4}
if BinarySearchLastLT(a, 2) != 0 {
t.Fatal(BinarySearchLastLT(a, 2))
}
a = []int{1, 2, 2, 2, 3, 4}
if BinarySearchLastLT(a, 1) != -1 {
t.Fatal(BinarySearchLastLT(a, 1))
}
a = []int{1, 2, 2, 2, 3, 4}
if BinarySearchLastLT(a, 3) != 3 {
t.Fatal(BinarySearchLastLT(a, 3))
}
a = []int{1, 2, 2, 2, 3, 4}
if BinarySearchLastLT(a, 4) != 4 {
t.Fatal(BinarySearchLastLT(a, 4))
}
}

177
go/17_skiplist/skiplist.go Normal file
View File

@ -0,0 +1,177 @@
package _7_skiplist
import (
"fmt"
"math"
"math/rand"
)
const (
//最高层数
MAX_LEVEL = 16
)
//跳表节点结构体
type skipListNode struct {
//跳表保存的值
v interface{}
//用于排序的分值
score int
//层高
level int
//每层前进指针
forwards []*skipListNode
}
//新建跳表节点
func newSkipListNode(v interface{}, score, level int) *skipListNode {
return &skipListNode{v: v, score: score, forwards: make([]*skipListNode, level, level), level: level}
}
//跳表结构体
type SkipList struct {
//跳表头结点
head *skipListNode
//跳表当前层数
level int
//跳表长度
length int
}
//实例化跳表对象
func NewSkipList() *SkipList {
//头结点,便于操作
head := newSkipListNode(0, math.MinInt32, MAX_LEVEL)
return &SkipList{head, 1, 0}
}
//获取跳表长度
func (sl *SkipList) Length() int {
return sl.length
}
//获取跳表层级
func (sl *SkipList) Level() int {
return sl.level
}
//插入节点到跳表中
func (sl *SkipList) Insert(v interface{}, score int) int {
if nil == v {
return 1
}
//查找插入位置
cur := sl.head
//记录每层的路径
update := [MAX_LEVEL]*skipListNode{}
i := MAX_LEVEL - 1
for ; i >= 0; i-- {
for nil != cur.forwards[i] {
if cur.forwards[i].v == v {
return 2
}
if cur.forwards[i].score > score {
update[i] = cur
break
}
cur = cur.forwards[i]
}
if nil == cur.forwards[i] {
update[i] = cur
}
}
//通过随机算法获取该节点层数
level := 1
for i := 1; i < MAX_LEVEL; i++ {
if rand.Int31()%7 == 1 {
level++
}
}
//创建一个新的跳表节点
newNode := newSkipListNode(v, score, level)
//原有节点连接
for i := 0; i <= level-1; i++ {
next := update[i].forwards[i]
update[i].forwards[i] = newNode
newNode.forwards[i] = next
}
//如果当前节点的层数大于之前跳表的层数
//更新当前跳表层数
if level > sl.level {
sl.level = level
}
//更新跳表长度
sl.length++
return 0
}
//查找
func (sl *SkipList) Find(v interface{}, score int) *skipListNode {
if nil == v || sl.length == 0 {
return nil
}
cur := sl.head
for i := sl.level - 1; i >= 0; i-- {
for nil != cur.forwards[i] {
if cur.forwards[i].score == score && cur.forwards[i].v == v {
return cur.forwards[i]
} else if cur.forwards[i].score > score {
break
}
cur = cur.forwards[i]
}
}
return nil
}
//删除节点
func (sl *SkipList) Delete(v interface{}, score int) int {
if nil == v {
return 1
}
//查找前驱节点
cur := sl.head
//记录前驱路径
update := [MAX_LEVEL]*skipListNode{}
for i := sl.level - 1; i >= 0; i-- {
update[i] = sl.head
for nil != cur.forwards[i] {
if cur.forwards[i].score == score && cur.forwards[i].v == v {
update[i] = cur
break
}
cur = cur.forwards[i]
}
}
cur = update[0].forwards[0]
for i := cur.level - 1; i >= 0; i-- {
if update[i] == sl.head && cur.forwards[i] == nil {
sl.level = i
}
if nil == update[i].forwards[i] {
update[i].forwards[i] = nil
} else {
update[i].forwards[i] = update[i].forwards[i].forwards[i]
}
}
sl.length--
return 0
}
func (sl *SkipList) String() string {
return fmt.Sprintf("level:%+v, length:%+v", sl.level, sl.length)
}

View File

@ -0,0 +1,38 @@
package _7_skiplist
import "testing"
func TestSkipList(t *testing.T) {
sl := NewSkipList()
sl.Insert("leo", 95)
t.Log(sl.head.forwards[0])
t.Log(sl.head.forwards[0].forwards[0])
t.Log(sl)
t.Log("-----------------------------")
sl.Insert("jack", 88)
t.Log(sl.head.forwards[0])
t.Log(sl.head.forwards[0].forwards[0])
t.Log(sl.head.forwards[0].forwards[0].forwards[0])
t.Log(sl)
t.Log("-----------------------------")
sl.Insert("lily", 100)
t.Log(sl.head.forwards[0])
t.Log(sl.head.forwards[0].forwards[0])
t.Log(sl.head.forwards[0].forwards[0].forwards[0])
t.Log(sl.head.forwards[0].forwards[0].forwards[0].forwards[0])
t.Log(sl)
t.Log("-----------------------------")
t.Log(sl.Find("jack", 88))
t.Log("-----------------------------")
sl.Delete("leo", 95)
t.Log(sl.head.forwards[0])
t.Log(sl.head.forwards[0].forwards[0])
t.Log(sl.head.forwards[0].forwards[0].forwards[0])
t.Log(sl)
t.Log("-----------------------------")
}

View File

@ -0,0 +1,145 @@
package _4_tree
type BST struct {
*BinaryTree
//比对函数0:v==nodeV,正数:v>nodeV,负数:v<nodeV
compareFunc func(v, nodeV interface{}) int
}
func NewBST(rootV interface{}, compareFunc func(v, nodeV interface{}) int) *BST {
if nil == compareFunc {
return nil
}
return &BST{BinaryTree: NewBinaryTree(rootV), compareFunc: compareFunc}
}
func (this *BST) Find(v interface{}) *Node {
p := this.root
for nil != p {
compareResult := this.compareFunc(v, p.data)
if compareResult == 0 {
return p
} else if compareResult > 0 { //v > nodeV
p = p.right
} else { //v < nodeV
p = p.left
}
}
return nil
}
func (this *BST) Insert(v interface{}) bool {
p := this.root
for nil != p {
compareResult := this.compareFunc(v, p.data)
if compareResult == 0 {
return false
} else if compareResult > 0 {
if nil == p.right {
p.right = NewNode(v)
break
}
p = p.right
} else {
if nil == p.left {
p.left = NewNode(v)
break
}
p = p.left
}
}
return true
}
func (this *BST) Delete(v interface{}) bool {
var pp *Node = nil
p := this.root
deleteLeft := false
for nil != p {
compareResult := this.compareFunc(v, p.data)
if compareResult > 0 {
pp = p
p = p.right
deleteLeft = false
} else if compareResult < 0 {
pp = p
p = p.left
deleteLeft = true
} else {
break
}
}
if nil == p { //需要删除的节点不存在
return false
} else if nil == p.left && nil == p.right { //删除的是一个叶子节点
if nil != pp {
if deleteLeft {
pp.left = nil
} else {
pp.right = nil
}
} else { //根节点
this.root = nil
}
} else if nil != p.right { //删除的是一个有右孩子,不一定有左孩子的节点
//找到p节点右孩子的最小节点
pq := p
q := p.right //向右走一步
fromRight := true
for nil != q.left { //向左走到底
pq = q
q = q.left
fromRight = false
}
if fromRight {
pq.right = nil
} else {
pq.left = nil
}
q.left = p.left
q.right = p.right
if nil == pp { //根节点被删除
this.root = q
} else {
if deleteLeft {
pq.left = q
} else {
pq.right = q
}
}
} else { //删除的是一个只有左孩子的节点
if nil != pp {
if deleteLeft {
pp.left = p.left
} else {
pp.right = p.left
}
} else {
if deleteLeft {
this.root = p.left
} else {
this.root = p.left
}
}
}
return true
}
func (this *BST) Min() *Node {
p := this.root
for nil != p.left {
p = p.left
}
return p
}
func (this *BST) Max() *Node {
p := this.root
for nil != p.right {
p = p.right
}
return p
}

View File

@ -0,0 +1,145 @@
package _4_tree
import "testing"
var compareFunc = func(v, nodeV interface{}) int {
vInt := v.(int)
nodeVInt := nodeV.(int)
if vInt > nodeVInt {
return 1
} else if vInt < nodeVInt {
return -1
}
return 0
}
func TestBST_Find(t *testing.T) {
bst := NewBST(1, compareFunc)
bst.Insert(3)
bst.Insert(1)
bst.Insert(2)
bst.Insert(7)
bst.Insert(5)
t.Log(bst.Find(2))
}
func TestBST_Insert(t *testing.T) {
bst := NewBST(1, compareFunc)
bst.Insert(3)
bst.Insert(1)
bst.Insert(2)
bst.Insert(7)
bst.Insert(5)
bst.InOrderTraverse()
}
func TestBST_Min(t *testing.T) {
bst := NewBST(1, compareFunc)
bst.Insert(3)
bst.Insert(1)
bst.Insert(2)
bst.Insert(7)
bst.Insert(5)
t.Log(bst.Min())
}
func TestBST_Max(t *testing.T) {
bst := NewBST(1, compareFunc)
bst.Insert(3)
bst.Insert(1)
bst.Insert(2)
bst.Insert(7)
bst.Insert(5)
t.Log(bst.Max())
}
func TestBST_DeleteA(t *testing.T) {
bst := NewBST(1, compareFunc)
bst.Insert(3)
bst.Insert(2)
bst.Insert(7)
bst.Insert(5)
t.Log(bst.Delete(7))
bst.InOrderTraverse()
}
func TestBST_DeleteB(t *testing.T) {
bst := NewBST(1, compareFunc)
t.Log(bst.Delete(1))
t.Log(bst.root)
bst.InOrderTraverse()
}
func TestBST_DeleteC(t *testing.T) {
bst := NewBST(1, compareFunc)
bst.Insert(3)
bst.Insert(2)
bst.Insert(7)
bst.Insert(5)
t.Log(bst.Delete(1))
bst.InOrderTraverse()
}
func TestBST_DeleteD(t *testing.T) {
bst := NewBST(1, compareFunc)
bst.Insert(3)
bst.Insert(2)
bst.Insert(5)
t.Log(bst.Delete(1))
bst.InOrderTraverse()
}
func TestBST_DeleteE(t *testing.T) {
bst := NewBST(5, compareFunc)
bst.Insert(3)
bst.Insert(2)
bst.Insert(4)
bst.Insert(1)
t.Log(bst.Delete(5))
bst.InOrderTraverse()
}
func TestBST_DeleteF(t *testing.T) {
bst := NewBST(5, compareFunc)
bst.Insert(3)
bst.Insert(2)
bst.Insert(4)
bst.Insert(1)
t.Log(bst.Delete(2))
bst.InOrderTraverse()
}
func TestBST_DeleteG(t *testing.T) {
bst := NewBST(5, compareFunc)
bst.Insert(3)
bst.Insert(2)
bst.Insert(4)
bst.Insert(1)
t.Log(bst.Delete(1))
bst.InOrderTraverse()
}

97
go/24_tree/BinaryTree.go Normal file
View File

@ -0,0 +1,97 @@
package _4_tree
import "fmt"
type BinaryTree struct {
root *Node
}
func NewBinaryTree(rootV interface{}) *BinaryTree {
return &BinaryTree{NewNode(rootV)}
}
func (this *BinaryTree) InOrderTraverse() {
p := this.root
s := NewArrayStack()
for !s.IsEmpty() || nil != p {
if nil != p {
s.Push(p)
p = p.left
} else {
tmp := s.Pop().(*Node)
fmt.Printf("%+v ", tmp.data)
p = tmp.right
}
}
fmt.Println()
}
func (this *BinaryTree) PreOrderTraverse() {
p := this.root
s := NewArrayStack()
for !s.IsEmpty() || nil != p {
if nil != p {
fmt.Printf("%+v ", p.data)
s.Push(p)
p = p.left
} else {
p = s.Pop().(*Node).right
}
}
fmt.Println()
}
func (this *BinaryTree) PostOrderTraverse() {
s1 := NewArrayStack()
s2 := NewArrayStack()
s1.Push(this.root)
for !s1.IsEmpty() {
p := s1.Pop().(*Node)
s2.Push(p)
if nil != p.left {
s1.Push(p.left)
}
if nil != p.right {
s1.Push(p.right)
}
}
for !s2.IsEmpty() {
fmt.Printf("%+v ", s2.Pop().(*Node).data)
}
}
//use one stack, pre cursor to traverse from post order
func (this *BinaryTree) PostOrderTraverse2() {
r := this.root
s := NewArrayStack()
//point to last visit node
var pre *Node
s.Push(r)
for !s.IsEmpty() {
r = s.Top().(*Node)
if (r.left == nil && r.right == nil) ||
(pre != nil && (pre == r.left || pre == r.right)) {
fmt.Printf("%+v ", r.data)
s.Pop()
pre = r
} else {
if r.right != nil {
s.Push(r.right)
}
if r.left != nil {
s.Push(r.left)
}
}
}
}

View File

@ -0,0 +1,39 @@
package _4_tree
import "testing"
func TestBinaryTree_InOrderTraverse(t *testing.T) {
binaryTree := NewBinaryTree(1)
binaryTree.root.left = NewNode(3)
binaryTree.root.right = NewNode(4)
binaryTree.root.right.left = NewNode(5)
binaryTree.InOrderTraverse()
}
func TestBinaryTree_PreOrderTraverse(t *testing.T) {
binaryTree := NewBinaryTree(1)
binaryTree.root.left = NewNode(3)
binaryTree.root.right = NewNode(4)
binaryTree.root.right.left = NewNode(5)
binaryTree.PreOrderTraverse()
}
func TestBinaryTree_PostOrderTraverse(t *testing.T) {
binaryTree := NewBinaryTree(1)
binaryTree.root.left = NewNode(3)
binaryTree.root.right = NewNode(4)
binaryTree.root.right.left = NewNode(5)
binaryTree.PostOrderTraverse()
}
func TestBinaryTree_PostOrderTraverse2(t *testing.T) {
binaryTree := NewBinaryTree(1)
binaryTree.root.left = NewNode(3)
binaryTree.root.right = NewNode(4)
binaryTree.root.right.left = NewNode(5)
binaryTree.PostOrderTraverse2()
}

View File

@ -0,0 +1,72 @@
package _4_tree
import "fmt"
/*
基于数组实现的栈
*/
type ArrayStack struct {
//数据
data []interface{}
//栈顶指针
top int
}
func NewArrayStack() *ArrayStack {
return &ArrayStack{
data: make([]interface{}, 0, 32),
top: -1,
}
}
func (this *ArrayStack) IsEmpty() bool {
if this.top < 0 {
return true
}
return false
}
func (this *ArrayStack) Push(v interface{}) {
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{} {
if this.IsEmpty() {
return nil
}
v := this.data[this.top]
this.top -= 1
return v
}
func (this *ArrayStack) Top() interface{} {
if this.IsEmpty() {
return nil
}
return this.data[this.top]
}
func (this *ArrayStack) Flush() {
this.top = -1
}
func (this *ArrayStack) Print() {
if this.IsEmpty() {
fmt.Println("empty statck")
} else {
for i := this.top; i >= 0; i-- {
fmt.Println(this.data[i])
}
}
}

17
go/24_tree/TreeNode.go Normal file
View File

@ -0,0 +1,17 @@
package _4_tree
import "fmt"
type Node struct {
data interface{}
left *Node
right *Node
}
func NewNode(data interface{}) *Node {
return &Node{data: data}
}
func (this *Node) String() string {
return fmt.Sprintf("v:%+v, left:%+v, right:%+v", this.data, this.left, this.right)
}

83
go/28_heap/heap.go Normal file
View File

@ -0,0 +1,83 @@
package heap
type Heap struct {
a []int
n int
count int
}
//init heap
func NewHeap(capacity int) *Heap {
heap := &Heap{}
heap.n = capacity
heap.a = make([]int, capacity+1)
heap.count = 0
return heap
}
//top-max heap -> heapify from down to up
func (heap *Heap) insert(data int) {
//defensive
if heap.count == heap.n {
return
}
heap.count++
heap.a[heap.count] = data
//compare with parent node
i := heap.count
parent := i / 2
for parent > 0 && heap.a[parent] < heap.a[i] {
swap(heap.a, parent, i)
i = parent
parent = i / 2
}
}
//heapfify from up to down
func (heap *Heap) removeMax() {
//defensive
if heap.count == 0 {
return
}
//swap max and last
swap(heap.a, 1, heap.count)
heap.count--
//heapify from up to down
heapifyUpToDown(heap.a, heap.count)
}
//heapify
func heapifyUpToDown(a []int, count int) {
for i := 1; i <= count/2; {
maxIndex := i
if a[i] < a[i*2] {
maxIndex = i * 2
}
if i*2+1 <= count && a[maxIndex] < a[i*2+1] {
maxIndex = i*2 + 1
}
if maxIndex == i {
break
}
swap(a, i, maxIndex)
i = maxIndex
}
}
//swap two elements
func swap(a []int, i int, j int) {
tmp := a[i]
a[i] = a[j]
a[j] = tmp
}

54
go/28_heap/heap_sort.go Normal file
View File

@ -0,0 +1,54 @@
package heap
//build a heap
func buidHeap(a []int, n int) {
//heapify from the last parent node
for i := n / 2; i >= 1; i-- {
heapifyUpToDown(a, i, n)
}
}
//sort by ascend, a index begin from 1, has n elements
func sort(a []int, n int) {
buidHeap(a, n)
k := n
for k >= 1 {
swap(a, 1, k)
heapifyUpToDown(a, 1, k-1)
k--
}
}
//heapify from up to down , node index = top
func heapifyUpToDown(a []int, top int, count int) {
for i := top; i <= count/2; {
maxIndex := i
if a[i] < a[i*2] {
maxIndex = i * 2
}
if i*2+1 <= count && a[maxIndex] < a[i*2+1] {
maxIndex = i*2 + 1
}
if maxIndex == i {
break
}
swap(a, i, maxIndex)
i = maxIndex
}
}
//swap two elements
func swap(a []int, i int, j int) {
tmp := a[i]
a[i] = a[j]
a[j] = tmp
}

90
go/binarysearch2.go Normal file
View File

@ -0,0 +1,90 @@
package binarySearch
//查找第一个值等于给定值得元素
func BinarySearch2(nums []int, value int) int {
length := len(nums)
start := 0
end := length - 1
for start <= end {
mid := start + ((end - start) >> 1)
if nums[mid] > value {
end = mid - 1
} else if nums[mid] < value {
start = mid + 1
} else {
for mid >= 0 {
if nums[mid-1] == value {
mid--
} else {
return mid
}
}
}
}
return -1
}
// 查找最后一个值等于给定值的元素
func BinarySearch3(nums []int, value int) int {
start := 0
end := len(nums) - 1
for start <= end {
mid := start + ((end - start) >> 1)
if nums[mid] > value {
end = mid - 1
} else if nums[mid] < value {
start = mid + 1
} else {
for mid < len(nums) {
if nums[mid+1] == value {
mid++
} else {
return mid
}
}
}
}
return -1
}
// 查找第一个大于等于给定值的元素
func BinarySearch4(nums []int, value int) int {
start := 0
end := len(nums) - 1
for start <= end {
mid := (start + end) >> 1
if nums[mid] < value {
start = mid + 1
} else {
for mid >= 0 {
if nums[mid-1] >= value {
mid--
} else {
return mid
}
}
}
}
return -1
}
// 查找最后一个小于等于给定值的元素
func BinarySearch5(nums []int, value int) int {
start := 0
end := len(nums) - 1
for start <= end {
mid := (start + end) >> 1
if nums[mid] > value {
end = mid - 1
} else {
for mid < len(nums) {
if nums[mid+1] <= value {
mid++
} else {
return mid
}
}
}
}
return -1
}

View File

@ -1,164 +1,163 @@
/**
*
* 1泛型动态数组
*
* Author: shi
*/
public class GenericArray<T> {
private T[] data;
private int size;
public class GenericArray<T> {
private T[] data;
private int size;
// 根据传入容量构造Array
public GenericArray(int capacity) {
data = (T[]) new Object[capacity];
size = 0;
}
// 根据传入容量构造Array
public GenericArray(int capacity) {
data = (T[]) new Object[capacity];
size = 0;
}
// 无参构造方法默认数组容量为10
public GenericArray() {
this(10);
}
// 无参构造方法默认数组容量为10
public GenericArray() {
this(10);
}
// 获取数组容量
public int getCapacity() {
return data.length;
}
// 获取组容量
public int getCapacity() {
return data.length;
}
// 获取当前元素个
public int count() {
return size;
}
// 获取当前元素个数
public int count() {
return size;
}
// 判断数组是否为空
public boolean isEmpty() {
return size == 0;
}
// 判断数组是否为空
public boolean isEmpty() {
return size == 0;
}
// 修改 index 位置的元素
public void set(int index, T e) {
checkIndex(index);
data[index] = e;
}
// 修改 index 位置的元素
public void set(int index, T e) {
checkIndex(index);
data[index] = e;
}
// 获取对应 index 位置的元素
public T get(int index) {
checkIndex(index);
return data[index];
}
// 获取对应 index 位置的元素
public T get(int index) {
checkIndex(index);
return data[index];
}
// 查看数组是否包含元素e
public boolean contains(T e) {
for (int i = 0; i < size; i++) {
if (data[i].equals(e)) {
return true;
}
}
return false;
}
// 查看数组是否包含元素e
public boolean contains(T e) {
for (int i = 0; i < size; i++) {
if (data[i].equals(e)) {
return true;
}
}
return false;
}
// 获取对应元素的下标, 未找到返回 -1
public int find(T e) {
for ( int i = 0; i < size; i++) {
if (data[i].equals(e)) {
return i;
}
}
return -1;
}
// 获取对应元素的下标, 未找到返回 -1
public int find(T e) {
for ( int i = 0; i < size; i++) {
if (data[i].equals(e)) {
return i;
}
}
return -1;
}
// index 位置插入元素e, 时间复杂度 O(m+n)
public void add(int index, T e) {
checkIndex(index);
// 如果当前元素个数等于数组容量则将数组扩容为原来的2倍
if (size == data.length) {
resize(2 * data.length);
}
// index 位置插入元素e, 时间复杂度 O(m+n)
public void add(int index, T e) {
checkIndex(index);
// 如果当前元素个数等于数组容量则将数组扩容为原来的2倍
if (size == data.length) {
resize(2 * data.length);
}
for (int i = size - 1; i >= index; i--) {
data[i + 1] = data[i];
}
data[index] = e;
size++;
}
for (int i = size - 1; i >= index; i--) {
data[i + 1] = data[i];
}
data[index] = e;
size++;
}
// 向数组头插入元素
public void addFirst(T e) {
add(0, e);
}
// 向数组头插入元素
public void addFirst(T e) {
add(0, e);
}
// 向数组尾插入元素
public void addLast(T e) {
add(size, e);
}
// 向数组尾插入元素
public void addLast(T e) {
add(size, e);
}
// 删除 index 位置的元素并返回
public T remove(int index) {
checkIndex(index);
// 删除 index 位置的元素并返回
public T remove(int index) {
checkIndexForRemove(index);
T ret = data[index];
for (int i = index + 1; i < size; i++) {
data[i - 1] = data[i];
}
size --;
data[size] = null;
T ret = data[index];
for (int i = index + 1; i < size; i++) {
data[i - 1] = data[i];
}
size --;
data[size] = null;
// 缩容
if (size == data.length / 4 && data.length / 2 != 0) {
resize(data.length / 2);
}
// 缩容
if (size == data.length / 4 && data.length / 2 != 0) {
resize(data.length / 2);
}
return ret;
}
return ret;
}
// 删除第一个元素
public T removeFirst() {
return remove(0);
}
// 删除第一个元素
public T removeFirst() {
return remove(0);
}
// 删除末尾元素
public T removeLast() {
return remove(size - 1);
}
// 删除末尾元素
public T removeLast() {
return remove(size - 1);
}
// 从数组中删除指定元素
public void removeElement(T e) {
int index = find(e);
if (index != -1) {
remove(index);
}
}
// 从数组中删除指定元素
public void removeElement(T e) {
int index = find(e);
if (index != -1) {
remove(index);
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(String.format("Array size = %d, capacity = %d \n", size, data.length));
builder.append('[');
for (int i = 0; i < size; i++) {
builder.append(data[i]);
if (i != size - 1) {
builder.append(", ");
}
}
builder.append(']');
return builder.toString();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(String.format("Array size = %d, capacity = %d \n", size, data.length));
builder.append('[');
for (int i = 0; i < size; i++) {
builder.append(data[i]);
if (i != size - 1) {
builder.append(", ");
}
}
builder.append(']');
return builder.toString();
}
// 扩容方法时间复杂度 O(n)
private void resize(int capacity) {
T[] newData = (T[]) new Object[capacity];
// 扩容方法时间复杂度 O(n)
private void resize(int capacity) {
T[] newData = (T[]) new Object[capacity];
for (int i = 0; i < size; i++) {
newData[i] = data[i];
}
data = newData;
}
for (int i = 0; i < size; i++) {
newData[i] = data[i];
}
data = newData;
}
private void checkIndex(int index) {
private void checkIndex(int index) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("Add failed! Require index >=0 and index <= size.");
}
}
}
}
private void checkIndexForRemove(int index) {
if(index < 0 || index >= size) {
throw new IllegalArgumentException("remove failed! Require index >=0 and index < size.");
}
}
}

View File

@ -8,160 +8,329 @@ package linkedlist;
*/
public class SinglyLinkedList {
private Node head = null;
private Node head = null;
public Node findByValue(int value) {
Node p = head;
while (p != null && p.data != value) {
p = p.next;
public Node findByValue(int value) {
Node p = head;
while (p != null && p.data != value) {
p = p.next;
}
return p;
}
return p;
}
public Node findByIndex(int index) {
Node p = head;
int pos = 0;
while (p != null && pos != index) {
p = p.next;
++pos;
}
public Node findByIndex(int index) {
Node p = head;
int pos = 0;
while (p != null && pos != index) {
p = p.next;
++pos;
return p;
}
return p;
}
public void insertToHead(int value) {
Node newNode = new Node(value, null);
insertToHead(newNode);
}
public void insertToHead(Node newNode) {
if (head == null) {
head = newNode;
} else {
newNode.next = head;
head = newNode;
}
}
public void insertAfter(Node p, int value) {
Node newNode = new Node(value, null);
insertAfter(p, newNode);
}
public void insertAfter(Node p, Node newNode) {
if (p == null) return;
newNode.next = p.next;
p.next = newNode;
}
public void insertBefore(Node p, int value) {
Node newNode = new Node(value, null);
insertBefore(p, newNode);
}
public void insertBefore(Node p, Node newNode) {
if (p == null) return;
if (head == p) {
insertToHead(newNode);
return;
//无头结点
//表头部插入
//这种操作将于输入的顺序相反逆序
public void insertToHead(int value) {
Node newNode = new Node(value, null);
insertToHead(newNode);
}
Node q = head;
while (q != null && q.next != p) {
q = q.next;
public void insertToHead(Node newNode) {
if (head == null) {
head = newNode;
} else {
newNode.next = head;
head = newNode;
}
}
if (q == null) {
return;
//顺序插入
//链表尾部插入
public void insertTail(int value){
Node newNode = new Node(value, null);
//空链表可以插入新节点作为head也可以不操作
if (head == null){
head = newNode;
}else{
Node q = head;
while(q.next != null){
q = q.next;
}
newNode.next = q.next;
q.next = newNode;
}
}
public void insertAfter(Node p, int value) {
Node newNode = new Node(value, null);
insertAfter(p, newNode);
}
newNode.next = p;
q.next = newNode;
public void insertAfter(Node p, Node newNode) {
if (p == null) return;
}
public void deleteByNode(Node p) {
if (p == null || head == null) return;
if (p == head) {
head = head.next;
return;
newNode.next = p.next;
p.next = newNode;
}
Node q = head;
while (q != null && q.next != p) {
q = q.next;
public void insertBefore(Node p, int value) {
Node newNode = new Node(value, null);
insertBefore(p, newNode);
}
if (q == null) {
return;
public void insertBefore(Node p, Node newNode) {
if (p == null) return;
if (head == p) {
insertToHead(newNode);
return;
}
Node q = head;
while (q != null && q.next != p) {
q = q.next;
}
if (q == null) {
return;
}
newNode.next = p;
q.next = newNode;
}
q.next = q.next.next;
}
public void deleteByNode(Node p) {
if (p == null || head == null) return;
public void deleteByValue(int value) {
if (head == null) return;
if (p == head) {
head = head.next;
return;
}
Node p = head;
Node q = null;
while (p != null && p.data != value) {
q = p;
p = p.next;
Node q = head;
while (q != null && q.next != p) {
q = q.next;
}
if (q == null) {
return;
}
q.next = q.next.next;
}
if (p == null) return;
public void deleteByValue(int value) {
if (head == null) return;
if (q == null) {
head = head.next;
} else {
q.next = q.next.next;
Node p = head;
Node q = null;
while (p != null && p.data != value) {
q = p;
p = p.next;
}
if (p == null) return;
if (q == null) {
head = head.next;
} else {
q.next = q.next.next;
}
// 可重复删除指定value的代码
/*
if (head != null && head.data == value) {
head = head.next;
}
Node pNode = head;
while (pNode != null) {
if (pNode.next.data == data) {
pNode.next = pNode.next.next;
continue;
}
pNode = pNode.next;
}
*/
}
// 可重复删除指定value的代码
/*
if (head != null && head.data == value) {
head = head.next;
public void printAll() {
Node p = head;
while (p != null) {
System.out.print(p.data + " ");
p = p.next;
}
System.out.println();
}
Node pNode = head;
while (pNode != null) {
if (pNode.next.data == data) {
pNode.next = pNode.next.next;
continue;
}
pNode = pNode.next;
//判断true or false
public boolean TFResult(Node left, Node right){
Node l = left;
Node r = right;
System.out.println("left_:"+l.data);
System.out.println("right_:"+r.data);
while(l != null && r != null){
if (l.data == r.data){
l = l.next;
r = r.next;
continue;
}else{
break;
}
}
System.out.println("什么结果");
if (l==null && r==null){
System.out.println("什么结果");
return true;
}else{
return false;
}
}
*/
}
// 判断是否为回文
public void printAll() {
Node p = head;
while (p != null) {
System.out.print(p.data + " ");
p = p.next;
}
System.out.println();
}
public boolean palindrome(){
if (head == null){
return false;
}else{
System.out.println("开始执行找到中间节点");
Node p = head;
Node q = head;
if (p.next == null){
System.out.println("只有一个元素");
return true;
}
while( q.next != null && q.next.next != null){
p = p.next;
q = q.next.next;
public static Node createNode(int value) {
return new Node(value, null);
}
}
public static class Node {
private int data;
private Node next;
System.out.println("中间节点" + p.data);
System.out.println("开始执行奇数节点的回文判断");
Node leftLink = null;
Node rightLink = null;
if(q.next == null){
// p 一定为整个链表的中点且节点数目为奇数
rightLink = p.next;
leftLink = inverseLinkList(p).next;
System.out.println("左边第一个节点"+leftLink.data);
System.out.println("右边第一个节点"+rightLink.data);
public Node(int data, Node next) {
this.data = data;
this.next = next;
}else{
//p q 均为中点
rightLink = p.next;
leftLink = inverseLinkList(p);
}
return TFResult(leftLink, rightLink);
}
}
public int getData() {
return data;
//带结点的链表翻转
public Node inverseLinkList_head(Node p){
// Head 为新建的一个头结点
Node Head = new Node(9999,null);
// p 为原来整个链表的头结点,现在Head指向 整个链表
Head.next = p;
/*
带头结点的链表翻转等价于
从第二个元素开始重新头插法建立链表
*/
Node Cur = p.next;
p.next = null;
Node next = null;
while(Cur != null){
next = Cur.next;
Cur.next = Head.next;
Head.next = Cur;
System.out.println("first " + Head.data);
Cur = next;
}
// 返回左半部分的中点之前的那个节点
// 从此处开始同步像两边比较
return Head;
}
//无头结点的链表翻转
public Node inverseLinkList(Node p){
Node pre = null;
Node r = head;
System.out.println("z---" + r.data);
Node next= null;
while(r !=p){
next = r.next;
r.next = pre;
pre = r;
r = next;
}
r.next = pre;
// 返回左半部分的中点之前的那个节点
// 从此处开始同步像两边比较
return r;
}
public static Node createNode(int value) {
return new Node(value, null);
}
public static class Node {
private int data;
private Node next;
public Node(int data, Node next) {
this.data = data;
this.next = next;
}
public int getData() {
return data;
}
}
public static void main(String[]args){
SinglyLinkedList link = new SinglyLinkedList();
System.out.println("hello");
//int data[] = {1};
//int data[] = {1,2};
//int data[] = {1,2,3,1};
//int data[] = {1,2,5};
//int data[] = {1,2,2,1};
// int data[] = {1,2,5,2,1};
int data[] = {1,2,5,3,1};
for(int i =0; i < data.length; i++){
//link.insertToHead(data[i]);
link.insertTail(data[i]);
}
// link.printAll();
// Node p = link.inverseLinkList_head(link.head);
// while(p != null){
// System.out.println("aa"+p.data);
// p = p.next;
// }
System.out.println("打印原始:");
link.printAll();
if (link.palindrome()){
System.out.println("回文");
}else{
System.out.println("不是回文");
}
}
}
}

View File

@ -0,0 +1,48 @@
package sorts;
import java.util.Arrays;
/**
* 插入排序插入位置从头至尾搜索
* @Author ooooor
*/
public class InsertionSortAdd {
public static void main(String[] args) {
int[] data = new int[]{4, 6, 5, 3, 7, 1, 2};
fromStartToEnd(Arrays.copyOf(data, data.length));
System.out.println(Arrays.toString(data));
}
/**
* 查询插入位置时 从头至尾搜索
* @param data
*/
private static void fromStartToEnd(int[] data) {
for (int i=1; i < data.length; i++) {
int value = data[i];
int[] tmp = new int[2];
int change = i;
for (int j=0; j < i; j++) {
if(value >= data[j]) {
continue;
}
int index = j%2;
if (change == i) {
tmp[Math.abs(index-1)] = data[j];
change = j;
}
tmp[index] = data[j+1];
if (0 == index) {
data[j+1] = tmp[index+1];
} else {
data[j+1] = tmp[index-1];
}
}
data[change] = value;
}
}
}

View File

@ -49,31 +49,16 @@ public class Sorts {
// 选择排序a表示数组n表示数组大小
public static void selectionSort(int[] a, int n) {
if (n <= 1) return;
<<<<<<< HEAD
for (int i = 0; i < n; ++i) {
// 查找最小值
int minIndex = i;
int minValue = a[i];
for (int j = i; j < n; ++j) {
if (a[j] < minValue) {
minValue = a[j];
=======
for (int i = 0; i < n - 1; ++i) {
// 查找最小值
int minIndex = i;
for (int j = i + 1; j < n; ++j) {
if (a[j] < a[minIndex]) {
>>>>>>> upstream/master
minIndex = j;
}
}
<<<<<<< HEAD
=======
if (minIndex == i)
continue;
>>>>>>> upstream/master
// 交换
int tmp = a[i];
a[i] = a[minIndex];

View File

@ -21,13 +21,13 @@ public class SkipList {
public Node find(int value) {
Node p = head;
for (int i = levelCount - 1; i >= 0; --i) {
while (p.forwords[i] != null && p.forwords[i].data < value) {
p = p.forwords[i];
while (p.forwards[i] != null && p.forwards[i].data < value) {
p = p.forwards[i];
}
}
if (p.forwords[0] != null && p.forwords[0].data == value) {
return p.forwords[0];
if (p.forwards[0] != null && p.forwards[0].data == value) {
return p.forwards[0];
} else {
return null;
}
@ -46,16 +46,16 @@ public class SkipList {
// record every level largest value which smaller than insert value in update[]
Node p = head;
for (int i = level - 1; i >= 0; --i) {
while (p.forwords[i] != null && p.forwords[i].data < value) {
p = p.forwords[i];
while (p.forwards[i] != null && p.forwards[i].data < value) {
p = p.forwards[i];
}
update[i] = p;// use update save node in search path
}
// in search path node next node become new node forwords(next)
for (int i = 0; i < level; ++i) {
newNode.forwords[i] = update[i].forwords[i];
update[i].forwords[i] = newNode;
newNode.forwards[i] = update[i].forwards[i];
update[i].forwards[i] = newNode;
}
// update node hight
@ -66,16 +66,16 @@ public class SkipList {
Node[] update = new Node[levelCount];
Node p = head;
for (int i = levelCount - 1; i >= 0; --i) {
while (p.forwords[i] != null && p.forwords[i].data < value) {
p = p.forwords[i];
while (p.forwards[i] != null && p.forwards[i].data < value) {
p = p.forwards[i];
}
update[i] = p;
}
if (p.forwords[0] != null && p.forwords[0].data == value) {
if (p.forwards[0] != null && p.forwards[0].data == value) {
for (int i = levelCount - 1; i >= 0; --i) {
if (update[i].forwords[i] != null && update[i].forwords[i].data == value) {
update[i].forwords[i] = update[i].forwords[i].forwords[i];
if (update[i].forwards[i] != null && update[i].forwards[i].data == value) {
update[i].forwards[i] = update[i].forwards[i].forwards[i];
}
}
}
@ -95,17 +95,16 @@ public class SkipList {
public void printAll() {
Node p = head;
while (p.forwords[0] != null) {
System.out.print(p.forwords[0] + " ");
p = p.forwords[0];
while (p.forwards[0] != null) {
System.out.print(p.forwards[0] + " ");
p = p.forwards[0];
}
System.out.println();
}
public class Node {
private int data = -1;
// 以数组形式维护下一个结点的指针
private Node forwords[] = new Node[MAX_LEVEL];
private Node forwards[] = new Node[MAX_LEVEL];
private int maxLevel = 0;
@Override

View File

@ -0,0 +1,99 @@
public class BinarySearchTree {
private Node tree;
public Node find(int data) {
Node p = tree;
while (p != null) {
if (data < p.data) p = p.left;
else if (data > p.data) p = p.right;
else return p;
}
return null;
}
public void insert(int data) {
if (tree == null) {
tree = new Node(data);
return;
}
Node p = tree;
while (p != null) {
if (data > p.data) {
if (p.right == null) {
p.right = new Node(data);
return;
}
p = p.right;
} else { // data < p.data
if (p.left == null) {
p.left = new Node(data);
return;
}
p = p.left;
}
}
}
public void delete(int data) {
Node p = tree; // p指向要删除的节点初始化指向根节点
Node pp = null; // pp记录的是p的父节点
while (p != null && p.data != data) {
pp = p;
if (data > p.data) p = p.right;
else p = p.left;
}
if (p == null) return; // 没有找到
// 要删除的节点有两个子节点
if (p.left != null && p.right != null) { // 查找右子树中最小节点
Node minP = p.right;
Node minPP = p; // minPP表示minP的父节点
while (minP.left != null) {
minPP = minP;
minP = minP.left;
}
p.data = minP.data; // 将minP的数据替换到p中
p = minP; // 下面就变成了删除minP了
pp = minPP;
}
// 删除节点是叶子节点或者仅有一个子节点
Node child; // p的子节点
if (p.left != null) child = p.left;
else if (p.right != null) child = p.right;
else child = null;
if (pp == null) tree = child; // 删除的是根节点
else if (pp.left == p) pp.left = child;
else pp.right = child;
}
public Node findMin() {
if (tree == null) return null;
Node p = tree;
while (p.left != null) {
p = p.left;
}
return p;
}
public Node findMax() {
if (tree == null) return null;
Node p = tree;
while (p.right != null) {
p = p.right;
}
return p;
}
public static class Node {
private int data;
private Node left;
private Node right;
public Node(int data) {
this.data = data;
}
}
}

View File

@ -0,0 +1,27 @@
/**
* 二分查找
*
* Author: nameczz
*/
// 数组必须有序 不存在重复
const biaryFind = (sortedArr, target) => {
if (sortedArr.length === 0) return -1
let low = 0
let high = sortedArr.length - 1
while (low <= high) {
const mid = Math.floor((low + high) / 2)
if (target === sortedArr[mid]) {
return mid
} else if (target < sortedArr[mid]) {
high = mid - 1
} else {
low = mid + 1
}
}
return -1
}
const arr = [1, 4, 5, 6, 7, 8, 10, 11, 23, 42, 44, 54, 56, 77, 102]
console.log(biaryFind(arr, 44))
console.log(biaryFind(arr, 1))
console.log(biaryFind(arr, 102))
console.log(biaryFind(arr, 1111))

View File

@ -0,0 +1,90 @@
/**
* 二分查找
*
* Author: nameczz
*/
// 查找第一个等于给定值
const biaryFindFirst = (sortedArr, target) => {
if (sortedArr.length === 0) return -1
let low = 0
let high = sortedArr.length - 1
while (low <= high) {
const mid = Math.floor((low + high) / 2)
if (target < sortedArr[mid]) {
high = mid - 1
} else if (target > sortedArr[mid]) {
low = mid + 1
} else {
if (mid === 0 || sortedArr[mid - 1] < target) return mid
high = mid - 1
}
}
return -1
}
// 查找最后一个相等的数
const biaryFindLast = (sortedArr, target) => {
if (sortedArr.length === 0) return -1
let low = 0
let high = sortedArr.length - 1
while (low <= high) {
const mid = Math.floor((low + high) / 2)
if (target < sortedArr[mid]) {
high = mid - 1
} else if (target > sortedArr[mid]) {
low = mid + 1
} else {
if (mid === sortedArr.length - 1 || sortedArr[mid + 1] > target) return mid
low = mid + 1
}
}
return -1
}
// 查找第一个大于等于给定值的元素
const biaryFindFistBig = (sortedArr, target) => {
if (sortedArr.length === 0) return -1
let low = 0
let high = sortedArr.length - 1
while (low <= high) {
const mid = Math.floor((low + high) / 2)
if (target <= sortedArr[mid]) {
if (mid === 0 || sortedArr[mid - 1] < target) return mid
high = mid - 1
} else {
low = mid + 1
}
}
return -1
}
// 查找最后一个小于等于给定值的元素
const biaryFindLastSmall = (sortedArr, target) => {
if (sortedArr.length === 0) return -1
let low = 0
let high = sortedArr.length - 1
while (low <= high) {
const mid = Math.floor((low + high) / 2)
if (sortedArr[mid] > target) {
high = mid - 1
} else {
if (mid === sortedArr.length - 1 || sortedArr[mid + 1] > target) return mid
low = mid + 1
}
}
return -1
}
const arr = [1, 2, 3, 4, 4, 4, 4, 4, 6, 7, 8, 8, 9]
const first = biaryFindFirst(arr, 4)
console.log(`FindFirst: ${first}`)
const last = biaryFindLast(arr, 4)
console.log(`FindLast: ${last}`)
const FisrtBig = biaryFindFistBig(arr, 5)
console.log(`FindFisrtBig: ${FisrtBig}`)
const LastSmall = biaryFindLastSmall(arr, 4)
console.log(`FindLastSmall: ${LastSmall}`)

View File

@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
/*
最基本的散列表
*/
class HashTable {
constructor() {
this.table=[];
}
//散列函数
loseHashCode(key){
var hash=0;
//从ASCII表中查到的ASCII值加到hash中
for (var i=0;i<key.length;i++){
hash+=key.charCodeAt(i);
}
//为了得到比较小的数值我们会用hash和任意数除余
return hash%37;
}
//向散列表增加一个新的项
put(key,value){
var position=this.loseHashCode(key);
console.log(position+'-'+key);
this.table[position]=value;
}
//根据键从散列表删除值
remove(key){
this.table[this.loseHashCode(key)]=undefined;
}
//返回根据键值检索到的特定的值
get(key){
console.log(this.table[this.loseHashCode(key)])
}
print(){
for (var i=0;i<this.table.length;++i){
if (this.table[i]!==undefined){
console.log(i+':'+this.table[i]);
}
}
}
}
var hash = new HashTable();
hash.put('Gandalf', 'gandalf@email.com');
hash.put('John', 'johnsnow@email.com');
hash.put('Tyrion', 'tyrion@email.com');
hash.remove('Gandalf')
hash.get('Gandalf')
hash.get('Tyrion')
hash.print()
//
</script>
</body>
</html>

View File

@ -0,0 +1,65 @@
/**
* 堆排序
*
* Author: nameczz
*/
// 忽视数组的第一位
class HeapSort {
constructor(originArray) {
this.originArray = originArray
console.log(this.originArray)
}
buildHeap() {
const arr = this.originArray
const startIndex = Math.floor(arr.length)
for (let i = startIndex; i >= 1; i--) {
this.heapify(arr, arr.length, i)
}
return arr
}
heapify(arr, len, i) {
while (true) {
let maxPos = i
// 如果index i拥有叶左节点 并且左节点较大
if (i * 2 <= len && arr[i] < arr[i * 2]) {
maxPos = i * 2
}
// 如果index i拥有叶右节点 与Max节点比较大小选出父/左/右中最大的一个
if (i * 2 + 1 <= len && arr[maxPos] < arr[i * 2 + 1]) {
maxPos = i * 2 + 1
}
if (maxPos === i) break // 循环直到i节点为最大值
this.swap(arr, i, maxPos) // 交换位置, 父节点为父/左/右中最大的一个
i = maxPos // i为左/右节点,并尝试向下查找更大的值
}
}
sort() {
const arr = this.buildHeap() // 先建堆
let len = arr.length - 1
while (len > 1) {
this.swap(arr, 1, len) // 交换顶元素和最后一位。顶元素永远是最大的。
len--
this.heapify(arr, len, 1) //剩下的元素重新建堆 直到len === 1 停止
}
console.log(arr)
}
swap(arr, i, max) {
let temp = arr[i]
arr[i] = arr[max]
arr[max] = temp
}
}
const arr = [null]
let i = 0
while (i <= 10) {
const num = Math.floor(Math.random() * 100)
arr.push(num)
i++
}
const testHeap = new HeapSort(arr)
testHeap.sort()

View File

@ -1,4 +1,4 @@
# 排序(
# 排序(平方时间复杂度排序算法
| 排序算法 | 时间复杂度 | 是否基于比较 |
|---------|----|----|

0
notes/12_sorts/.gitkeep Normal file
View File

176
notes/12_sorts/readme.md Normal file
View File

@ -0,0 +1,176 @@
# 排序(线性对数时间复杂度排序算法)
开篇问题:如何在 $O(n)$ 时间复杂度内寻找一个无序数组中第 K 大的元素?
## 归并排序
* 归并排序使用了「分治」思想Divide and Conquer
* 分:把数组分成前后两部分,分别排序
* 合:将有序的两部分合并
![归并排序分解图](https://static001.geekbang.org/resource/image/db/2b/db7f892d3355ef74da9cd64aa926dc2b.jpg)
* 分治与递归
* 分治:解决问题的处理办法
* 递归:实现算法的手段
* ——分治算法经常用递归来实现
* 递归实现:
* 终止条件:区间 `[first, last)` 内不足 2 个元素
* 递归公式:`merge_sort(first, last) = merge(merge_sort(first, mid), merge_sort(mid, last))`,其中 `mid = first + (last - first) / 2`
C++ 实现:
```cpp
template <typename FrwdIt,
typename T = typename std::iterator_traits<FrwdIt>::value_type,
typename BinaryPred = std::less<T>>
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<T> tmp;
tmp.reserve(len);
detail::merge(first, cut, cut, last, std::back_inserter(tmp), comp);
std::copy(tmp.begin(), tmp.end(), first);
}
```
这里涉及到一个 `merge` 的过程,它的实现大致是:
```cpp
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
```
![`merge` 的过程](https://static001.geekbang.org/resource/image/95/2f/95897ade4f7ad5d10af057b1d144a22f.jpg)
### 算法分析
* 稳定性
* 由于 `comp` 是严格偏序,所以 `!comp(*first2, *first1)` 时,取用 `first1` 的元素放入 `d_first` 保证了算法稳定性
* 时间复杂度
* 定义 $T(n)$ 表示问题规模为 $n$ 时算法的耗时,
* 有递推公式:$T(n) = 2T(n/2) + n$
* 展开得 $T(n) = 2^{k}T(1) + k * n$
* 考虑 $k$ 是递归深度,它的值是 $\log_2 n$,因此 $T(n) = n + n\log_2 n$
* 因此,归并排序的时间复杂度为 $\Theta(n\log n)$
* 空间复杂度
* 一般来说,空间复杂度是 $\Theta(n)$
## 快速排序quick sort快排
原理:
* 在待排序区间 `[first, last)` 中选取一个元素称为主元pivot枢轴
* 对待排序区间进行划分,使得 `[first, cut)` 中的元素满足 `comp(element, pivot)``[cut, last)` 中的元素不满足 `comp(element, pivot)`
* 对划分的两个区间,继续划分,直到区间 `[first, last)` 内不足 2 个元素
![快排分区示例](https://static001.geekbang.org/resource/image/4d/81/4d892c3a2e08a17f16097d07ea088a81.jpg)
显然,这又是一个递归:
* 终止条件:区间 `[first, last)` 内不足 2 个元素
* 递归公式:`quick_sort(first, last) = quick_sort(first, cut) + quick_sort(cut, last)`
```cpp
template <typename IterT, typename T = typename std::iterator_traits<IterT>::value_type>
void quick_sort(IterT first, IterT last) {
if (std::distance(first, last) > 1) {
IterT prev_last = std::prev(last);
IterT cut = std::partition(first, prev_last, [prev_last](T v) { return v < *prev_last; });
std::iter_swap(cut, prev_last);
quick_sort(first, cut);
quick_sort(cut, last);
}
}
```
> 一点优化Liam Huang通过将 `if` 改为 `while` 同时修改 `last` 迭代器的值,可以节省一半递归调用的开销。
```cpp
template <typename IterT, typename T = typename std::iterator_traits<IterT>::value_type>
void quick_sort(IterT first, IterT last) {
while (std::distance(first, last) > 1) {
IterT prev_last = std::prev(last);
IterT cut = std::partition(first, prev_last, [prev_last](T v) { return v < *prev_last; });
std::iter_swap(cut, prev_last);
quick_sort(cut, last);
last = cut;
}
}
```
如果不要求空间复杂度,分区函数实现起来很容易。
![非原地分区](https://static001.geekbang.org/resource/image/66/dc/6643bc3cef766f5b3e4526c332c60adc.jpg)
若要求原地分区,则不那么容易了。下面的实现实现了原地分区函数,并且能将所有相等的主元排在一起。
```cpp
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};
}
```
### 算法分析
* 稳定性
* 由于 `inplace_partition` 使用了大量 `std::iter_swap` 操作,所以不是稳定排序
* 时间复杂度
* 定义 $T(n)$ 表示问题规模为 $n$ 时算法的耗时,
* 有递推公式:$T(n) = 2T(n/2) + n$(假定每次分割都是均衡分割)
* 展开得 $T(n) = 2^{k}T(1) + k * n$
* 考虑 $k$ 是递归深度,它的值是 $\log_2 n$,因此 $T(n) = n + n\log_2 n$
* 因此,快速排序的时间复杂度为 $\Theta(n\log n)$
* 空间复杂度
* 一般来说,空间复杂度是 $\Theta(1)$,因此是原地排序算法
## 开篇问题
* 分区,看前半段元素数量
* 前半段元素数量 < K对后半段进行分区
* 前半段元素数量 > K对前半段进行分区
* 前半段元素数量 = K前半段末位元素即是所求

0
notes/13_sorts/.gitkeep Normal file
View File

77
notes/13_sorts/readme.md Normal file
View File

@ -0,0 +1,77 @@
# 线性排序
## 开篇问题
如何按年龄给 100 万用户排序?
## 桶排序Bucket Sort
算法思想:
* 按待排序数据的 key 分有序桶
* 桶内排序
* 有序桶依次输出
![桶排序示例](https://static001.geekbang.org/resource/image/98/ae/987564607b864255f81686829503abae.jpg)
### 算法分析
* 时间复杂度 $O(n)$
* $n$ 个元素,分 $m$ 个有序桶,每个桶里平均 $k = n / m$ 个元素
* 桶内快排,复杂度 $O(k \log k)$$m$ 个桶一共 $O(n \log k)$
* 当 $m$ 接近 $n$,例如当 $k = 4$ 时,这个复杂度近似 $O(n)$
* 使用条件
* 数据易于分如有序桶
* 数据在各个有序桶之间分布均匀
* 适合外部排序——数据不全部载入磁盘
## 计数排序Counting Sort
计数排序可以视作是桶排序的一个特殊情况:
* 数据的取值范围很小
* 每个分桶内的元素 key 值都一样
此时,由于分桶内的元素 key 值都一样,所以桶内的排序操作可以省略,以及桶的编号本身就能记录桶内元素的值。因此,算法只需遍历一遍所有的数据,统计每个取值上有多少元素即可。这个过程时间复杂度是 $O(n)$。
* 假设待排序的数组 `A = {2, 5, 3, 0, 2, 3, 0, 3}`,我们有计数数组 `C = {2, 0, 2, 3, 0, 1}`
接下来,我们要对 `C` 进行计数操作,具体来说,对从下标为 1 的元素开始累加 `C[i] += C[i - 1]`
* 计数累加 `C = {2, 2, 4, 7, 7, 8}`
此时,`C` 中的元素表示「小于等于下标的元素的个数」。接下来,我们从尾至头扫描待排序数组 `A`,将其中元素依次拷贝到输出数组 `R` 的相应位置。我们注意到,`A[7] = 3` 而 `C[3] == 4` 。这意味着,待排序的数组中,包括 3 本身在内,不超过 3 的元素共有 4 个。因此,我们可以将这个 3 放置在 `R[C[3] - 1]` 的位置,而后将 `C[3]` 的计数减一——这是由于待排序数组中未处理的部分,不超过 3 的元素现在只剩下 3 个了。如此遍历整个待排序数组 `A`,即可得到排序后的结果 `R`
![计数排序示例](https://static001.geekbang.org/resource/image/1d/84/1d730cb17249f8e92ef5cab53ae65784.jpg)
### 算法分析
* 时间复杂度
* $n$ 个元素,最大值是 $k$,分 $k$ 个「桶」;时间复杂度 $O(n)$
* 桶内计数累加;时间复杂度 $O(k)$
* 摆放元素;时间复杂度 $O(n)$
* 当 $k < n$ 总体时间复杂度是 $O(n)$
* 使用条件
* $k < n$
* 待排序数据的 key 是非负整数
## 基数排序Radix Sort
基数排序适用于等长数据的排序。对于不等长数据,可以在较短的数据后面做 padding使得数据等长。
* 先就 least significant digit 进行稳定排序——通常可以用桶排序或者计数排序;时间复杂度 $O(n)$
* 而后依次向 greatest significant digit 移动,进行稳定排序
![基数排序示例](https://static001.geekbang.org/resource/image/df/0c/df0cdbb73bd19a2d69a52c54d8b9fc0c.jpg)
### 算法分析
* 时间复杂度
* 对每一位的排序时间复杂度是 $O(n)$
* 总共 $k$ 位,因此总的时间复杂度是 $O(kn)$;考虑到 $k$ 是常数,因此总的时间复杂度是 $O(n)$
* 使用条件
* 等长数据
## 解答开篇
桶排序。

0
notes/14_sorts/.gitkeep Normal file
View File

10
notes/14_sorts/readme.md Normal file
View File

@ -0,0 +1,10 @@
# 排序优化
## 如何取舍排序算法?
* 排序规模小 —— $O(n^2)$ 的算法(通常是插排)
* 排序规模大 —— $O(n\log n)$ 的算法(通常不用归并排序)
## 如何优化快速排序?
参考:[谈谈内省式排序算法](https://liam.page/2018/08/29/introspective-sort/)

View File

View File

@ -0,0 +1,23 @@
# 二分查找(上)
## 算法描述
二分查找Binary Search也叫折半查找是针对有序数据集合的查找算法。其描述十分简单
* 折半取中,判断元素与目标元素的大小关系
* 小于——往前继续折半
* 大于——往后继续折半
* 等于——返回
关于它的复杂度分析,参见[谈谈基于比较的排序算法的复杂度下界](https://liam.page/2018/08/28/lower-bound-of-comparation-based-sort-algorithm/)中的相关信息。它的复杂度是 $O(\log n)$。
## $O(\log n)$ 的惊人之处
在 42 亿个数据中用二分查找一个数据,最多需要比较 32 次。
## 适用场景
* 依赖顺序表结构
* 数据本身必须有序
* 数据量相对比较元素的开销要足够大——不然遍历即可
* 数据量相对内存空间不能太大——不然顺序表装不下

View File

100
notes/16_bsearch/readme.md Normal file
View File

@ -0,0 +1,100 @@
# 二分查找(下)
本节课讨论二分的各种变体。实际上在针对上一节的代码中,已经实现了两个变体。本次实现四个变体:
* 第一个等于给定值的元素
* 最后一个等于给定值的元素
* 第一个不小于给定值的元素
* 最后一个不大于给定值的元素
```cpp
/**
* Created by Liam Huang (Liam0205) on 2018/10/26.
*/
#ifndef BSEARCH_BSEARCH_VARIENTS_HPP_
#define BSEARCH_BSEARCH_VARIENTS_HPP_
#include <iterator>
#include <functional>
enum class BsearchPolicy { UNSPECIFIED, FIRST, LAST, FIRST_NOT_LESS, LAST_NOT_GREATER };
// Liam Huang: The algorithm works right with iterators that meet the ForwardIterator requirement,
// but with a bad time complexity. For better performance, iterators should meet
// the RandomAccessIterator requirement.
template <typename IterT,
typename ValueT = typename std::iterator_traits<IterT>::value_type,
typename Compare>
IterT bsearch(IterT first,
IterT last,
ValueT target,
Compare comp,
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
IterT result = last;
while (std::distance(first, last) > 0) {
IterT mid = first + std::distance(first, last) / 2;
if (policy == BsearchPolicy::FIRST_NOT_LESS) {
if (!comp(*mid, target)) {
if (mid == first or comp(*(mid - 1), target)) {
result = mid;
break;
} else {
last = mid;
}
} else {
first = mid + 1;
}
} else if (policy == BsearchPolicy::LAST_NOT_GREATER) {
if (comp(target, *mid)) {
last = mid;
} else {
if (std::distance(mid, last) == 1 or comp(target, *(mid + 1))) {
result = mid;
break;
} else {
first = mid + 1;
}
}
} else { // policy == UNSPECIFIED or FIRST or LAST
if (comp(*mid, target)) {
first = mid + 1;
} else if (comp(target, *mid)) {
last = mid;
} else { // equal
if (policy == BsearchPolicy::FIRST) {
if (mid == first or comp(*(mid - 1), *mid)) {
result = mid;
break;
} else {
last = mid;
}
} else if (policy == BsearchPolicy::LAST) {
if (std::distance(mid, last) == 1 or comp(*mid, *(mid + 1))) {
result = mid;
break;
} else {
first = mid + 1;
}
} else {
result = mid;
break;
}
}
}
}
return result;
}
template <typename IterT,
typename ValueT = typename std::iterator_traits<IterT>::value_type,
typename Compare = std::less<ValueT>>
IterT bsearch(IterT first,
IterT last,
ValueT target,
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
return bsearch(first, last, target, Compare(), policy);
}
#endif // BSEARCH_BSEARCH_VARIENTS_HPP_
```

View File

View File

@ -0,0 +1,43 @@
# 跳表Skip List
支持快速地:
* 插入
* 删除
* 查找
某些情况下跳表甚至可以替代红黑树Red-Black tree。Redis 当中的有序集合Sorted Set是用跳表实现的。
## 跳表的结构
跳表是对链表的改进。对于单链表来说,即使内容是有序的,查找具体某个元素的时间复杂度也要达到 $O(n)$。对于二分查找来说,由于链表不支持随机访问,根据 `first``last` 确定 `cut` 时,必须沿着链表依次迭代 `std::distance(first, last) / 2` 步;特别地,计算 `std::(first, last)` 本身,就必须沿着链表迭代才行。此时,二分查找的效率甚至退化到了 $O(n \log n)$,甚至还不如顺序遍历。
![单链表查找示例](https://static001.geekbang.org/resource/image/e1/6d/e18303fcedc068e5a168de04df956f6d.jpg)
跳表的核心思想是用空间换时间,构建足够多级数的索引,来缩短查找具体值的时间开销。
![具有二级索引的跳表示例](https://static001.geekbang.org/resource/image/49/65/492206afe5e2fef9f683c7cff83afa65.jpg)
例如对于一个具有 64 个有序元素的五级跳表,查找起来的过程大约如下图所示。
![五级跳表示例](https://static001.geekbang.org/resource/image/46/a9/46d283cd82c987153b3fe0c76dfba8a9.jpg)
## 复杂度分析
对于一个每一级索引的跨度是下一级索引 $k$ 倍的跳表,每一次 `down` 操作,相当于将搜索范围缩小到「剩余的可能性的 $1 / k$」。因此,查找具体某个元素的时间复杂度大约需要 $\lfloor \log_k n\rfloor + 1$ 次操作;也就是说时间复杂度是 $O(\log n)$。
![跳表查询过程示例](https://static001.geekbang.org/resource/image/d0/0c/d03bef9a64a0368e6a0d23ace8bd450c.jpg)
前面说了,跳表是一种用空间换时间的数据结构。因此它的空间复杂度一定不小。我们考虑原链表有 $n$ 个元素,那么第一级索引就有 $n / k$ 个元素,剩余的索引依次有 $n / k^2$, $n / k^3$, ..., $1$ 个元素。总共的元素个数是一个等比数列求和问题,它的值是 $\frac{n - 1}{k - 1}$。可见,不论 $k$ 是多少,跳表的空间复杂度都是 $O(n)$;但随着 $k$ 的增加,实际需要的额外节点数会下降。
## 高效地插入和删除
对于链表来说,插入或删除一个给定结点的时间复杂度是 $O(1)$。因此,对于跳表来说,插入或删除某个结点,其时间复杂度完全依赖于查找这类结点的耗时。而我们知道,在跳表中查找某个元素的时间复杂度是 $O(\log n)$。因此,在跳表中插入或删除某个结点的时间复杂度是 $O(\log n)$。
![在跳表中插入一个元素](https://static001.geekbang.org/resource/image/65/6c/65379f0651bc3a7cfd13ab8694c4d26c.jpg)
## 跳表索引的动态更新
为了维护跳表的结构,在不断插入数据的过程中,有必要动态维护跳表的索引结构。一般来说,可以采用随机层级法。具体来说是引入一个输出整数的随机函数。当随机函数输出 $K$,则更新从第 $1$ 级至第 $K$ 级的索引。为了保证索引结构和数据规模大小的匹配,一般采用二项分布的随机函数。
![在跳表中插入一个元素并更新索引](https://static001.geekbang.org/resource/image/a8/a7/a861445d0b53fc842f38919365b004a7.jpg)

View File

View File

@ -0,0 +1,69 @@
# 散列表
散列表是数组的一种扩展,利用数组下标的随机访问特性。
## 散列思想
* 键/关键字/Key用来标识一个数据
* 散列函数/哈希函数/Hash将 Key 映射到数组下标的函数
* 散列值/哈希值Key 经过散列函数得到的数值
![](https://static001.geekbang.org/resource/image/92/73/92c89a57e21f49d2f14f4424343a2773.jpg)
本质:利用散列函数将关键字映射到数组下标,而后利用数组随机访问时间复杂度为 $\Theta(1)$ 的特性快速访问。
## 散列函数
* 形式:`hash(key)`
* 基本要求
1. 散列值是非负整数
1. 如果 `key1 == key2`,那么 `hash(key1) == hash(key2)`
1. 如果 `key1 != key2`,那么 `hash(key1) != hash(key2)`
第 3 个要求,实际上不可能对任意的 `key1``key2` 都成立。因为通常散列函数的输出范围有限而输入范围无限。
## 散列冲突¡
* 散列冲突:`key1 != key2` 但 `hash(key1) == hash(key2)`
散列冲突会导致不同键值映射到散列表的同一个位置。为此,我们需要解决散列冲突带来的问题。
### 开放寻址法
如果遇到冲突,那就继续寻找下一个空闲的槽位。
#### 线性探测
插入时,如果遇到冲突,那就依次往下寻找下一个空闲的槽位。(橙色表示已被占用的槽位,黄色表示空闲槽位)
![](https://static001.geekbang.org/resource/image/5c/d5/5c31a3127cbc00f0c63409bbe1fbd0d5.jpg)
查找时,如果目标槽位上不是目标数据,则依次往下寻找;直至遇见目标数据或空槽位。
![](https://static001.geekbang.org/resource/image/91/ff/9126b0d33476777e7371b96e676e90ff.jpg)
删除时,标记为 `deleted`,而不是直接删除。
#### 平方探测Quadratic probing
插入时,如果遇到冲突,那就往后寻找下一个空闲的槽位,其步长为 $1^2$, $2^2$, $3^2$, $\ldots$。
查找时,如果目标槽位上不是目标数据,则依次往下寻找,其步长为 $1^2$, $2^2$, $3^2$, $\ldots$;直至遇见目标数据或空槽位。
删除时,标记为 `deleted`,而不是直接删除。
#### 装载因子load factor
$\text{load factor} = \frac{size()}{capacity()}$
### 链表法
所有散列值相同的 key 以链表的形式存储在同一个槽位中。
![](https://static001.geekbang.org/resource/image/a4/7f/a4b77d593e4cb76acb2b0689294ec17f.jpg)
插入时,不论是否有冲突,直接插入目标位置的链表。
查找时,遍历目标位置的链表来查询。
删除时,遍历目标位置的链表来删除。

View File

View File

@ -0,0 +1,59 @@
# 散列表
核心:散列表的效率并不总是 $O(1)$,仅仅是在理论上能达到 $O(1)$。实际情况中,恶意攻击者可以通过精心构造数据,使得散列表的性能急剧下降。
如何设计一个工业级的散列表?
## 散列函数
* 不能过于复杂——避免散列过程耗时
* 散列函数的结果要尽可能均匀——最小化散列冲突
## 装载因子过大怎么办
动态扩容。涉及到 rehash效率可能很低。
![](https://static001.geekbang.org/resource/image/67/43/67d12e07a7d673a9c1d14354ad029443.jpg)
如何避免低效扩容?
——将 rehash 的步骤,均摊到每一次插入中去:
* 申请新的空间
* 不立即使用
* 每次来了新的数据,往新表插入数据
* 同时,取出旧表的一个数据,插入新表
![](https://static001.geekbang.org/resource/image/6d/cb/6d6736f986ec4b75dabc5472965fb9cb.jpg)
## 解决冲突
开放寻址法,优点:
* 不需要额外空间
* 有效利用 CPU 缓存
* 方便序列化
开放寻址法,缺点:
* 查找、删除数据时,涉及到 `delete` 标志,相对麻烦
* 冲突的代价更高
* 对装载因子敏感
链表法,优点:
* 内存利用率较高——链表的优点
* 对装载因子不敏感
链表法,缺点:
* 需要额外的空间(保存指针)
* 对 CPU 缓存不友好
——将链表改造成更高效的数据结构,例如跳表、红黑树
## 举个栗子JAVA 中的 HashMap
* 初始大小16
* 装载因子:超过 0.75 时动态扩容
* 散列冲突:优化版的链表法(当槽位冲突元素超过 8 时使用红黑树,否则使用链表)

View File

@ -28,8 +28,6 @@ function expression($str)
array_push($operStack, $arr[$i]);
break;
case '*':
<<<<<<< HEAD
=======
$arrLen = count($operStack);
while ($operStack[$arrLen-1] === '/'){
compute($numStack, $operStack);
@ -38,7 +36,6 @@ function expression($str)
array_push($operStack, $arr[$i]);
break;
>>>>>>> upstream/master
case '/':
case '(':
array_push($operStack, $arr[$i]);
@ -81,13 +78,9 @@ function compute(&$numStack, &$operStack){
case '-':
array_push($numStack, array_pop($numStack) - $num);
break;
<<<<<<< HEAD
=======
case '(':
throw new \Exception("不匹配的(", 2);
break;
>>>>>>> upstream/master
}
}
expression('-1+2-(1+2*3)');

47
php/12_sort/quicksort.php Normal file
View File

@ -0,0 +1,47 @@
<?php
function quickSort(array &$a)
{
$n = count($a);
quickSortInternally($a, 0, $n-1);
}
function quickSortInternally(array &$a, int $l, int $r)
{
if ($l >= $r) return;
$q = partition($a, $l, $r);
quickSortInternally($a, $l, $q-1);
quickSortInternally($a, $q+1, $r);
}
function partition(&$a, $l, $r): int
{
$pivot = $a[$r];
$i = $l;
for ($j = $l; $j < $r; ++$j) {
if ($a[$j] < $pivot) {
[$a[$j], $a[$i]] = [$a[$i], $a[$j]];
++$i;
}
}
[$a[$r], $a[$i]] = [$a[$i], $a[$r]];
return $i;
}
$a1 = [1,4,6,2,3,5,4];
$a2 = [2, 2, 2, 2];
$a3 = [4, 3, 2, 1];
$a4 = [5, -1, 9, 3, 7, 8, 3, -2, 9];
quickSort($a1);
print_r($a1);
quickSort($a2);
print_r($a2);
quickSort($a3);
print_r($a3);
quickSort($a4);
print_r($a4);

View File

@ -0,0 +1,50 @@
<?php
require_once '../12_sort/quickSort.php';
$numbers = [11,23,45,67,88,99,22,34,56,78,90,12,34,5,6,91,92,93,93,94,95,94,95,96,97,98,99,100];
$size = 10;
var_dump(bucketSort($numbers,10));//加在了quickSort文件请忽略前几个打印
/**
* 桶排序
* 假设一个桶只能放置10个元素
* 当一个桶内元素过多,需要继续分桶
* @param array $numbers
* @param [type] $size
*
* @return void
* @date 2018/11/25
* @author yuanliandu
*/
function bucketSort(array $numbers) {
$min = min($numbers);
$max = max($numbers);
$length = count($numbers);
$bucketNumber = ceil(($max-$min)/$length) + 1;
$buckets = [];
foreach($numbers as $key => $value) {
$index = ceil(($value-$min)/$length);
$buckets[$index][] = $value;
}
$result = [];
for($i=0;$i<$bucketNumber;$i++) {
$bucket = $buckets[$i];
$length = count($bucket);
//如果桶内元素为空,跳过这个桶
if($length == 0) {
continue;
}
if( $length > 10) {
$bucket = bucketSort($bucket,$length);
}
quickSort($bucket,0,count($bucket)-1);
$result = array_merge($result,$bucket);
}
return $result;
}

View File

@ -0,0 +1,43 @@
<?php
/**
* 计数排序
* 五分制
* 13个人
*/
$score = [0,1,5,3,2,4,1,2,4,2,1,4,4];
var_dump(countingSort($score));die();
function countingSort(array $score) {
$length = count($score);
if($length <= 1) {return $score;}
/**
* 统计每个分数的人数
*/
$temp = [];
$countScore = [];
foreach ($score as $key => $value) {
$countScore[$value]++;
}
/**
* 顺序求和
*/
for($i=1;$i<=5;$i++) {
$countScore[$i] += $countScore[$i-1];
}
/**
* 排序
*/
foreach ($score as $key => $value) {
$countScore[$value] --;
$temp[$countScore[$value]] = $value;
}
//copy
for($i=0;$i<$length;$i++) {
$score[$i] = $temp[$i];
}
return $score;
}

48
php/13_sort/radixSort.php Normal file
View File

@ -0,0 +1,48 @@
<?php
/**
* 基数排序
* 先根据个位排序、百位、千位........
*/
$numbers = [
1234,
4321,
12,
31,
412,
];
$max = (string) max($numbers);//求出最大数字
$loop = strlen($max);//计算最大数字的长度,决定循环次数
for($i=0;$i<$loop;$i++) {
radixSort($numbers,$i);
}
var_dump($numbers);
/**
* 基数排序
* @param array $numbers
* @param [type] $loop
*
* @return void
* @date 2018/11/26
* @author yuanliandu
*/
function radixSort(array &$numbers,$loop) {
$divisor = pow(10,$loop);//除数 主要决定比较个位数、百位.....
$buckets = (new \SplFixedArray(10))->toArray();
foreach ($numbers as $key => $value) {
$index = ($value/$divisor)%10;//计算该数字在哪个桶中
$buckets[$index][] = $value;
}
/**
* 从桶中取出数字
*/
$k=0;
for($i=0;$i<10;$i++) {
while(count($buckets[$i]) > 0) {
$numbers[$k++] = array_shift($buckets[$i]);
}
}
}

98
php/15_binary/binary.php Normal file
View File

@ -0,0 +1,98 @@
<?php
/**
* 二分查找 查找=find的元素
* @param array $numbers
* @param [type] $find
*
* @return void
* @date 2018/11/26
* @author yuanliandu
*/
function binarySearch(array $numbers, $find)
{
$low = 0;
$high = count($numbers) - 1;
return search($numbers, $low, $high, $find);
}
function search(array $numbers, $low, $high, $find)
{
/**
* notice1 循环退出条件
*/
if ($low > $high) {
return -1;
}
/**
* notice2 mid计算
*/
$mid = $low + (($high - $low) >> 1);
if ($numbers[$mid] > $find) {
//notice3 high值更新
return search($numbers, $low, $mid -1, $find);
} elseif ($numbers[$mid] < $find) {
//notice4 low值更新
return search($numbers, $mid + 1, $high, $find);
} else {
return $mid;
}
}
/**
* 求数字的平方根保留6位小数
* @param [type] $number
*
* @return void
* @date 2018/11/26
* @author yuanliandu
*/
function squareRoot($number)
{
if ($number < 0) {
return -1;
} elseif ($number < 1) {
$min = $number;
$max = 1;
} else {
$min = 1;
$max = $number;
}
$mid = $min + ($max - $min) / 2;
while (getDecimalPlaces($mid) < 6) {
$square = $mid * $mid;
if ($square > $number) {
$max = $mid;
} elseif ($square == $number) {
return $mid;
} else {
$min = $mid;
}
$mid = $min + ($max - $min) / 2;
}
return $mid;
}
/**
* 计算数字小数点后有几位数字
* @param [type] $number
*
* @return void
* @date 2018/11/27
* @author yuanliandu <yuanliandu@qq.com>
*/
function getDecimalPlaces($number)
{
$temp = explode('.', $number);
return strlen($temp[1]);
}
// 测试二分查找给定值
$numbers = [0, 1, 2, 3, 3, 4, 5, 6, 7, 9];
$find = 1;
var_dump(binarySearch($numbers,$find));
//测试求平方根
var_dump(squareRoot(3));

191
php/16_binary/binary.php Normal file
View File

@ -0,0 +1,191 @@
<?php
/**
* 找到第一个=value的元素
* @param array $numbers
*
* @return void
* @date 2018/11/27
* @author yuanliandu <yuanliandu@qq.com>
*/
function findFirstEqual(array $numbers,$find) {
$length = count($numbers);
$low = 0;
$high = $length - 1;
while($low <= $high) {
$mid = $low + (($high-$low)>>1);
if($numbers[$mid] > $find) {
$high = $mid - 1;
}else if($numbers[$mid] < $find) {
$low = $mid + 1;
}else {
/**
* 如果是第一个元素,或之前一个元素不等于我们要找的值
* 我们就找到了第一个=find的element
*/
if($mid==0 || $numbers[$mid-1]!=$find) {
return $mid;
}else {
$high = $mid - 1;
}
}
}
return -1;
}
/**
* 找到最后一个=find的元素
* @param array $numbers
* @param [type] $find
*
* @return void
* @date 2018/11/27
* @author yuanliandu <yuanliandu@qq.com>
*/
function findLastEqual(array $numbers,$find) {
$length = count($numbers);
$low = 0;
$high = $length - 1;
while($low <= $high) {
$mid = $low + (($high-$low)>>1);
if($numbers[$mid] > $find) {
$high = $mid - 1;
}else if($numbers[$mid] < $find) {
$low = $mid + 1;
}else {
/**
* 如果mid是最后一个元素的index
* 或mid后一个元素!=我们要找的值
* 则找到了最后一个=find的value
*/
if($mid==$length-1 || $numbers[$mid+1]!=$find) {
return $mid;
}else {
$low = $mid + 1;
}
}
}
return -1;
}
/**
* 找到第一个大于等于find的元素
* @param array $numbers
* @param [type] $find
*
* @return void
* @date 2018/11/27
* @author yuanliandu <yuanliandu@qq.com>
*/
function findFirstGreaterEqual(array $numbers,$find) {
$length = count($numbers);
$low = 0;
$high = $length - 1;
while($low <= $high) {
$mid = $low + (($high-$low)>>1);
if($numbers[$mid] >= $find) {
if ($mid == 0 || $numbers[$mid-1] < $find) {
return $mid;
}else {
$high = $mid - 1;
}
}else {
$low = $mid + 1;
}
}
return -1;
}
/**
* 找到最后一个小于等于find的元素
* @param array $numbers
* @param [type] $find
*
* @return void
* @date 2018/11/27
* @author yuanliandu <yuanliandu@qq.com>
*/
function findLastLessEqual(array $numbers,$find) {
$length = count($numbers);
$low = 0;
$high = $length - 1;
while($low <= $high) {
$mid = $low + (($high-$low)>>1);
if($numbers[$mid] <= $find) {
if($mid==$length-1 || $numbers[$mid+1]> $find) {
return $mid;
}
$low = $mid + 1;
}else {
$high = $mid - 1;
}
}
return -1;
}
/**
* 循环数组中找指定元素
* @param array $numbers
* @param [type] $find
*
* @return void
* @date 2018/11/27
* @author yuanliandu <yuanliandu@qq.com>
*/
function searchCircularArray(array $numbers,$find) {
$length = count($numbers);
$low = 0;
$high = $length - 1;
while($low <= $high) {
$mid = $low + (($high-$low)>>1);
if($numbers[$mid] === $find) {
return $mid;
}
if($numbers[$low] > $numbers[$mid]) {
// 后半部分是有序数组
if(($numbers[$mid] < $find) && ($numbers[$high] >= $find)) {
if($numbers[$high] === $find) return $high;
//在后半个区间内
$low = $mid + 1;
}else {
$high = $mid - 1;
}
}else {
// 前半部分是有序的
if(($numbers[$low] <= $find) && ($numbers[$mid] > $find)) {
// 在有序区间内
if($numbers[$low] === $find) return $low;
$high = $mid - 1;
}else {
$low = $mid + 1;
}
}
}
return -1;
}
/***
* 测试
*/
$numbers = [1,2,3,3,3,4,5,6,8,11,13];
$find = 3;
var_dump(findFirstEqual($numbers,$find));//找到第一个等于find的元素
var_dump(findFirstGreaterEqual($numbers,$find));//找到第一个大于等于find的元素
var_dump(findLastEqual($numbers,$find));//找到最后一个=find的元素
var_dump(findLastLessEqual($numbers,$find));//找到最后一个小于等于find的元素
//测试在循环数组中找到指定数字
$numbers = [9,10,1,2,3,4,5,6,7,8];
$find = 2;
var_dump(searchCircularArray($numbers,$find));

View File

@ -17,11 +17,7 @@
* findMiddleNode 求链表的中间结点
#### 08_stack
<<<<<<< HEAD
* 链栈实现
=======
* 链栈实现
#### 09_stack
* 队列链表实现
>>>>>>> upstream/master

View File

@ -7,12 +7,8 @@
"psr-4": {
"Algo_06\\": "06_linkedlist/",
"Algo_07\\": "07_linkedlist/",
<<<<<<< HEAD
"Algo_08\\": "08_stack/"
=======
"Algo_08\\": "08_stack/",
"Algo_09\\": "09_queue/"
>>>>>>> upstream/master
}
}
}

BIN
python/.vs/slnx.sqlite Normal file

Binary file not shown.

View File

@ -1,4 +1,6 @@
from typing import Optional
#
# 1) Insertion, deletion and random access of array
# 2) Assumes int for element type
@ -25,38 +27,68 @@ class MyArray:
def find(self, index: int) -> Optional[int]:
if index >= self._count or index <= -self._count: return None
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
if index >= self._count or index <= -self._count:
return False
self._data[index:-1] = self._data[index+1:]
self._data[index:-1] = self._data[index + 1:]
self._count -= 1
# 真正将数据删除并覆盖原来的数据 ,这个需要增加
self._data = self._data[0:self._count]
print ('delet function',self._data)
print('delete function', self._data)
return True
def insert(self, index: int, value: int) -> bool:
#if index >= self._count or index <= -self._count: return False
if self._capacity == self._count: return False
# if index >= self._count or index <= -self._count: return False
if self._capacity == self._count:
return False
# 如果还有空间,那么插入位置大于当前的元素个数,可以插入最后的位置
if index >= self._count:
self._data.append(value)
# 同上如果位置小于0 可以插入第0个位置.
if index < 0:
print (index)
print(index)
self._data.insert(0, value)
self._count += 1
return True
def insert_v2(self, index: int, value: int) -> bool:
"""
支持任意位置插入
:param index:
:param value:
:return:
"""
# 数组空间已满
if self._capacity == self._count:
return False
# 插入位置大于当前的元素个数,可以插入最后的位置
if index >= self._count:
self._data.append(value)
elif index < 0:
# 位置小于 0 可以插入第 个位置
self._data.insert(0, value)
else:
# 挪动 index 至 _count 位到 index+1 至 _count+1 位
# 插入第 index
self._data[index+1:self._count+1] = self._data[index:self._count]
self._data[index] = value
self._count += 1
return True
def insert_to_tail(self, value: int) -> bool:
if self._count == self._capacity: return False
if self._count == self._capacity:
return False
if self._count == len(self._data):
self._data.append(value)
else:
@ -71,25 +103,31 @@ class MyArray:
def print_all(self):
for num in self._data[:self._count]:
print("{num}", end=" ")
print(f"{num}", end=" ")
print("\n", flush=True)
def test_myarray():
array_a = MyArray(6)
for num in range(6):
array_a.insert_to_tail(num)
assert array_a.find(0) == 0
assert array_a[0] == 0
array_a.delete(0)
assert array_a[0] == 1
if __name__ == "__main__":
a = MyArray(6)
for i in range(6):
a.insert_to_tail(i)
<<<<<<< HEAD
a.delete(2)
print(a)
a.insert_to_tail(7)
print(a)
=======
print('origin',a)
print('origin', a)
a.delete(4)
print ('delete ',a)
print('delete ', a)
a.insert(100,10000)
print (a)
>>>>>>> upstream/master
a.insert(100, 10000)
print(a)

Some files were not shown because too many files have changed in this diff Show More