C++ code note
unique_ptr
#ifndef _UNIQUE_PTR_H
#define __UNIQUE_H
class Delete {
public:
template<typename T>
void operator()(T *p) const {
delete p;
}
};
template<typename T,typename D = Delete >
class unique_ptr {
public:
explicit unique_ptr(T *pp = nullptr ,const D &dd = D() ):
un_ptr(pp), del(dd)
{
}
~unique_ptr()
{
del(un_ptr);
}
/* 不支持拷贝与赋值 */
unique_ptr(const unique_ptr&) = delete ;
unique_ptr& operator=(const unique_ptr& ) = delete ;
/* 移动赋值与移动拷贝 */
unique_ptr( unique_ptr&& right_value):
un_ptr(right_value.un_ptr),del(std::move(right_value.del)) {
right_value.un_ptr = nullptr ;
}
unique_ptr& operator=( unique_ptr&& right_value ) noexcept {
if(this != &right_value ){
std::cout << "operator && right_value " << std::endl ;
del(*this);
un_ptr = right_value.un_ptr;
del = std::move(right_value.del);
right_value.un_ptr = nullptr ;
}
return *this ;
}
//u.release() u 放弃对指针的控制权,返回指针,并将 u 置为空
T* release(){
T *tmp = un_ptr ;
un_ptr = nullptr ;
return tmp;
}
/*
u.reset() 释放u指向的对象
u.reset(q) 如果提供了内置指针q,就令u指向这个对象
u.reset(nullptr) 将 u 置为空
*/
void reset(T* q = nullptr){
del(un_ptr);
un_ptr = q;
}
void swap(unique_ptr &other ) noexcept {
std::swap(un_ptr, other.un_ptr);
std::swap(del, other.del) ;
}
T* get() { return un_ptr; }
D& get_deleter(){ return del; }
T& operator*() { return *un_ptr; }
T* operator->() { return un_ptr; }
private:
T *un_ptr = nullptr ;
D del ;
};
#endif
shared_ptr
https://www.cnblogs.com/howo/p/8468713.html
//
// SharedPtr.hpp
// SharedPtr
//
// Created by 顾浩 on 24/2/18.
// Copyright © 2018 顾浩. All rights reserved.
//
#ifndef SHARED_PTR_H
#define SHARED_PTR_H
#include <iostream>
using namespace std;
template<typename T>
class SharedPtr {
public:
SharedPtr() : _ptr((T *)0), _refCount(0)
{
}
SharedPtr(T *obj) : _ptr(obj), _refCount(new int(1))
{
cout<<"create object : "<<*_ptr<<"\trefCount = 1"<<endl;
}
SharedPtr(SharedPtr &other) : _ptr(other._ptr), _refCount(&(++*other._refCount))
{
cout<<"copy constructor : "<<*_ptr<<"\trefCount = "<<*_refCount<<endl;
}
~SharedPtr()
{
if(_ptr && --*_refCount == 0) {
cout<<*_ptr<<"\trefCount = 0. delete the _ptr:"<<*_ptr<<endl;
delete _ptr;
delete _refCount;
}
}
SharedPtr &operator=(SharedPtr &other)
{
if(this==&other) return *this;
++*other._refCount;
if(--*_refCount == 0) {
cout<<"in function operator = . delete "<<*_ptr<<endl;
delete _ptr;
delete _refCount;
}
_ptr = other._ptr;
_refCount = other._refCount;
cout<<"in function operator = . "<<*_ptr<<"\t_refCount = "<<*_refCount<<endl;
return *this;
}
T *operator->()
{
if(_refCount == 0) return 0;
return _ptr;
}
T &operator*()
{
if (_refCount == 0) return (T*)0;
return *_ptr;
}
private:
T *_ptr;
int *_refCount; //should be int*, rather than int
};
#endif /* SharedPtr_h */
partion
int par(T a[],int l,int r){
int R = r;
T x = a[R];
while(l<r){
while(l<r&&a[l]<=x) ++l;
while(l<r&&a[r]>=x) --r;
swap(a[l], a[r]);
}
swap(a[l], a[R]);
return l;
}
T F(T A[], int l, int r, int k) {
int pos = par(A, l, r);
if(pos == k) return A[k];
else if(pos < k)
return F(A, pos+1, r, k);
else
return F(A, l, pos-1, k);
}
T Median( T A[], int N ){
return F(A, 0, N-1, N/2);
}
hash_table
template<class Value>
struct __hashtable_node {
__hashtable_node *next;
Value val;
};
template<class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc>
struct __hashtable_iterator {
typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> hashtable;
typedef __hashtable_node<Value> node;
node *cur;
hashtable *ht;
}
template<class Value, class Key, class HashFcn, class ExtractKey, class EqualKey, class Alloc = alloc>
class hashtable{
public:
typedef Key key_type;
typedef Value value_type;
typedef HashFcn hasher;
typedef EqualKey key_equal;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef value_type *pointer;
typedef value_type &reference;
private:
hasher hash;
key_equal equals;
ExtractKey get_key;
typedef __hashtable_node<Value> node;
typedef simple_alloc<node, Alloc> node_alocator;
vector<node*, Alloc> buckets;
size_type num_elements;
public:
//hash_table源码中有重载的构造函数,这里我选了其中一种。
hashtable(size_type n, const HashFcn& hf, const EqualKey& eql,
const ExtractKey& ext)
:hash(hf),equals(eql),get_key(ext),num_elements(0)
{
initialize_buckets(n);
}
~hashtable(){ clear(); }
private:
static const int __stl_num_prime_last = 28;
static const unsigned long __stl_prime_list[__stl_num_primes] =
{
53, 97, 193, 389, 769,
1543, 3079, 6151, 12289, 24593,
49157, 98317, 196613, 393241, 786433,
1572869, 3145739, 6291469, 12582917, 25165843,
50331653, 100663319, 201326611, 402653189, 805306457,
1610612741, 3221225473ul, 4294967291ul
};
void initialize_buckets(size_type n)
{
const size_type n_buckets = next_size(n);
buckets.reserve(n_buckets);
buckets.insert(buckets.end(), n_buckets, (node*)0);
num_elements = 0;
}
size_type next_size(size_type n)const
{
return __stl_next_prime(n);
}
unsigned long __stl_next_prime(unsigned long n)
{
const unsigned long *first = __stl_prime_list;
const unsigned long *last = __stl_prime_list + __stl_num_primes;
const unsigned long *pos = lower_bound(first, last, n);
return pos == last ? *(last-1) : *pos ;
}
//STL中如何判断元素的落脚处
size_type bkt_num(const value_type& obj, size_t n)const
{
return bkt_num_key(get_key(obj), n);
}
size_type bkt_num_key(const key_type& key, size_t n)
{
return hash(key) % n;
}
pair<iterator, bool> insert_unique(const value_type& obj)
{
resize(num_element + 1); //插入元素前先判断需不需要重建vector
return insert_unique_noresize(obj);
}
template<class V, class K, clss HF, class Ex, class Eq, class A>
void hashtable<V, K, HF, Ex, Eq, A>::resize(size_type num_element_hint)
{
const size_type old_n = buckets.size();
if(num_element_hint > old_n){
const size_type n = next_size(num_element_hint);
if(n > old_n){
vector<node *, A> tmp(n, (node*)0);
for(size_type bucket = 0; bucket < old_n; ++bucket){
node *first = buckets[bucket];
while(first){
size_type new_bucket = bkt_num(first->val, n);
buckets[bucket] = first->next;
first->next = tmp[new_bucket];
tmp[new_bucket] = first;
first = buckets[bucket];
}
}
buckets.swap(tmp);
}
}
}
template <class V, class K, class HF, class Ex, class Eq, class A>
pair<typename hashtable<V, K, HF, Ex, Eq, A>::iterator, bool>
hashtable<V, K, HF, Ex, Eq, A>::insert_unique_noresize(const value_type& obj)
{
const size_type n = bkt_num(obj);
node* first = buckets[n];
for (node* cur = first; cur; cur = cur->next)
if (equals(get_key(cur->val), get_key(obj)))
return pair<iterator, bool>(iterator(cur, this), false);
node* tmp = new_node(obj);
tmp->next = first;
buckets[n] = tmp;
++num_elements;
return pair<iterator, bool>(iterator(tmp, this), true);
}
};
my hashtable
#include <bits/stdc++.h>
using namespace std;
template<class Value>
struct hashtable_node {
Value val;
hashtable_node *next;
hashtable_node(Value val, hashtable_node *next):val(val), next(next){}
};
template<class Key>
struct hashtable_iterator {
typedef hashtable_node<Key> node;
node *cur;
};
/***********************************************************************************************************/
template<class Key, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>>
struct hashtable{
typedef hashtable_node<Key> node;
Hash hash;
KeyEqual equals;
vector<node*> buckets;
int num_elements;
hashtable(int n = *prime_list){
num_elements = 0;
int n_buckets = next_size(n);
buckets.resize(n_buckets);
}
~hashtable(){
for(auto cur: buckets) {
while(cur != NULL) {
node *tmp = cur->next;
delete cur;
cur = tmp;
}
}
}
node* find(const Key& obj) {
int n = hash(obj)%buckets.size();
node *cur = buckets[n];
while(cur) {
if (equals(cur->val, obj))
return cur;
cur = cur->next;
}
return cur;
}
pair<node*, bool> insert(const Key& obj, bool same = false) {
resize(num_elements + 1);
const int n = hash(obj)%buckets.size();
node* first = buckets[n], *cur = first;
while(cur) {
if (equals(cur->val, obj)) {
if(same) {
node* tmp = new node(obj, cur->next);
*tmp = node{obj, cur->next};
cur->next = tmp;
++num_elements;
return {tmp, true};
}
return {cur, false};
}
cur = cur->next;
}
node* tmp = new node(obj, first);
buckets[n] = tmp;
++num_elements;
return {tmp, true};
}
bool erase(const Key& obj, bool same = false) {
node* cur = find(obj);
if(cur == NULL) return false;
while(cur && equals(cur->val, obj)) {
node *tmp = cur->next;
delete cur;
cur = tmp;
--num_elements;
if(!same) break ;
}
return true;
}
private:
static constexpr int _num_prime = 22;
static constexpr int prime_list[_num_prime] = {
53, 97, 193, 389, 769,
1543, 3079, 6151, 12289, 24593,
49157, 98317, 196613, 393241, 786433,
1572869, 3145739, 6291469, 12582917, 25165843,
50331653, 100663319
};
int next_size(int n) {
const int *last = prime_list+_num_prime;
const int *pos = lower_bound(prime_list, last, n);
return pos == last? *(last-1) : *pos;
}
void resize(int num) {
int old_n = buckets.size();
if(num > old_n){
int n = next_size(num);
if(n > old_n){
vector<node*> tmp(n, NULL);
for(int bucket = 0; bucket < old_n; ++bucket){
node *first = buckets[bucket];
while(first){
int new_bucket = hash(first->val)%n;
buckets[bucket] = first->next;
first->next = tmp[new_bucket];
tmp[new_bucket] = first;
first = buckets[bucket];
}
}
buckets.swap(tmp);
}
}
}
};
int main() {
hashtable<int> H;
H.insert(3);
printf("%d\n", H.erase(5));
printf("%d\n", H.erase(3));
//H.insert(5, 0);
return 0;
}
B tree
参考图: https://www.cnblogs.com/vianzhang/p/7922426.html
B-tree
B-tree中,一个节点的大小通常相当于一个完整的磁盘页。每次读一个节点相当于读一个磁盘页。
最小度数t, 任意节点关键字数为[t-1, 2t-1]
性质:
每个节点有以下域:
n[x]: 当前x节点的关键字数
n[x]个关键字本身
leaf[x]:bool值,表示是否是叶节点
n[x]+1个指针, 指向其子节点
叶节点深度相同
每个非根节点至少包含t-1个关键字, 至多包含2t-1个关键字
插入:
自顶向下裂变, 沿途每遇到一个包含2t-1个关键字的节点, 将其中间节点往上提, 剩下2t-2个关键字裂变成2个节点。
(此操作保证了裂变的时候, 父节点的关键字数不是满的, 每次裂变完所有叶子节点依然在同一个深度。自底向上的话, 则不能保证。)
删除:
较复杂
B+-tree
与B-tree的不同:
非叶节点只存储键值信息和指针
所有叶节点之间有指针
数据记录都存放在叶子节点
优点:
1. 一个块中可容纳更多的索引项,一是可以降低树的高度。二是一个内部节点可以定位更多的叶子节点
2.叶子节点之间通过指针来连接,范围扫描将十分简单
缺点:
任意数据都需要搜索到叶节点才能找到
https://www.cnblogs.com/hzy1991/p/8567334.html
诸神对凡人心生艳羡,厌倦天堂。