1. 程式人生 > >STL原始碼剖析之stl_deque的實現(二)

STL原始碼剖析之stl_deque的實現(二)

STL中deque(雙端佇列)是一種非常重要的結構,stack,與queue底層都是藉助deque.

deque(雙端佇列)是一種雙向開口的連續性空間,雙向開口意思是可以在頭尾兩端做元素的插入和刪除操作。deque和vector最大的差異在於deque允許常數時間內對起頭端進行元素的插入或移除操作,二者在於deque沒所謂的容量(capacity)觀念,因為它是動態地以分段連續空間組合而成,隨時可以增加一段新的空間並連結起來。deque採用一塊所謂的map作為主控,這裡所謂的map是一小塊連續的空間,其中每個元素都是指標,指向另一段較大的連續線性空間,稱為緩衝區。緩衝區才是deque的儲存空間主體。SGI STL允許我們指定緩衝區大小,預設值為0表示將使用512 bytes緩衝區。但是在deque在排序的時候需要借住vector,為了最高效率要將deque先完整複製到一個vector身上,將vector排序後再複製回deque.預設map_size開始大小為8個.

下面的程式碼從stl_deque中摘取,deque僅僅實現了構造物件,與插入數值。

deque無型別檔案,引用所需要的檔案

#ifndef _DEQUE_
#define _DEQUE_

#include"stl_construct.h"
#include"stl_iterator.h"
#include"type_traits.h"
#include"stl_uninitialized.h"
#include"stl_alloc.h"
#include"stl_deque.h"

#endif

stl_construct.h 構造的實現

#ifndef _STL_CONSTRUCT_H
#define _STL_CONSTRUCT_H

#include"type_traits.h"
#include<new.h>

template <class T>
inline void destroy(T* pointer) 
{
    pointer->~T();
}

template <class T1, class T2>
inline void construct(T1* p, const T2& value) 
{
	new (p) T1(value);
}

template <class ForwardIterator>
inline void
__destroy_aux(ForwardIterator first, ForwardIterator last, __false_type)
{
	for ( ; first < last; ++first)
		destroy(&*first);
}

template <class ForwardIterator> 
inline void __destroy_aux(ForwardIterator, ForwardIterator, __true_type) 
{}

template <class ForwardIterator, class T>
inline void __destroy(ForwardIterator first, ForwardIterator last, T*)
{
	typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor;
	__destroy_aux(first, last, trivial_destructor());
}

template <class ForwardIterator>
inline void destroy(ForwardIterator first, ForwardIterator last) 
{
	__destroy(first, last, value_type(first));
}

#endif

stl_iterator.h 迭代器

#ifndef _STL_ITERATOR_H
#define _STL_ITERATOR_H

template <class T>
inline T* value_type(const T*)
{
	return (T*)(0); 
}

template <class T>
inline size_t* distance_type(const T*)
{
	return (size_t*)(0);
}

struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};

template <class T>
inline random_access_iterator_tag iterator_category(const T*) 
{
	return random_access_iterator_tag();
}

#endif

type_traits.h 萃取機制

#ifndef _TYPE_TRAITS_H
#define _TYPE_TRAITS_H


struct __true_type
{};
struct __false_type
{};

template <class type>
struct __type_traits 
{ 
   typedef __true_type     this_dummy_member_must_be_first;
   typedef __false_type    has_trivial_default_constructor;
   typedef __false_type    has_trivial_copy_constructor;
   typedef __false_type    has_trivial_assignment_operator;
   typedef __false_type    has_trivial_destructor;
   typedef __false_type    is_POD_type;
};

struct __type_traits<int> 
{ 
   typedef __true_type     this_dummy_member_must_be_first;
   typedef __true_type    has_trivial_default_constructor;
   typedef __true_type    has_trivial_copy_constructor;
   typedef __true_type    has_trivial_assignment_operator;
   typedef __true_type    has_trivial_destructor;
   typedef __true_type    is_POD_type;
};

#endif

stl_uninitialized.h 未初始化的引數

#ifndef _STL_UNINITIALIZED_H
#define _STL_UNINITIALIZED_H

