資料結構篇-雙鏈表

來源:互聯網
上載者:User

#include<iostream>//stl版雙鏈表,與迭代器共同工作#include"mymemory.h"#include"myconstruct.h"template<typename T>struct __list_node{typedef void* void_pointer;void_pointer prev;//其實可以設為__list_node<T>*void_pointer next;T data;};template<typename T,typename Ref,typename Ptr>struct __list_iterator{//這兩個有什麼作用?typedef __list_iterator<T,T&,T*> iterator;typedef __list_iterator<T,Ref,Ptr>  self;typedef bidirectional_iterator_tag iterator_category;typedef T   value_type;typedef Ptr   pointer;typedef Ref reference;typedef __list_node<T>*  link_type;typedef size_t  size_type;typedef ptrdiff_t   difference_type;link_type node;//這個就是迭代器與容器的紐帶//constructor__list_iterator(link_type x):node(x){ }__list_iterator(){}__list_iterator(const iterator& x):node(x.node){ }/*這兒的實現可能有點差, *根據C++ primer的建議,重載操作符時的四條原則: *1.=,[],(),->必須是類成員 *2.複合賦值的操作符通常定義為類成員 *3.改變對象狀態或與給定類型密切聯絡的通常應定義為類成員,如:自增,自減,解引用 *4.對稱的操作符,如算術,相等,關係,位操作符最好定義為普通成員函數 */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;}//取值pointer    operator->() const{return &(operator*());}//注意此處self& operator++(){node=(link_type)(node->next);return *this;}self operator++(int){self tmp=*this;++*this;return tmp;}self& operator--(){node=(link_type)(node->prev);return *this;}self operator--(int){self tmp=*this;--*this;return tmp;}};template<typename T,typename Alloc=alloc>class list{public:  typedef T value_type;  typedef value_type* pointer;  typedef const value_type* const_pointer;  typedef value_type& reference;  typedef const value_type& const_reference;  typedef size_t size_type;  typedef ptrdiff_t difference_type;  typedef __list_iterator<T,T&,T*>  iterator;protected:typedef __list_node<T> list_node;typedef simple_alloc<list_node,Alloc> node_allocator;public:typedef list_node* link_type;protected:link_type node;//一個指標,迴圈遍曆整體環形雙向鏈表,只要令其指向尾端的一個空白節點,//node變能符合前開後閉要求,成為last迭代器,node的next指向鏈表的頭結點,如果鏈表//為空白,則指向自身public:list(){ empty_initialize();}//產生一個空鏈表iterator begin() {return (link_type)(node->next);}iterator  end(){return node;}bool empty() const{return node->next==node;}inline size_t size() const;reference front(){return *begin();}reference back(){return *(--end());}//在position之前插入一個節點,內容為xiterator insert(iterator position,const T& x);void push_back(const T& x){insert(end(),x);}void push_front(const T& x){insert(begin(),x);}iterator erase(iterator position);//移除position所指的節點void pop_front(){erase(begin());}void pop_back(){erase(--end());}void clear();//清除鏈表void remove(const T& value);//移除值為value的元素void unique();//移除數值相同的連續元素public://交換兩個鏈表;void swap(list& x){link_type tmp;tmp=node;node=x.node;x.node=tmp;}//將[first,last)內的所有元素移動到position之前void transfer(iterator position,iterator first,iterator last);void splice(iterator position,list& x){//將x接合於position所指位置之前,x不同於*thisif(!x.empty()) transfer(position,x.begin(),x.end());}void splice(iterator position,list&,iterator i);//將i所指元素接合於position之前//[first,last)中的所有元素接合於position所指位置之前void splice(iterator position,list&,iterator first,iterator last){if(first!=last) transfer(position,first,last);}void merge(list& x);//兩個list都經過遞增排序,將x合并到*thisvoid reverse();//翻轉void sort();//這裡採用的是歸併排序protected://配置一個結點並傳回link_type  get_node(){return node_allocator::allocate();}//釋放一個結點void put_node(link_type p){node_allocator::deallocate(p);}//產生(配置並構造)一個節點,帶有元素值link_type create_node(const T& x){link_type p=get_node();construct(&(p->data),x);return p;}//銷毀(析構並釋放)一個節點void destroy_node(link_type p){destroy(&(p->data));put_node(p);}inline void empty_initialize();};//-----------------------------------------------------------------template<typename T,typename Alloc>inline size_t list<T,Alloc>::size()  const{size_t result=0;link_type p=node->next;while(p!=node){++result;p=p->next;}return result;}//--------------------------------------------------------------------template<typename T,typename Alloc>inline void list<T,Alloc>::empty_initialize(){node=get_node();node->next=node;node->prev=node;}//--------------------------------------------------------------------template<typename T,typename Alloc>typename list<T,Alloc>::iterator list<T,Alloc>::insert(iterator position,const T& x){link_type tmp=create_node(x);tmp->next=position.node;tmp->prev=position.node->prev;(link_type(position.node->prev))->next=tmp;position.node->prev=tmp;return tmp;}//---------------------------------------------------------------------template<typename T,typename Alloc>typename list<T,Alloc>::iterator list<T,Alloc>::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);}//------------------------------------------------------------------------template<typename T,typename Alloc>void list<T,Alloc>::clear(){link_type cur=(link_type)node->next;while(cur!=node){link_type tmp=cur;cur=(link_type) cur->next;destroy(tmp);}node->next=node;node->prev=node;}//------------------------------------------------------------------------template<typename T,typename Alloc>void list<T,Alloc>::remove(const T& value){iterator first=begin();iterator last=end();while(first!=last){iterator next=first;++next;if(*first==value) erase(first);first=next;}}//-----------------------------------------------------------------------template<typename T,typename Alloc>void list<T,Alloc>::unique(){iterator first=begin();iterator last=end();if(first==last) return;iterator next=first;while(++next!=last){if(*first==*next)erase(next);elsefirst=next;next=first;}}//-------------------------------------------------------------------------template<typename T,typename Alloc>void list<T,Alloc>::transfer(iterator position,iterator first,iterator last){if(position!=last){(*(link_type((*last.node).prev))).next=position.node;(*(link_type((*first.node).prev))).next=last.node;(*(link_type((*position.node).prev))).next=first.node;link_type tmp=link_type((*position.node).prev);(*last.node).prev=(*first.node).prev;(*first.node).prev=tmp;}}//---------------------------------------------------------------------------template<typename T,typename Alloc>void list<T,Alloc>::splice(iterator position,list&,iterator i){iterator j=i;++j;if(position==i||position==j)return;transfer(position,i,j);}//-------------------------------------------------------------------------template<typename T,typename Alloc>void list<T,Alloc>::merge(list<T,Alloc>& x){iterator first1=begin();iterator last1=end();iterator first2=x.begin();iterator last2=x.end();while(first1!=last1 &&first2!=last2){if(*first2<*first1){iterator next=first2;transfer(first1,first2,++next);}else++first1;}if(first2!=last2) transfer(last1,first2,last2);}//-------------------------------------------------------------template<typename T,typename Alloc>void list<T,Alloc>::reverse(){//空鏈表或者只有一個元素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);}}//-----------------------------------------------------------------//沒有調試成功template<typename T,typename Alloc>void list<T,Alloc>::sort()//此處mergesort我覺得不如quicksort,但是此處的實現方法很有趣,//值得一看{if(node->next==node||link_type(node->next)->next==node) return;//中介資料存放區區list<T,Alloc> carry;list<T,Alloc> counter[64];int fill=0;//counter[0]儲存2元素,counter[1]儲存排序的四元素。。。。。while(!empty()){//每次這個迴圈開始,carry取原list中的一個元素carry.splice(carry.begin(),*this,begin());//這兒的控制是,如果counter[0]中已有一個元素,先將carry與counter[0]合并,如果counter[0]//為空白,那麼就將carry中的元素給counter[0],然後將合并好的元素傳遞給carry,counter[0]為空白//如果此時counter[1]中已有兩個元素,那麼將其合并,如果沒有的話,就把這兩個元素傳給counter[1]//然後carry再取元素。。。。迴圈重複    int i=0;   while(i<fill &&!counter[i].empty()){     counter[i].merge(carry);     carry.swap(counter[i]); ++i;      }   carry.swap(counter[i]);   if(i==fill)++fill;}for(int i=1;i<fill;++i){counter[i].merge(counter[i-1]);}swap(counter[fill-1]);}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.