/images/art2.png

Bit operation in C++

Bit operator

operatorfunctionexample
«left shift0001 –> 0010
»right shift0010 –> 0001
&and (bit by bit)1100 & 1010 = 1000
|or (bit by bit)1010 | 0101 = 1111
~reverse~0000 = 1111
^XOR0110 ^ 1100 = 1010

Operator: &

x is a bit

x & 1 = x

x & 0 = 0

Usually use & as a filter. Suppose we have a number is X, X & 0011 will get the last two bits of X.

RB tree

2-3 tree & 2-4 tree

2-node: 1 key and 2 children 3-node: 2 keys and 3 children 4-node: 3 keys and 4 children

A (2,4) tree (also called 2-4 tree or 2-3-4 tree) is a multi-way search with the following properties:

  • Node-Size Property: every internal node has at most four children
  • Depth Property: all the external nodes have the same depth

insertion

/images/2019-8-17-RB-tree/2-4-insertion.png

Operator overwrite in c++

Example

increment and decrement operator

#include <iostream>
using namespace std;

class INT
{
private:
    int m_i;
public:
    INT(int i):m_i(i){};

    friend bool operator==(INT& test1, INT& test2){
        return test1.m_i == test2.m_i;
    }

    friend bool operator!=(INT& test1, INT& test2){
        return test1.m_i != test2.m_i;
    }

    friend INT operator+(INT& test1, INT& test2){
        int temp = test1.m_i + test2.m_i;
        INT res(temp);
        return res;
    }

    INT& operator=(INT& test){
        this->m_i = test.m_i;
        return *this;
    }

    int& operator*() const{
        return (int&)this->m_i;
    }
    // int a() const {}; This means a() cannot change any member in class.

    INT& operator++(){ //prefix. ++test;
        this->m_i += 1;
        return *this;
    }
    // Why prefix is not const. Because it always return original class and actually it support ++++test.

    const INT operator++(int){ //postfix. test++;
        INT temp = *this;
        // ++(*this);
        this->m_i += 1;
        return temp;
    }
    // Postfix must be const. Because it return a temporary variable and it not support test++++.
    // You can try int i = 1; i++++;
    // This is invalid.

    friend ostream& operator<<(ostream& s, const INT& i){
        s << '[' << i.m_i << ']';
        return s;
    }

};

int main(int argc, char const *argv[])
{
    INT test(1);
    INT test1(10);
    INT test2(3);
    cout << ++test << endl; //[2]
    cout << test++ << endl; //[2]
    cout << test << endl; //[3]
    cout << *test << endl; //3
    cout << (test + test2) << endl; //[6]
    cout << boolalpha << (test == test2) << endl; //true
    test = test1;
    cout << test << endl; //[10]
    return 0;
}

Second Example

convert operator

Container in c++

Classification

  • Sequence container
  • Associative container
    • RB-tree (not public)
    • set
    • map
    • multiset
    • multemap
    • hashtable (not standard)
    • hash_set (not standard)
    • hash_map (not standard)
    • hash_multimap (not standard)
    • hash_multiset (not standard)

Associative container have a key-value pair. It do not have back and front so they never have push_back, pop_back.

Vector

This is similar with grow array. Vector use sequential space.

explicit and implicit in c++

explicit and implicit

In C++, constructor can be explicit and implicit.

The reserve word explicit affect constructor with only one parameter or only one parameter without given initial value.

#include <iostream>
using namespace std;

class test1
{
    int data;
public:
    test1(int t = 0):data(t){};
    ~test1(){};

    test1 operator + (const test1 &a) const{
        return test1(data + a.data);
    }

    test1& operator = (const test1 &a)
    {
        this->data = a.data;
        return *this;
    }

    int getData(){return data;};
};

class test2
{
    int data;
public:
    // explicit test2(int t):data(t){};
    explicit test2(int t, int a = 0):data(t){};
    ~test2(){};

    int getData(){return data;};
};

int main(int argc, char const *argv[])
{
    test1 t1(1); //explicit constructor
    cout << t1.getData() << endl; // 1

    test1 t2 = 1; //implicit constructor
    cout << t2.getData() << endl; // 1

    test1 t3 = 'a'; //implicit convert integer into char and call implicit constructor
    cout << t3.getData() << endl; // 97

    test1 t4;
    t4 = t2 + 3; // + operation will take 3 and call implicit constructor

    t4 = 3 + t2; // ERROR! + operater belongs the integer and it doesn't know how to convert t2

    test2 t5('a');// explicit constructor is OK
    cout << t5.getData() << endl; // 97

    test2 t6 = 'a'; //error. Must be explicit.
    return 0;
}

t1(1) -> explicit t1 = 1 -> implicit

Iterator in c++

Iterator 设计思维

STL 中 container 和 algorithm 是相对独立的,本身设计也是泛型化的。Iterator 就是用来将这两者联系在一起的。

Iterator 是一种 smart pointer

可以不用 delete

Iterator 属性

iterator_traits 是用来抽取 iterator 中的类型(特指 value type)的。

这是 iterator 中常见的五种属性。

template <class I>
struct iterator_traits
{
    typedef typename I::iterator_category iterator_category; //category
    typedef typename I::value_type value_type; // type
    typedef typename I::difference_type difference_type; //
    typedef typename I::pointer pointer; // T*
    typedef typename I::reference reference; // T&
};
#include <iostream>     // std::cout
#include <iterator>     // std::iterator_traits
#include <typeinfo>     // typeid
using namespace std;

