STL源碼剖析 list概述

目錄

list的節點(node)

list迭代器

?list 的構造和內存管理

list 的元素操作

  • ?list相較于vector連續的線性空間就顯得很復雜,他的存儲空間是不連續的,好處是每次插入和刪除一個元素的時候,只需要配置或者釋放一個元素的空間

  • 插入和刪除十分的方便

list的節點(node)

  • list 本身和list的節點是不同的結構,需要分開設計
  • list節點結構是一個雙向的鏈表
template <class T>
struct __list_node{typedef void* void_pointer;void_pointer prev;   //指針的類型是void*,其實可以將其設定為 __list_node<T>void_pointer next;   T data;
};

list迭代器

  • list迭代器不能像vector一樣使用普通的指針,因為考慮到內存分配的不連續性,list的迭代器必須有能力指向list的的節點,并正確的進行遞增、遞減、取值(獲取成員節點的數據值)、成員的存取(取用的是節點的成員)等操作
  • 因為list的迭代器具備前移和后移的能力,所以使用Bidirectional iterators
  • list的插入和接合操作(splice)都不會造成原有的list迭代器失效,vector不可以,因為vector插入操作可能造成記憶體的重新配置,會導致原有的迭代器失效
  • list刪除元素(erase)也只有指向被刪除元素的那個迭代器會失效,其余的迭代器不會受到任何的影響

  • ?list迭代器設計如下
//list的迭代器設計
template <class T,class Ref,class Ptr>
struct __list_iterator{typedef __list_iterator<T,T&,T*>    iterator;typedef __list_iterator<T,Ref,Ptr>  self;typedef std::bidirectional_iterator_tag iterator_category;typedef T value_type;typedef Ptr pointer;typedef Ref reference;typedef __list_node<T>* link_type;typedef std::size_t size_type;typedef ptrdiff_t difference_type;link_type node;//迭代器內部需要一個普通的指針,指向list節點//constructor__list_iterator(){}__list_iterator(link_type x):node(x){}__list_iterator(const iterator& x):node(x.node){}bool operator==(const self& x) const{return (node == x.node);}bool operator!=(const self& x) const{return (node != x.node);}//以下對迭代器取值 取得的是節點的數據值reference operator*() const {return (*node).data;}//以下是對迭代器的成員進行存取 (member access) 運算子的標準做法pointer operator->() const {return &(operator*());}//對迭代器進行加一 前進一個節點self& operator++(){node = (link_type)((*node).next);}self operator++(int){self tmp = *this;++*this;return tmp;}//對迭代器進行減一 后退一個節點self& operator--(){node = (link_type)((*node).prev);}self operator--(int){self tmp = *this;--*this;return tmp;}
};

list的數據結構

  • SGI list不僅僅是雙向鏈表 還是一個環狀雙向鏈表,只需要一個指針就可以完成整個鏈表的遍歷
//list的迭代器設計
template <class T,class Ref,class Ptr>
struct __list_iterator{typedef __list_iterator<T,T&,T*>    iterator;typedef __list_iterator<T,Ref,Ptr>  self;typedef std::bidirectional_iterator_tag iterator_category;typedef T value_type;typedef Ptr pointer;typedef Ref reference;typedef __list_node<T>* link_type;typedef std::size_t size_type;typedef ptrdiff_t difference_type;link_type node;//迭代器內部需要一個普通的指針,指向list節點//constructor__list_iterator(){}__list_iterator(link_type x):node(x){}__list_iterator(const iterator& x):node(x.node){}bool operator==(const self& x) const{return (node == x.node);}bool operator!=(const self& x) const{return (node != x.node);}//以下對迭代器取值 取得的是節點的數據值reference operator*() const {return (*node).data;}//以下是對迭代器的成員進行存取 (member access) 運算子的標準做法pointer operator->() const {return &(operator*());}//對迭代器進行加一 前進一個節點self& operator++(){node = (link_type)((*node).next);}self operator++(int){self tmp = *this;++*this;return tmp;}//對迭代器進行減一 后退一個節點self& operator--(){node = (link_type)((*node).prev);}self operator--(int){self tmp = *this;--*this;return tmp;}//讓指針node刻意指向尾端的一個空白節點,node節點便會符合STL對于前開后閉區間的要求,成為list迭代器iterator begin(){return (link_type)(*node->next);}iterator end(){return node;}bool empty()const{return node->next == node;}size_type size()const{size_type result = 0;std::distance(begin(),end(),result);return result;}//取頭部節點的內容(元素數值)reference front(){return *begin();}//取尾節點的內容(元素數值)reference back(){return *(--end());}
};
//list 環狀雙向鏈表設計如下
template <class T,class Alloc> //缺省使用alloc作為配置器
class list{
protected:typedef __list_node<T> list_node;
public:typedef list_node* link_type;
protected:link_type node; //只需要一個指針,便可以循環遍歷整個環狀的雙向鏈表
};