#include<typeinfo.h>
#include"stl_algobase.h"

template<class ForwardIterator, class Size, class T>
ForwardIterator __uninitialized_fill_n_aux(ForwardIterator first, Size n, const T &x, __true_type)
{
	return fill_n(first, n, x);
}

template<class ForwardIterator, class Size, class T>
ForwardIterator __uninitialized_fill_n_aux(ForwardIterator first, Size n, const T &x, __false_type)
{
	ForwardIterator cur = first;
	for(; n>0; --n, ++cur)
		construct(&*cur, x);
	return cur;
}

template<class ForwardIterator, class Size, class T, class T1>
ForwardIterator __uninitialized_fill_n(ForwardIterator first, Size n, const T &x, T1*)
{
	cout<<"T1 = "<<typeid(T1).name()<<endl;
	typedef typename __type_traits<T1>::is_POD_type is_POD;
	return __uninitialized_fill_n_aux(first, n, x, is_POD());
}


template<class ForwardIterator, class Size, class T>
ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T &x)
{
	return __uninitialized_fill_n(first, n, x, value_type(first));
}

///////////////////////////////////////////////////////////////////////////////

template <class InputIterator, class ForwardIterator>
inline ForwardIterator __uninitialized_copy_aux(InputIterator first, 
												InputIterator last,
												ForwardIterator result,
												__true_type)
{
	return copy(first, last, result);
}

template <class InputIterator, class ForwardIterator>
ForwardIterator __uninitialized_copy_aux(InputIterator first, 
										 InputIterator last,
										 ForwardIterator result,
										 __false_type) 
{
	ForwardIterator cur = result;
    for ( ; first != last; ++first, ++cur)
		construct(&*cur, *first);
    return cur;
}

template <class InputIterator, class ForwardIterator, class T>
inline ForwardIterator __uninitialized_copy(InputIterator first,
											InputIterator last,
											ForwardIterator result, T*) 
{
	typedef typename __type_traits<T>::is_POD_type is_POD;
	return __uninitialized_copy_aux(first, last, result, is_POD());
}

template <class InputIterator, class ForwardIterator>
inline ForwardIterator uninitialized_copy(InputIterator first, 
										  InputIterator last,
										  ForwardIterator result) 
{
	return __uninitialized_copy(first, last, result, value_type(result));
}


#endif

stl_alloc.h 空間配置器

#ifndef _STL_ALLOC_H
#define _STL_ALLOC_H

#if 0
#include<new>
#define __THROW_BAD_ALLOC throw bad_alloc
#else
#include<iostream.h>
#include<malloc.h>
#include<stdlib.h>
#define __THROW_BAD_ALLOC cerr<<"Out Of Memory."<<endl;exit(1)
#endif

//malloc  free

template<int inst>
class __malloc_alloc_template
{
private:
	static void* oom_malloc(size_t n)
	{
		void (*my_malloc_handler)();
		void *result;
		for(;;)
		{
			my_malloc_handler = __malloc_alloc_oom_handler;
			if(0 == my_malloc_handler)
			{
				__THROW_BAD_ALLOC;
			}
			(*my_malloc_handler)();
			result = malloc(n);
			if(result)
				return result;
		}
	}
	static void* oom_realloc(void *p, size_t n)
	{
		void (* my_malloc_handler)();
		void *result;
		for (;;) 
		{
			my_malloc_handler = __malloc_alloc_oom_handler;
			if (0 == my_malloc_handler) 
			{
				__THROW_BAD_ALLOC; 
			}
			(*my_malloc_handler)();
			result = realloc(p, n);
			if (result) 
				return(result);
		}
	}
	static void(*__malloc_alloc_oom_handler)();
public:
	static void* allocate(size_t n)
	{
		void *result = malloc(n);
		if(0 == result)
			result = oom_malloc(n);
		return result;
	}
	static void  deallocate(void *p, size_t n)
	{
		free(p);
	}
	static void* reallocate(void *p, size_t old_sz, size_t new_sz)
	{
		void *result = realloc(p, new_sz);
		if(0 == result)
			result = oom_realloc(p, new_sz);
		return result;
	}
public:
	//set_new_handler  模擬
	static void(*set_malloc_handler(void(*f)()))()
	{
		void(*old)() = __malloc_alloc_oom_handler;
		__malloc_alloc_oom_handler = f;
		return old;
	}
};

