zoukankan      html  css  js  c++  java
  • 线性表

    本文是为了加深自己对线性表的印象。附有复杂度的分析,数组实现和指针实现的优缺点等。

    一、线性表

    template <typename E> class List{
        private:
        void operator=(const List&){} //protect assignment why?
        List(const List&) {}//protect copy constructor
        
        public:
        List(){}
        virtual ~List(){}
        
        virtual void clear()=0;//clear contents from the lists,to make it empty
        
        virtual void insert(const E& item)=0;
        
        virtual void append(const E& item)=0;//add a element in the end of the list
        
        virtual E remove()=0;//remove the current element
        
        virtual void moveToStart()=0;
        
        virtual void moveToEnd()=0;
        
        virtual void prev()=0;
        
        virtual void next()=0;
        
        virtual int length() const=0;
        
        virtual int currPos() const=0;
        
        virtual void moveToPos(int pos)=0;
        
        virtual const E& getValue() const=0;
        
    }

    二、数组实现线性表

    #include "List.h"
    template <typename E> class AList:public List<E>{
        private:
        int maxSize;
        int listSize;
        int curr;
        E* listArray;
        
        public:
        AList(){}
        AList(int size){
            maxSize=size;
            listSize=0;
            curr=0;
            listArray=new E[maxSize];
        }
        ~AList(){ delete [] listArray;}
        
        void clear(){
            delete [] listArray;
            curr=listSize=0;
            listArray=new E[maxSize];
        }
        
        bool check(){
            if(listSize>maxSize||listSize<0) {
                cout<<"out of range"<<endl;
                return true;
            }
        }
        
        //time complexity:O(n)
        void insert(const E& item){
            listSize++;
            if(check()) return;
            for(int cnt=listSize-1;cnt>curr;cnt--){
                listArray[cnt]=listArray[cnt-1];
            }
            listArray[curr]=item;
            return;
        }
        
        //time complexity:O(1)
        void append(const E&item){
            listSize++;
            if(check()) return;
            listArray[listSize-1]=item;
        }
        
        //time complexity:O(n)
        E remove(){
            int temp=listArray[cnt];
            listSize--;
            if(check()) return NULL;
            for(int cnt=curr;cnt<listSize;cnt++){
                listArray[cnt]=listArray[cnt+1];
            }
            return temp;
        }
        
        //time complexity:O(1)
        void moveToStart(){
            curr=0;
        }
        
        void moveToEnd(){
            curr=listSize;
        }
        
        void next(){
            if(curr>=listSize-1) cout<<"out of range"<<endl;
            curr++;
        }
        
        void prev(){
            if(curr<=0) cout<<"out of range"<<endl;
            curr--;
        }
        
        int length(){ return listSize;}
        int currPos(){return curr;}
        
        void moveToPos(int pos){
            if(pos<=0||pos>=listSize) cout<<"out of range"<<endl;
            curr=pos;
        }
        
        const E& getValue() const{
            if(listSize<=0) cout<<"No current element"<<endl;
            return listArray[curr];
        }
    
        void print() const{
            for (int cnt = 0; cnt < listSize; cnt++) {
                cout << listArray[cnt] << " ";
            }
            cout << endl;
        }
    }

    三、指针实现线性表

    template <typename E> class Link{
        public:
        E element;
        Link *next;
        
        Link(){
            next=nullptr;
        }
        Link(const E&item){
            element=item;
            next=nullptr;
        }
        Link(const E&item,Link* nextval){
            element=item;
            next=nextval;
        }
        Link(Link* nextval){
            next=nextval;
        }
    }
    
    template <typename E> class LList:public List<E>{
        private:
        Link<E>* head;
        Link<E>* tail;
        Link<E>* curr;
        int size;
        
        void init(){
            curr=tail=head=new Link<E>;
            cnt=0;
        }
        
        void removeall(){
            while(head!=nullptr){
                curr=head;
                head=head->next;
                delete curr;
            }
        }
        
        public:
        LList(){init();}
        LList(int length){
            init();
            cnt=length;
            int temp=cnt-1;
            while(temp--){
                append();
            }
        }
        
        void clear(){
            removeall();
            init();
        }
        
        void insert(const E&item){
            Link<E>* temp=new Link<E>(item,curr->next);
            curr->next=temp;
            if(tail==curr) tail=temp;
            size++;
        }
        
        void append(){
            tail->next=new Link<E>(0,nullptr);
            tail=tail->next;
            cnt++;
        }
        void append(const E&item){
            tail=tail->next=new Link<E>(item,nullptr);
            cnt++;
        }
        
        E remove(){//remove curr->next
            assert(curr!=tail,"No,element"); 
            E temp=curr->next->element;
            if(curr->next==tail){
                curr->next=nullptr;
                delete tail;
                tail=curr;
                cnt--;
            }
            else{
                Link<E>* ltemp=curr->next;
                curr->next=curr->next->next;
                delete ltemp;
                cnt--;
            }
            return temp;
        }
        
        void moveToStart(){
            curr=head;
        }
        
        void moveToEnd(){
            curr=tail;
        }
        
        void prev(){
            if(curr==head) return;
            Link<E>* temp=head;
            while(temp->next!=curr)
                temp=temp->next;
            curr=temp;
        }
        
        void next(){
            if(curr==tail) return;
            curr=curr->next;
        }
        
        int length() const{
            return size;
        }
        
        int currPos() const{
            Link<E>* temp=head;
            int cnt=0;
            while(temp!=curr){
                temp=temp->next;
                cnt++;
            return cnt;
        } 
        
        void moveToPos(int pos){
            Link<E>* temp=head;
            while(pos--){
                temp=temp->next;
            }
            curr=temp;
        }
        
        const E& getValue() const{
            return curr->element;
        }
    }

    四、两种实现方式各自的优缺点

    1.从存储空间上考虑 

    数组需要 size*n的大小。而链表需要 size*(n+4*cnt),指针本身需要空间存放。

    2.从访问速度上考虑

    数组访问任一成员的时间复杂度为O(1),而链表为O(n)

    3.从删除或添加成员带来的代价上考虑

    数组添加或删除任一成员的时间复杂度为O(n),而链表为O(1)

    4.从可扩展性考虑

    数组一旦建立,便不能更改大小,而链表可以随意扩大

    五、从链表衍生出来的其它数据结构

    freelist

    在链表创建和删除结点时,Link类的程序员能够提供简单而有效的内存管理例程,以代替系统级的存储分配和回收操作符。Link类能管理自己的可利用空间表(freelist),以取代反复调用的newdelete。当需要把一个新元素增加到链表时,先检查freelist是否为空,如果freelist不为空,则可从freelist中取走结点。在每次删除结点时,将其插入freelist中。

    template <typename E>class Link{
        private:
        static Link<E>* freelist;
        
        public:
        E element;
        Link* next;
        
        Link(Link* nextval=nullptr){
            next=nextptr;
        }
        Link(const E&item,Link* nextval=nullptr){
            element=item;
            next=nextptr;
        }
        
        void* operator new(size_t){
            if(freelist=nullptr) return ::new Link;
            Link<E>* temp=freelist;
            freelist=freelist->next;
            return temp;
        }
        
        void operator delete(void* ptr){
            ((Link<E>*)ptr)->next=freelist;
            freelist=(Link<E>*)ptr;
        }
    }
    
    template <typename E> Link<E>* Link<E>::freelist=nullptr;

    在重载new 函数中,原来的new函数被现在的 ::new 函数代替了。这表明标准的C++new操作符被调用,而不是重载的new操作,避免死循环。

    利用空间表,还能产生额外的功效:

    调用100次系统new操作符获得一百个结点远比调用一次new操作(一次获得100个结点)要慢。因此如果程序员需要成千上万个链表结点,可以先创建很多个结点在freelist中,实现程序的加速。

  • 相关阅读:
    Silverlight学习(五)图形标绘
    Silverlight学习(四) domainservice动态多条件查询
    MySQL之单表查询
    mysql外键的三种关系
    mysql之完整性约束
    接口类和抽象类的区别
    mysql中的sql_mode
    html5本地存储技术 localstorage
    mysql数值类型
    mysql
  • 原文地址:https://www.cnblogs.com/logosG/p/8058670.html
Copyright © 2011-2022 走看看