?list 的構造和內存管理

  • 具體內容見代碼注釋
//list 環狀雙向鏈表設計如下
template <class T,class Alloc> //缺省使用alloc作為配置器
class list{protected:typedef __list_node<T> list_node;//專屬空間配置器 每次配置一個節點的大小
public:typedef list_node* link_type;typedef simple_alloc<list_node,Alloc>list_node_allocator;//list_node_allocator(n) 表示分配n個節點空間,以下四個函數分別用來配置、釋放、構造、銷毀一個節點
protected://配置一個節點并返回link_type get_node(){return list_node_allocator::allocate();}//釋放一個節點link_type put_node(){return list_node_allocator::deallocate();}//產生(配置并構造)一個節點 帶有元素數值link_type create_node(const T& x){link_type p = get_node();Chy::allocator<T>::construct(p->data,x); //全局函數 構造/析構基本工具return p;}//銷毀 (析構并釋放) 一個節點void destroy_node(link_type p){Chy::allocator<T>::destroy(&p->data);  //全局函數 構造/析構基本工具}public://構造函數//產生一個空的鏈表list(){empty_initialize();} //產生一個空的鏈表
protected:link_type node; //只需要一個指針,便可以循環遍歷整個環狀的雙向鏈表void empty_initialize(){node = get_node();  //配置一個節點空間,令node指向它node->next = node;  //令node頭尾指向自己  不設置元素值node->prev = node;  }
};

  • ?當使用push_back()將新的元素插入到list的尾端的時候 ,這個函數內部調用的是insert();

list 的元素操作