void(* __malloc_alloc_template<0>::__malloc_alloc_oom_handler)() = 0;

typedef __malloc_alloc_template<0> malloc_alloc;
/////////////////////////////////////////////////////////////////////////////////

enum {__ALIGN = 8};
enum {__MAX_BYTES = 128};
enum {__NFREELISTS = __MAX_BYTES / __ALIGN};

template<bool threads, int inst>
class __default_alloc_template
{
public:
	static void * allocate(size_t n);
	static void   deallocate(void *p, size_t n);
	static void * reallocate(void *p, size_t old_sz, size_t new_sz);
protected:
	static void * refill(size_t n);
	static char* chunk_alloc(size_t size, int &nobjs);
private:
	static size_t ROUND_UP(size_t bytes)
	{
		return ((bytes + __ALIGN-1) &~(__ALIGN-1));
	}
private:
	union obj
	{
		union obj * free_list_link;
		char client_data[1];
	};
private:
	static size_t  FREELIST_INDEX(size_t bytes)
	{
		return ((bytes + __ALIGN-1) / __ALIGN-1);
	}
	static obj* free_list[__NFREELISTS];
private:
	static char * start_free;
	static char * end_free;
	static size_t heap_size;
};

template<bool threads, int inst>
char* __default_alloc_template<threads, inst>::start_free = 0;
template<bool threads, int inst>
char* __default_alloc_template<threads, inst>::end_free = 0;
template<bool threads, int inst>
size_t __default_alloc_template<threads, inst>::heap_size = 0;

template<bool threads, int inst>
__default_alloc_template<threads, inst>::obj*
__default_alloc_template<threads, inst>::free_list[__NFREELISTS] = 
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

template<bool threads, int inst>
void * __default_alloc_template<threads, inst>::allocate(size_t n)
{
	obj ** my_free_list;
	obj * result;
	if(n > __MAX_BYTES)
		return malloc_alloc::allocate(n);

	my_free_list = free_list + FREELIST_INDEX(n);
	result = *my_free_list;
	if(result == 0)
	{
		void *r = refill(ROUND_UP(n));
		return r;
	}
	*my_free_list = result->free_list_link;
	return result;
}

template <bool threads, int inst>
char*
__default_alloc_template<threads, inst>::chunk_alloc(size_t size, int& nobjs)
{
    char * result;
    size_t total_bytes = size * nobjs;
    size_t bytes_left = end_free - start_free;
	
    if (bytes_left >= total_bytes) 
	{
        result = start_free;
        start_free += total_bytes;
        return(result);
    } 
	else if (bytes_left >= size) 
	{
        nobjs = bytes_left/size;
        total_bytes = size * nobjs;
        result = start_free;
        start_free += total_bytes;
        return(result);
    } 
	else 
	{
        size_t bytes_to_get = 2 * total_bytes + ROUND_UP(heap_size >> 4);
        if (bytes_left > 0) 
		{
            obj ** my_free_list = free_list + FREELIST_INDEX(bytes_left);
            ((obj *)start_free) -> free_list_link = *my_free_list;
            *my_free_list = (obj *)start_free;
        }
        start_free = (char *)malloc(bytes_to_get);
        if (0 == start_free) 
		{
            int i;
            obj ** my_free_list, *p;
            for (i = size; i <= __MAX_BYTES; i += __ALIGN) 
			{
                my_free_list = free_list + FREELIST_INDEX(i);
                p = *my_free_list;
                if (0 != p) 
				{
                    *my_free_list = p -> free_list_link;
                    start_free = (char *)p;
                    end_free = start_free + i;
                    return(chunk_alloc(size, nobjs));
                }
            }
			end_free = 0;
            start_free = (char *)malloc_alloc::allocate(bytes_to_get);
        }
        heap_size += bytes_to_get;
        end_free = start_free + bytes_to_get;
        return(chunk_alloc(size, nobjs));
    }
}