int main() {
  typedef std::iterator_traits<double*> traits;
  cout << typeid(traits::iterator_category).name() << endl;
  cout << typeid(traits::value_type).name() << endl;
  cout << typeid(traits::difference_type).name() << endl;
  cout << typeid(traits::pointer).name() << endl;
  cout << typeid(traits::reference).name() << endl;
  return 0;
}
NSt3__126random_access_iterator_tagE
d
l
Pd
d
yanghaoli

iterator_category

  1. Input iterator: Read only. Cannot be change.
  2. Output iterator: Write only.
  3. Forward iterator: Allow write and only one direction.(only operator++). Some algorithms use one direction enough.(like replace())
  4. Bidirectional iterator: For some algorithm will move both direction. Support operator++ and operator–.
  5. Random access iterator: Support more operator. p+n, p-n, p[n], p1-p2, p1 < p2.

iterator & const_iterator

const_iterator is read only.

Allocator in c++

Allocator is for memory

配置内存空间 -> 构建(constructor) -> 解构(destructor) -> 释放内存空间

construct() and destroy()

用于建构和解构

Memory allocate and release

双层配置器。第一级是区块大于 128 bytes 的,使用 malloc()和 free()。第二级是区块小于 128 bytes 的,使用 memory pool 和 freelist。

第一級配置器

第一級配置器以 malloc(), free(), realloc() 等 C 函式執行實際的記憶體配置、釋放、重配置動作,並實作出類似 C++ new-handler7 機制。是的,它不能直接運用 C++ new-handler 機制,因為它並非使用 ::operator new 來配置記 憶體。

所謂 C++ new handler 機制是,你可以要求系統在記憶體配置需求無法被滿足時, 喚起一個你所指定的函式。換句話說一旦 ::operator new 無法達成任務,在丟出 std::bad_alloc 異常狀態之前,會先呼叫由客端指定的處理常式。此處理常式 通常即被稱為 new-handler。new-handler 解決記憶體不足的作法有特定的模式。

注意,SGI 以 malloc 而非 ::operator new 來配置記憶體(我所能夠想像的一 個原因是歷史因素,另一個原因是 C++ 並未提供相應於 realloc() 的記憶體配 置動作),因此 SGI 不能直接使用 C++ 的 set_new_handler(),必須模擬一個 類似的 set_malloc_handler()。

Functor in C++

Basically, Functor have same functionality with interface in java.

Think about this code. You want count all string whose length is less than 5.

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

bool lenLessThanFive(const string& str){
    return str.size() < 5;
}

int main(int argc, char const *argv[])
{
    string ia[5] = {"a", "aa", "aaa", "aaaa", "aaaaa"};
    vector<string> iv(ia, ia+5);
    int res = count_if(iv.begin(), iv.end(), lenLessThanFive);
    cout << "res= " << res << endl;
    return 0;
}

lenLessThanFive is a function pointer here. It is work right, but it lack scalability. We cannot change the threshold in the function every time. Meanwhile, Function need to be unary(only one parameter). Therefore, we can consider the Functor.

Common method comparison - c++ & java

Sort

C++

For c++, here is official document

sort()

This method sorts elements in the range [first, last).

Result is in ascending order by deflaut.

Introsort.

// sort algorithm example
#include <iostream>     // std::cout
#include <algorithm>    // std::sort
#include <vector>       // std::vector

bool myfunction (int i,int j) { return (i>j); }

int main () {
  int myints[] = {32,71,12,45,26,80,53,33};
  std::vector<int> myvector (myints, myints+8); // 32 71 12 45 26 80 53 33

  // using default comparison (operator <):
  std::sort (myvector.begin(), myvector.begin()+4); //(12 32 45 71)26 80 53 33

  // using function as comp
  std::sort (myvector.begin(), myvector.end(), myfunction); //80 71 53 45 33 32 26 12

  // print out content:
  std::cout << "myvector contains:";
  for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';
  return 0;
}

On average, linearithmic in the distance between first and last: Performs approximately N*log2N

Container comparison - c++ & java

Container comparison

C++ version is c++11. Java version is java se8.

C++JAVADescription
array / [ ][ ]固定大小的数组
vectorArrayList可变长度的数组
Vector可变长度的数组,支持同步操作,效率比 ArrayList 略差
listLinkedList双链表,便于增删
forward_list单链表,c++没有给他提供 size()的方法
dequeArrayDeque双向队列
stackStack栈,先进后出
queueQueue队,先进先出
priority_queuePriorityQueue支持优先级的队列
setTreeSet集合,数据有序,红黑树
unordered_setHashSet集合,数据无序,hash
mapTreeMapkey-value 映射,key 有序,红黑树
unordered_mapHashMapmap, 无序,hash
multiset集合,允许重复元素
multimapmap,允许重复的 key
unordered_multiset无序允许重复元素集合
unordered_multimap无序允许重复 key 的 map
LinkedHashSet按照插入顺序,支持 hash 查找
LinkedHashMap按照插入顺序,支持 hash 查找
HashTable类似 HashMap,效率略低
bitsetBitSet位操作

HashTable & HashMap

The HashMap class is roughly equivalent to Hashtable, except that it is asynchronized and permits nulls.