//清除所有的節點(整個鏈表)
template <class T,class Alloc>
void list<T,Alloc>::clear() {link_type cur = (link_type)node->next; //begin()while (cur != node){   //遍歷每一個節點link_type tmp = cur;cur = (link_type)cur->next;destroy_node(tmp); //銷毀、析構釋放一個節點}//恢復node的原始狀態node->next = node;node->prev = node;
}//清除數值為value的所有元素
template<class T,class Alloc>
void list<T,Alloc>::remove(const T &value) {typedef typename __list_iterator<T,T&,T*>::iterator iterator;iterator first = __list_iterator<T,T&,T*>::begin();iterator last = __list_iterator<T,T&,T*>::end();while (first != last){iterator next = first;++next;if (*first == value){__list_iterator<T,T&,T*>::erase(value);first = next;}}
}//移除數值相同的連續元素,注意:只有"連續并且相同的元素",才會被刪除只剩一個
template <class T,class Alloc>
void list<T,Alloc>::unique() {typedef typename __list_iterator<T,T&,T*>::iterator iterator;iterator first = __list_iterator<T,T&,T*>::begin();iterator last = __list_iterator<T,T&,T*>::end();if (first == last){return; //空的鏈表  什么都不做}iterator next = first;while(++next != last){       //遍歷每一個節點if (*first == *next){    //如果這個區段中存在相同的元素__list_iterator<T,T&,T*>::erase(next); //移除之} else{first = next;        //調整指針}next = first;            //修正區段范圍}
}
  • list是一個雙向的環狀鏈表,只需要處理邊界條件,在頭部和尾部插入和刪除的操作幾乎是一樣的
  • 移除(erase) 某個迭代器所指向的元素,只是進行指針移動操作

  • list提供了一個遷移操作(transfer),將連續范圍的元素遷移到某個特定位置之前,技術角度上講是節點之間的指針移動
  • transfer遷移操作 是 其余操作(splice 、 sort 、 merge)的基礎
  • transfer的源代碼?

  • transfer接收的[first , last)區間可以在同一個list中
  • transfer不是公開的接口,list提供的是所謂的接合操作(splice) ,將某聯系范圍的元素從一個list移動到另一個(或者同一個)list的某個定點?
    //將[first , last) 內的所有元素 移動到 position之前void transfer(iterator position,iterator first,iterator last){if (last != position){(*(link_type((*last.node).prev))).next = position.node; //1(*(link_type((*first.node).prev))).next = last.node;    //2(*(link_type((*position.node).prev))).next = first.node;//3link_type tmp = link_type ((*position.node).prev);      //4(*position.node).prev = (*last.node).prev;              //5(*last.node).prev = (*first.node).prev;                 //6(*first.node).prev = tmp;                               //7}}

  • 本質上是節點之間的指針移動,上述splice、reverse、sort函數本身依靠的是transfer函數

  • ?完整代碼? 不一定對
#include <iostream>
#include <list>template<class T,class Alloc>
class simple_alloc{
public:static T* allocate(std::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 (n!=0){Alloc::deallocate(p,n * sizeof(T));}}static void deallocate(T* p){Alloc::deallocate(p,sizeof(T));}
};namespace Chy{template <class T>inline T* _allocate(ptrdiff_t size,T*){std::set_new_handler(0);T* tmp = (T*)(::operator new((std::size_t)(size * sizeof (T))));if (tmp == 0){std::cerr << "out of memory" << std::endl;exit(1);}return tmp;}template<class T>inline void _deallocate(T* buffer){::operator delete (buffer);}template<class T1,class T2>inline void _construct(T1 *p,const T2& value){new(p) T1 (value);  //沒看懂}template <class T>inline void _destroy(T* ptr){ptr->~T();}template <class T>class allocator{public:typedef T           value_type;typedef T*          pointer;typedef const T*    const_pointer;typedef T&          reference;typedef const T&    const_reference;typedef std::size_t size_type;typedef ptrdiff_t   difference_type;template<class U>struct rebind{typedef allocator<U>other;};pointer allocate(size_type n,const void * hint = 0){return _allocate((difference_type)n,(pointer)0);}void deallocate(pointer p,size_type n){_deallocate(p);}void construct(pointer p,const T& value){_construct(p,value);}void destroy(pointer p){_destroy(p);}pointer address(reference x){return (pointer)&x;}const_pointer const_address(const_reference x){return (const_pointer)&x;}size_type max_size()const{return size_type(UINT_MAX/sizeof (T));}};
}//如果是copy construction 等同于assignment而且destructor 是 trivial以下就會有效
//如果是POD型別 執行的流程就會跳轉到以下函數,這個是通過function template的參數推導機制得到的
template<class ForwardIterator,class Size,class T>
inline ForwardIterator __uninitizlized_fill_n_aux(ForwardIterator first,Size n,const T&x){return fill_n(first,n,x); //交給高階函數執行
}struct __true_type{};
struct __false_type{};template<class T>
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_constructor;typedef __false_type has_trivial_destructor;typedef __false_type is_POD_type;
};//函數的邏輯是
//首先萃取出 迭代器first的value type,然后判斷這個型別是否是POD類型
template<class ForwardIterator,class Size,class T,class T1>
inline ForwardIterator __uninitizlized_fill_n(ForwardIterator first,Size n,const T&x,T1*){//以下使用的是__type_traits<T1>::is_POD_type is _PODtypedef typename __type_traits<T1>::is_POD_type is_POD;return __uninitizlized_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 __uninitizlized_fill_n(first,n,x,value_type(first));//使用value_type()判斷first的value type
}//list的節點結構設計
template <class T>
struct __list_node{typedef void* void_pointer;void_pointer prev;   //指針的類型是void*,其實可以將其設定為 __list_node<T>void_pointer next;T data;
};//list的迭代器設計
template <class T,class Ref,class Ptr>
struct __list_iterator{typedef __list_iterator<T,T&,T*>    iterator;typedef __list_iterator<T,Ref,Ptr>  self;typedef std::bidirectional_iterator_tag iterator_category;typedef T value_type;typedef Ptr pointer;typedef Ref reference;typedef __list_node<T>* link_type;typedef std::size_t size_type;typedef ptrdiff_t difference_type;link_type node;//迭代器內部需要一個普通的指針,指向list節點//constructor__list_iterator(){}__list_iterator(link_type x):node(x){}__list_iterator(const iterator& x):node(x.node){}bool operator==(const self& x) const{return (node == x.node);}bool operator!=(const self& x) const{return (node != x.node);}//以下對迭代器取值 取得的是節點的數據值reference operator*() const {return (*node).data;}//以下是對迭代器的成員進行存取 (member access) 運算子的標準做法pointer operator->() const {return &(operator*());}//對迭代器進行加一 前進一個節點self& operator++(){node = (link_type)((*node).next);}self operator++(int){self tmp = *this;++*this;return tmp;}//對迭代器進行減一 后退一個節點self& operator--(){node = (link_type)((*node).prev);}self operator--(int){self tmp = *this;--*this;return tmp;}};//list 環狀雙向鏈表設計如下
template <class T,class Alloc> //缺省使用alloc作為配置器
class list{protected:typedef typename __list_iterator<T,T&,T*>::iterator iterator;typedef typename __list_iterator<T,T&,T*>::value_type value_type;typedef typename __list_iterator<T,T&,T*>::reference reference;typedef typename __list_iterator<T,T&,T*>::size_type size_type;typedef __list_node<T> list_node;//專屬空間配置器 每次配置一個節點的大小
public:typedef list_node* link_type;typedef simple_alloc<list_node,Alloc>list_node_allocator;//list_node_allocator(n) 表示分配n個節點空間,以下四個函數分別用來配置、釋放、構造、銷毀一個節點
protected://配置一個節點并返回link_type get_node(){return list_node_allocator::allocate();}//釋放一個節點link_type put_node(){return list_node_allocator::deallocate();}//產生(配置并構造)一個節點 帶有元素數值link_type create_node(const T& x){link_type p = get_node();Chy::allocator<T>::construct(p->data,x); //全局函數 構造/析構基本工具return p;}//銷毀 (析構并釋放) 一個節點void destroy_node(link_type p){Chy::allocator<T>::destroy(&p->data);  //全局函數 構造/析構基本工具}public://讓指針node刻意指向尾端的一個空白節點,node節點便會符合STL對于前開后閉區間的要求,成為list迭代器iterator begin(){return (link_type)(*node->next);}iterator end(){return node;}bool empty()const{return node->next == node;}size_type size()const{size_type result = 0;std::distance(begin(),end(),result);return result;}//取頭部節點的內容(元素數值)reference front(){return *begin();}//取尾節點的內容(元素數值)reference back(){return *(--end());}//插入元素 供push_back()函數調用//insert函數 需要配置并構造一個節點,然后在尾端進行指針操作,將新的節點插入進去//函數的目的是為了在迭代器指定的位置插入一個節點,內容為xiterator insert(iterator position,const T&x){ //產生一個節點,默認初始化元素數值為xlink_type tmp = create_node(x);//調整雙指針 將tmp插入進去tmp->next = position.node;tmp->prev = position.node->prev;(link_type(position.node->prev))->next = tmp;position.node->prev = tmp;return tmp;}//插入一個節點 作為頭部節點void push_front(const T& x){insert(begin(),x);}//插入一個節點 作為尾節點void push_back(const T& x){insert(end(),x);}//移除迭代器position指向的節點iterator erase(iterator position){link_type next_node = link_type (position.node->next);link_type prev_node = link_type (position.node->prev);prev_node->next = next_node;next_node->prev = prev_node;destroy_node(position.node);return iterator (next_node);}//移除頭部節點void pop_front(){erase(begin());}//移除尾部節點void pop_back(){iterator tmp = end();erase(--tmp);}//將[first , last) 內的所有元素 移動到 position之前void transfer(iterator position,iterator first,iterator last){if (last != position){(*(link_type((*last.node).prev))).next = position.node; //1(*(link_type((*first.node).prev))).next = last.node;    //2(*(link_type((*position.node).prev))).next = first.node;//3link_type tmp = link_type ((*position.node).prev);      //4(*position.node).prev = (*last.node).prev;              //5(*last.node).prev = (*first.node).prev;                 //6(*first.node).prev = tmp;                               //7}}public://構造函數//產生一個空的鏈表list(){empty_initialize();} //產生一個空的鏈表void clear();void remove(const T& value);void unique();protected:link_type node; //只需要一個指針,便可以循環遍歷整個環狀的雙向鏈表//空初始化void empty_initialize(){node = get_node();  //配置一個節點空間,令node指向它node->next = node;  //令node頭尾指向自己  不設置元素值node->prev = node;}public://將x結合于position所指定位置之前 x必須不同于*thisvoid splice(__list_iterator<T, T &, T *>, list &x);//將i指向的元素結合于position所指定的位置之前。position和i可以指向同一個listvoid splice(iterator position,list& ,iterator i){iterator j = i;++j;if (position == i || position == j){return;}transfer(position,i,j);}//將[first,last)內的元素接合于position指定的位置之前//position 和 [first,last)內可能指向的是同一個list//但是position 不能位于 [first,last)內部void splice(iterator position,list &,iterator first,iterator last){if (first != last){transfer(position,first,last);}}//merage() 將x合并到*this身上,但是兩個lists的內容都必須要先經過遞增排序void meage(list& x){iterator first1 = begin();iterator last1  = end();iterator first2 = x.begin();iterator last2 = x.end();//兩個list實現需要經過排序while (first1 != last1 && first2 != last2){if (*first2 < *first1){iterator next = first2;transfer(first1,first2,++next);first2 = next;} else{++first1;}if (first2 != last2){transfer(last1,first2,last2);}}}//reverse() 將this的內容 逆向重置void reverse(){//以下判斷,如果是空的鏈表,或者僅僅只有一個元素,就不進行任何的操作//使用size() == 0 || size() == 1 判斷,速度較慢if (node->next == node ||link_type(node->next)->next == node)return;iterator first = begin();++first;while (first != end()){iterator old = first;++first;transfer(begin(),old,first);}}//list不能使用STL算法的sort() 因為STL算法只接受randomAccessIterator//本函數使用快速排序void sort(){//以下判斷,如果是空的鏈表,或者僅僅只有一個元素,就不進行任何的操作//使用size() == 0 || size() == 1 判斷,速度較慢if (node->next == node ||link_type(node->next)->next == node)return;//使用一些新的lists 作為中介數據存儲區list carry;list counter[64];int fill = 0;while (!empty()){carry.splice(carry.begin(),*this,begin());int i = 0;while (i < fill && !counter[i].empty()){counter[i].merage(carry);carry.swap(counter[i++]);}carry.swap(counter[i]);if (i == fill){++fill;}}for (int i = 1; i < fill; ++i) {counter[i].merage(counter[i-1]);}std::swap(counter[fill-1]);}
};//清除所有的節點(整個鏈表)
template <class T,class Alloc>
void list<T,Alloc>::clear() {link_type cur = (link_type)node->next; //begin()while (cur != node){   //遍歷每一個節點link_type tmp = cur;cur = (link_type)cur->next;destroy_node(tmp); //銷毀、析構釋放一個節點}//恢復node的原始狀態node->next = node;node->prev = node;
}//清除數值為value的所有元素
template<class T,class Alloc>
void list<T,Alloc>::remove(const T &value) {typedef typename __list_iterator<T,T&,T*>::iterator iterator;iterator first = __list_iterator<T,T&,T*>::begin();iterator last = __list_iterator<T,T&,T*>::end();while (first != last){iterator next = first;++next;if (*first == value){__list_iterator<T,T&,T*>::erase(value);first = next;}}
}//移除數值相同的連續元素,注意:只有"連續并且相同的元素",才會被刪除只剩一個
template <class T,class Alloc>
void list<T,Alloc>::unique() {typedef typename __list_iterator<T,T&,T*>::iterator iterator;iterator first = __list_iterator<T,T&,T*>::begin();iterator last = __list_iterator<T,T&,T*>::end();if (first == last){return; //空的鏈表  什么都不做}iterator next = first;while(++next != last){       //遍歷每一個節點if (*first == *next){    //如果這個區段中存在相同的元素__list_iterator<T,T&,T*>::erase(next); //移除之} else{first = next;        //調整指針}next = first;            //修正區段范圍}
}template <class T,class Alloc>
void list<T,Alloc>::splice(__list_iterator<T, T &, T *>position, list<T, Alloc> &x) {if (!x.empty()){transfer(position,x.begin(),x.end());}
}
  • 涉及到transfer的相關函數的代碼 理解不是很透徹 垃圾

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/446278.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/446278.shtml
英文地址,請注明出處:http://en.pswp.cn/news/446278.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vsftp不允許切換到其它目錄_IntelliJ IDEA如何對project的目錄進行篩選顯示?

如果你的項目很龐大&#xff0c;同一個功能用到的各種文件散落在多個文件夾&#xff0c;開發時切換不便&#xff0c;可以利用scope功能&#xff0c;只顯示該功能用到的文件&#xff0c;讓project列表十分清爽&#xff0c;提高開發效率。本文使用的IDEA版本為2020.1。1、打開sco…

java 年份對應的中國生肖

題目 編寫一個程序&#xff0c;為一個給定的年份找出其對應的中國生肖。 中國的生肖基于12年一個周期&#xff0c; 每年用一個動物代表&#xff1a; rat、ox、tiger、rabbit、dragon、snake、horse、sheep、monkey、 rooster、dog、pig。 提示&#xff1a;2019年&#xff1a;豬…

密碼學專題 對稱加密算法

一般來說&#xff0c;使用OpenSSL對稱加密算法有兩種方式&#xff0c;一種是使用API函數的方式&#xff0c;一種是使用OpenSSL提供的對稱加密算法指令方式。本書將介紹對稱加密算法的指令方式OpenSSL的對稱加密算法指令主要用來對數據進行加密和解密處理&#xff0c;輸入輸出的…

網絡防火墻單向和雙向_單向晶閘管與雙向晶閘管之間的不同之處

晶閘管是回一個可以控導點開關&#xff0c;能以弱電去控制強電的各種電路。晶閘管常用于整流&#xff0c;調壓&#xff0c;交直流變化&#xff0c;開關&#xff0c;調光等控制電路中。具有提交小&#xff0c;重量輕&#xff0c;耐壓高&#xff0c;容量大&#xff0c;效率高&…

java 遍歷100以內的偶數,偶數的和,偶數的個數

題目 遍歷100以內的偶數&#xff0c;偶數的和&#xff0c;偶數的個數 代碼 package l2_for; /*遍歷100以內的偶數&#xff0c;偶數的和&#xff0c;偶數的個數*/ public class ForDemo1 {public static void main(String[] args) {//方法1&#xff1a;int sum1 0,count10;f…

python版本切換_怎么切換python版本

展開全部 &#xff08;1&#xff09;分別安2113裝 python-2.7.12.amd64.msi python-3.5.2-amd64.exe &#xff08;python官網下載的&#xff09; 順序無所謂&#xff08;為5261了看著4102方便&#xff0c;我把安裝路徑修改統一了1653&#xff09; &#xff08;2&#xff09;配置…

java 打印

題目 編寫程序從1循環到150&#xff0c;并在每行打印一個值&#xff0c;另外在每個3的倍數行 上打印出“foo”,在每個5的倍數行上打印“biz”,在每個7的倍數行上打印 輸出“baz”。 代碼 package l2_for;/** 編寫程序從1循環到150&#xff0c;并在每行打印一個值&#xff0c…

react.lazy 路由懶加載_Vue面試題: 如何實現路由懶加載?

非懶加載import List from /components/list.vue const router new VueRouter({routes: [{ path: /list, component: List }] })方案一(常用)const List () > import(/components/list.vue) const router new VueRouter({routes: [{ path: /list, component: List }] })方…

STL源碼剖析 deque雙端隊列 概述

vector是單向開口的連續線性空間&#xff0c;deque是一種雙向開口的連續線性空間。deque可以在頭尾兩端分別進行元素的插入和刪除操作vector和deque的差異 1&#xff0c;deque允許常數時間內對于頭端元素進行插入和刪除操作2&#xff0c;deque沒有所謂容量(capacity)的概念&…

java 最大公約數和最小公倍數

題目 題目&#xff1a;輸入兩個正整數m和n&#xff0c;求其最大公約數和最小公倍數。 比如&#xff1a;12和20的最大公約數是4&#xff0c;最小公倍數是60。 說明&#xff1a;break關鍵字的使用 代碼一 package l2_for; //題目&#xff1a;輸入兩個正整數m和n&#xff0c;求…

python的自帶數據集_Python的Sklearn庫中的數據集

一、Sklearn介紹 scikit-learn是Python語言開發的機器學習庫&#xff0c;一般簡稱為sklearn&#xff0c;目前算是通用機器學習算法庫中實現得比較完善的庫了。其完善之處不僅在于實現的算法多&#xff0c;還包括大量詳盡的文檔和示例。其文檔寫得通俗易懂&#xff0c;完全可以當…

STL源碼剖析 stack 棧 概述->(使用deque雙端隊列 / list鏈表)作為stack的底層容器

Stack是一種先進后出的數據結構&#xff0c;他只有一個出口stack允許 新增元素、移除元素、取得最頂端的元素&#xff0c;但是無法獲得stack的內部數據&#xff0c;因此satck沒有遍歷行為Stack定義的完整列表 (雙端隊列作為Stack的底層容器) 將deque作為Stack的底部結構&#…

java 三位數的水仙花數

代碼 package l2_for;public class ForDemo6 {public static void main(String[] args) {for (int i 100; i <999 ; i) {int i1i/1%10;int i2i/10%10;int i3i/100%10;if (i(int)(Math.pow(i1,3)Math.pow(i2,3)Math.pow(i3,3))){System.out.print(i"\t");}}} }

python怎么實現圖像去噪_基于深度卷積神經網絡和跳躍連接的圖像去噪和超分辨...

Image Restoration Using Very Deep Convolutional Encoder-Decoder Networks with Symmetric Skip Connections作者&#xff1a;Xiao-Jiao Mao、Chunhua Shen等本文提出了一個深度的全卷積編碼-解碼框架來解決去噪和超分辨之類的圖像修復問題。網絡由多層的卷積和反卷積組成&a…

STL源碼剖析 queue隊列概述

queue是一種先進先出的數據結構&#xff0c;他有兩個出口允許新增元素&#xff08;從最底端 加入元素&#xff09;、移除元素&#xff08;從最頂端刪除元素&#xff09;&#xff0c;除了對于頂端和底端元素進行操作之外&#xff0c;沒有辦法可以獲取queue的其他元素即queue沒有…

java輸入正數和負數并計算個數

題目 從鍵盤讀入個數不確定的整數&#xff0c;并判斷讀入的正數和負數的個數&#xff0c;輸入 為0時結束程序。 知識點 最簡單“無限” 循環格式&#xff1a;while(true) , for(;;),無限循環存在的原因是并不 知道循環多少次&#xff0c;需要根據循環體內部某些條件&#xf…

python為什么運行不了_python為什么會環境變量設置不成功

學習python編程&#xff0c;首先要配置好環境變量。本文主要講解python的環境變量配置&#xff0c;在不同版本下如何安裝 Windows 打開Python官方下載網站 x86:表示是32位電腦 x86-64:表示是64位電腦 目前Python版本分為2.x版本和3.x版本。推薦大家使用3.x版本。 設置環境變量&…

STL 源碼剖析 heap堆

heap不屬于STL容器的組件&#xff0c;屬于幕后角色&#xff0c;是priority_queue的助手priority_queue 允許用戶以任何次序將任何元素推入容器內&#xff0c;但是取出的時候需要從優先級最高(也就是數值最高)的元素開始取&#xff0c;這種思想是基于heap的函數實現如果使用list…

java 打印星號

代碼1 package lesson.l2_for; //6列4行 //****** //****** //****** //****** public class ForDemo8 {public static void main(String[] args) {for (int i1;i<4;i){for (int j 1; j <6 ; j) {System.out.print("*");}System.out.println();}} }代碼2 pa…

python從小白到大牛百度云盤_Java從小白到大牛 (關東升著) 中文pdf+mobi版[36MB]

《Java從小白到大牛》是一本Java語言學習立體教程&#xff0c;讀者群是零基礎小白&#xff0c;通過本書的學習能夠成為Java大牛。主要內容包括&#xff1a;Java語法基礎、Java編碼規范、數據類型、運算符、控制語句、數組、字符串、面向對象基礎、繼承與多態、抽象類與接口、枚…