template <bool threads, int inst>
void* __default_alloc_template<threads, inst>::refill(size_t n)
{
    int nobjs = 20;
    char * chunk = chunk_alloc(n, nobjs);
    obj ** my_free_list;
    obj * result;
    obj * current_obj, * next_obj;
    int i;
	
    if (1 == nobjs) return(chunk);
    my_free_list = free_list + FREELIST_INDEX(n);
	
	result = (obj *)chunk;
	*my_free_list = next_obj = (obj *)(chunk + n);
	for (i = 1; ; i++) 
	{
        current_obj = next_obj;
        next_obj = (obj *)((char *)next_obj + n);
        if (nobjs - 1 == i) 
		{
            current_obj -> free_list_link = 0;
            break;
        } 
		else 
		{
            current_obj -> free_list_link = next_obj;
        }
	}
    return(result);
}

template <bool threads, int inst>
void*
__default_alloc_template<threads, inst>::reallocate(void *p,
													size_t old_sz,
                                                    size_t new_sz)
{
    void * result;
    size_t copy_sz;
	
    if (old_sz > (size_t) __MAX_BYTES && new_sz > (size_t) __MAX_BYTES) 
	{
        return(realloc(p, new_sz));
    }
    if (ROUND_UP(old_sz) == ROUND_UP(new_sz))
		return(p);
    result = allocate(new_sz);
    copy_sz = new_sz > old_sz? old_sz : new_sz;
    memcpy(result, p, copy_sz);
    deallocate(p, old_sz);
    return(result);
}


template <bool threads, int inst>
void __default_alloc_template<threads, inst>::deallocate(void *p, size_t n)
{
    obj *q = (obj *)p;
    obj ** my_free_list;
    if (n > (size_t) __MAX_BYTES) 
	{
        malloc_alloc::deallocate(p, n);
        return;
    }
    my_free_list = free_list + FREELIST_INDEX(n);
    q -> free_list_link = *my_free_list;
    *my_free_list = q;
}

/////////////////////////////////////////////////////////////////

#ifdef __USE_MALLOC
typedef __malloc_alloc_template<0> malloc_alloc;
typedef malloc_alloc alloc;
#else
typedef __default_alloc_template<0,0> alloc;
#endif

template<class T, class Alloc>
class simple_alloc
{
public:
	static T * allocate(size_t n)
	{
		return 0==n ? 0 : (T*)Alloc::allocate(n * sizeof(T));
	}
	static T * allocate(void)
	{
		return (T*)Alloc::allocate(sizeof(T));
	}
	static void deallocate(T *p, size_t n)
	{
		if(0!=n)
			Alloc::deallocate(p, n*sizeof(T));
	}
	static void deallocate(T *p)
	{
		Alloc::deallocate(p,sizeof(T));
	}
};
#endif




stl_deque.h 雙端佇列的實現

#ifndef _STL_DEQUE_H
#define _STL_DEQUE_H

template<class T>
T max(T &a, T &b)
{
	return a > b ? a : b;
}

size_t __deque_buf_size(size_t n, size_t sz)
{
	return n!=0 ? n : (sz<512 ? size_t(512/sz) : size_t(1));
}

template<class T, class Ref, class Ptr, size_t BufSiz>
struct __deque_iterator
{
	typedef __deque_iterator<T, T&, T*, BufSiz>   iterator;
	typedef T value_type;
	typedef Ptr pointer;
	typedef Ref reference;
	typedef size_t size_type;
	typedef size_t difference_type;
	typedef T** map_pointer;

	typedef __deque_iterator  self;

	static size_t buffer_size()
	{
		return __deque_buf_size(BufSiz, sizeof(T));
	}

	T *cur;
	T *first;
	T *last;
	map_pointer  node; //T**node

	/////////////////////////////////////////////////////////
	__deque_iterator() : cur(0), first(0), last(0), node(0) 
	{}
	void set_node(map_pointer new_node) 
	{
		node = new_node;
		first = *new_node;
		last = first + difference_type(buffer_size());
	}
	bool operator==(const self& x) const { return cur == x.cur; }
    bool operator!=(const self& x) const { return !(*this == x); }
	reference operator*() const { return *cur; }
	self& operator++() 
	{
		++cur;
		if (cur == last) 
		{
			set_node(node + 1);
			cur = first;
		}
		return *this; 
  }
};

template<class T, class Alloc=alloc, size_t BufSiz=0>
class deque
{
public:
	typedef T value_type;
	typedef size_t size_type;
	typedef value_type* pointer;

	typedef __deque_iterator<T, T&, T*, BufSiz> iterator;
public:
	deque() : start(), finish(), map(0), map_size(0)
	{
		create_map_and_nodes(0);
	}
public:
	iterator begin()
	{
		return start;
	}
	iterator end()
	{
		return finish;
	}
public:
	void push_back(const value_type& t) 
	{
		if (finish.cur != finish.last - 1) 
		{
			construct(finish.cur, t);
			++finish.cur;
		}
		else
			push_back_aux(t);
	}
	
	void push_front(const value_type& t) 
	{
		if (start.cur != start.first) 
		{
			construct(start.cur - 1, t);
			--start.cur;
		}
		else
			push_front_aux(t);
	}
protected:
	void push_back_aux(const value_type& t);
	void push_front_aux(const value_type& t);
	void reserve_map_at_back (size_type nodes_to_add = 1)
	{
		if (nodes_to_add + 1 > map_size - (finish.node - map))
			reallocate_map(nodes_to_add, false);
	}
	void reserve_map_at_front (size_type nodes_to_add = 1) 
	{
		if (nodes_to_add > start.node - map)
			reallocate_map(nodes_to_add, true);
	}
	void reallocate_map(size_type nodes_to_add, bool add_at_front);
protected:
	void create_map_and_nodes(size_type n);
	static size_type initial_map_size() 
	{
		return 8; 
	}
	static size_type buffer_size() 
	{
		return __deque_buf_size(BufSiz, sizeof(value_type));
	}
	pointer allocate_node() 
	{
		return data_allocator::allocate(buffer_size()); 
	}
protected:
	typedef pointer* map_pointer;
	typedef simple_alloc<value_type, Alloc> data_allocator;
	typedef simple_alloc<pointer, Alloc>    map_allocator;
protected:
	iterator start;
	iterator finish;
	map_pointer map;
	size_type map_size;
};

template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::create_map_and_nodes(size_type num_elements)
{
	size_type num_nodes = num_elements / buffer_size() + 1;
	
	//map_size = max(initial_map_size(), num_nodes + 2);
	map_size = initial_map_size() > (num_nodes + 2) ? initial_map_size() : (num_nodes + 2);
	map = map_allocator::allocate(map_size);
	
	map_pointer nstart = map + (map_size - num_nodes) / 2;
	map_pointer nfinish = nstart + num_nodes - 1;
    
	map_pointer cur;
	
    for (cur = nstart; cur <= nfinish; ++cur)
		*cur = allocate_node();
	
	start.set_node(nstart);
	finish.set_node(nfinish);
	start.cur = start.first;
	finish.cur = finish.first + num_elements % buffer_size();
}

template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::push_back_aux(const value_type& t) 
{
	value_type t_copy = t;
	reserve_map_at_back();
	*(finish.node + 1) = allocate_node();
	
    construct(finish.cur, t_copy);
    finish.set_node(finish.node + 1);
    finish.cur = finish.first;
}

template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::push_front_aux(const value_type& t) 
{
	value_type t_copy = t;
	reserve_map_at_front();
	*(start.node - 1) = allocate_node();
	
    start.set_node(start.node - 1);
    start.cur = start.last - 1;
    construct(start.cur, t_copy);
} 

template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::reallocate_map(size_type nodes_to_add,
                                              bool add_at_front) 
{
	size_type old_num_nodes = finish.node - start.node + 1;
	size_type new_num_nodes = old_num_nodes + nodes_to_add;
	
	map_pointer new_nstart;
	if (map_size > 2 * new_num_nodes) 
	{
		new_nstart = map + (map_size - new_num_nodes) / 2 
			+ (add_at_front ? nodes_to_add : 0);
		if (new_nstart < start.node)
			copy(start.node, finish.node + 1, new_nstart);
		else
			copy_backward(start.node, finish.node + 1, new_nstart + old_num_nodes);
	}
	else 
	{
		size_type new_map_size = map_size + max(map_size, nodes_to_add) + 2;
		
		map_pointer new_map = map_allocator::allocate(new_map_size);
		new_nstart = new_map + (new_map_size - new_num_nodes) / 2
			+ (add_at_front ? nodes_to_add : 0);
		copy(start.node, finish.node + 1, new_nstart);
		map_allocator::deallocate(map, map_size);
		
		map = new_map;
		map_size = new_map_size;
	}
	
	start.set_node(new_nstart);
	finish.set_node(new_nstart + old_num_nodes - 1);
}


#endif

測試主函式main.cpp

void main()
{
	deque<int> de;
	de.push_back(1);
	de.push_back(2);
	de.push_front(3);
	de.push_front(4);  //4 3 1 2

	deque<int>::iterator it = de.begin();
	while(it != de.end())
	{
		cout<<*it<<" ";
		++it;
	}
	cout<<endl;

}

參考文獻:《STL原始碼剖析》

相關推薦

STL原始碼剖析stl_deque實現

STL中deque(雙端佇列)是一種非常重要的結構,stack,與queue底層都是藉助deque. deque(雙端佇列)是一種雙向開口的連續性空間,雙向開口意思是可以在頭尾兩端做元素的插入和刪除操作。deque和vector最大的差異在於deque允許常數時間內對起頭端

mybatis原始碼解析Configuration載入

概述 上一篇我們講了configuation.xml中幾個標籤的解析,例如<properties>,<typeAlises>,<settings>等,今天我們來介紹剩下的兩個比較重要的標籤之一,<environments>,這個標籤主要用於我們訪問資料庫的配置

elasticsearch原始碼分析啟動過程

最近開始廣泛的使用elasticsearch,也開始寫一些java程式碼了,為了提高java程式碼能力,也為了更加深入一點了解elasticsearch的內部運作機制,所以開始看一些elasticsearch的原始碼了。對於這種廣受追捧的開源專案,細細品讀一定會受益匪淺,

Java併發包原始碼學習AQS框架CLH lock queue和自旋鎖

上一篇文章提到AQS是基於CLH lock queue,那麼什麼是CLH lock queue,說複雜很複雜說簡單也簡單, 所謂大道至簡: CLH lock queue其實就是一個FIFO的佇列,佇列中的每個結點(執行緒)只要等待其前繼釋放鎖就可以了。 AbstractQueuedSynchronizer

雲客Drupal8原始碼分析實體Entity配置實體基類

配置實體基類是系統定義的一個用於配置實體的抽象基類,繼承自實體基類,完成了配置實體的大部分通用功能,具體的配置實體往往會繼承它,比如使用者角色實體,這樣寫少量程式碼即可,類定義如下: Drupal\Core\Config\Entity\ConfigEntityBase 實

Android4.4.2原始碼分析WiFi模組

接著上一篇繼續對WiFi原始碼的分析 onResume方法中 6>,首先是呼叫WiFiEnabler的resume方法對switch進行管理 接下來註冊廣播 getActivity().registerReceiver(mReceiver, mFilter);

spring原始碼解析IOC容器------載入和註冊

  上一篇跟蹤了IOC容器對配置檔案的定位,現在我們繼續跟蹤程式碼,看看IOC容器是怎麼載入和註冊配置檔案中的資訊的。開始之前,首先我們先來了解一下IOC容器所使用的資料結構-------BeanDefinition,它是一個上層介面,有很多實現類,分別對應不同的資料載體。我們平時開發的時候,也會定義很多po

Spring原始碼解析基礎應用

方法注入 在spring容器中,大部分bean的作用域(scope)是單例(singleton)的,少部分bean的作用域是原型(prototype),如果一個bean的作用域是原型,我們A bean的作用域是原型,B bean中以@Autowired的方式注入A,那麼B在A中依舊是單例。我們可以讓B類實現A

原始碼剖析】tornado-memcached-sessions —— Tornado session 支援的實現

     客官您終於回頭了!讓我們本著探(zuo)索(si)精神把 session.py 看完吧...       首先看看需要的庫:       pickle 一個用於序列化反序列化的庫(聽

C++STL中sort函式的內部實現

另外一個版本: 概述 先進行introsort,基本有序後再使用insertion sort。introsort是改進的quick sort,為了防止最壞情況發生,它使用__lg()函式控制分割惡化的情況。 intro sort演算法 元素個數

併發程式設計—— Java 執行緒池 實現原理與原始碼深度解析 submit方法

在上一篇《併發程式設計(十一)—— Java 執行緒池 實現原理與原始碼深度解析(一)》中提到了執行緒池ThreadPoolExecutor的原理以及它的execute方法。這篇文章是接著上一篇文章寫的,如果你沒有閱讀上一篇文章,建議你去讀讀。本文解析ThreadPoolExecutor#submit。  

Spring原始碼分析IOC的三種常見用法及原始碼實現

Spring原始碼分析之IOC的三種常見用法及原始碼實現(二) 回顧上文 我們研究的是 AnnotationConfigApplicationContext annotationConfigApplication = new AnnotationConfigApplicationContext

STL原始碼剖析——stack的實現原理和使用方法詳解

Stack 簡介     stack 是堆疊容器,是一種“先進後出”的容器。     stack 是簡單地裝飾 deque 容器而成為另外一種容器。     使用 stack 時需要加上標頭檔案 #include<s

STL原始碼剖析——deque的實現原理和使用方法詳解

Deque 簡介     deque是“double—ended queue”的縮寫,和vector一樣都是STL的容器,deque 是雙端陣列,而 vector 是單端的。     deque 在介面上和 vector 非常相似,在許多操作的地方

spring-boot-admin原始碼分析及單機監控spring-boot-monitor的實現

SpringBootMonitor spring-boot-admin原始碼分析及單機監控spring-boot-monitor的實現(一) spring-boot-admin原始碼分析及單機監控spring-boot-monitor的實現(二)

嵌入式核心及驅動開發學習筆記 實現應用控制驅動

Linux系統根據驅動程式實現的模型框架將裝置驅動分成字元裝置驅動、塊裝置驅動、網路裝置驅動三大類。這裡簡單理解一下概念 字元裝置:裝置按位元組流處理資料,通常用的串列埠裝置、鍵盤裝置都是這種。 塊裝置:裝置按塊單位對資料處理,通常是儲存裝置。 網路裝置:顧名思義,建立在soc

STL原始碼剖析map和set

之前分析二叉搜尋樹和平衡二叉樹時,真心感覺樹的實現真是難,特別是平衡二叉樹,不平衡之後需要調整,還要考慮各種情況,累感不愛.今天看到這個紅黑樹,發現比平衡二叉樹還難,但是紅黑樹比平衡二叉樹使用的場景更多,所以平常使用時,我們需要了解紅黑樹的實現原理,如果有能力,可以自己實現,但是如果實在做不出來,也

Android底部導航欄實現RadioGroup

這裡簡單記錄一下Android底部導航欄通過RadioGroup+Fragment的實現。 這裡寫圖片描述 佈局: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:and

Html靜態網頁的實現——傻瓜式教程

上次說到Html5中無法換行的問題 <body> <p>把文字輸入到這裡</p> <p>把文字輸入到這裡</p> </body> 看看執行結果 這下是不是就換行了   格式:<p a

以太坊原始碼分析 P2P網路、節點發現流程

區塊鏈特輯 :https://blog.csdn.net/fusan2004/article/details/80879343,歡迎查閱,原創作品,轉載請標明!上一篇文章簡單介紹了下一些基礎的型別定義,從這一篇開始我們將描述p2p網路的更多細節。從關於節點的定義來看,其實不同