zoukankan      html  css  js  c++  java
  • 数据结构基础(12) --双向循环链表的设计与实现

    双向链表的操作特点:

        (1) “查询” 和单链表相同;

        (2)“插入” 和“删除”时需要同时修改两个方向上的指针。

       但是对于双向循环链表则在表尾插入非常的迅速, 只需O(1)的时间,因为有指向前面的指针, 因此双向循环链表会很容易的找到位于表尾的元素,因此双向循环链表比较适用于频繁在表尾插入的情况.



    空链表:


    双向循环链表节点构造:

    class DoubleListNode
    {
    private:
        Type data;
        DoubleListNode *prev;   //前向指针域
        DoubleListNode *next;   //后项指针域
    };

    因为需要将其用于DoubleList,因此需要将其改造如下:

    template <typename Type>
    class DoubleListNode
    {
        //友元声明
        friend class DoubleList<Type>;
        friend class ListIterator<Type>;
    
        template <typename T>
        friend ostream &operator<<(ostream &os, const DoubleList<T> &list);
    private:
        DoubleListNode(const Type &dataValue)
            :data(dataValue),prev(NULL),next(NULL) {}
    
        Type data;
        DoubleListNode *prev;   //前向指针域
        DoubleListNode *next;   //后项指针域
    };

    双向循环链表构造:

    template <typename Type>
    class DoubleList
    {
        friend class ListIterator<Type>;
        template <typename T>
        friend ostream &operator<<(ostream &os, const DoubleList<T> &list);
    public:
        DoubleList();
        ~DoubleList();
    
        void push_back(const Type &data);
        void push_front(const Type &data);
        void insert(int position, const Type &data);
    
        void pop_front();
        void pop_back();
        void remove(const Type &removeData);
    
        bool search(const Type &searchData) const;
        bool isEmpty() const
        {
            return (first->next == first);
        }
    
    private:
        //将节点x插入到节点previous后面
        void insertPrivate(DoubleListNode<Type> *previous,
                           DoubleListNode<Type> *x);
        void removePrivate(DoubleListNode<Type> *x);
    
    private:
        DoubleListNode<Type> *first;
    };

    链表的构造与析构:

    //构造链表
    template <typename Type>
    DoubleList<Type>::DoubleList()
    {
        first = new DoubleListNode<Type>(0);
        first->next = first;
        first->prev = first;
    }
    //析构链表
    template <typename Type>
    DoubleList<Type>::~DoubleList()
    {
        DoubleListNode<Type> *deleteNode = NULL;
        //保存链表尾元素
        DoubleListNode<Type> *tmp = first;
    
        //first首先指向第一个真实的元素
        first = first->next;
        //一路到达链表结尾
        while (first != tmp)
        {
            deleteNode = first;
            first = first -> next;
            delete deleteNode;
        }
        // 释放掉链表的空节点(表头)
        delete tmp;
    }

    链表元素插入与删除的两大主力:

    //同为private成员
    //插入节点
    template <typename Type>
    void DoubleList<Type>::insertPrivate(DoubleListNode<Type> *previous,
                                         DoubleListNode<Type> *x)
    {
        x->prev = previous;
        x->next = previous->next;
        previous->next->prev = x;
        previous->next = x;
    }

    //删除节点
    template <typename Type>
    void DoubleList<Type>::removePrivate(DoubleListNode<Type> *x)
    
    {
        if (x == first)
            throw std::range_error("permission denied to delete first pointer");
    
        x->prev->next = x->next;
        x->next->prev = x->prev;
        delete x;
    }

    提供给客户的插入:

    //插入到表尾
    template <typename Type>
    void DoubleList<Type>::push_back(const Type &data)
    {
        DoubleListNode<Type> *newNode = new DoubleListNode<Type>(data);
        //找到first的前一个节点
        DoubleListNode<Type> *previous = first->prev;
    
        //插入
        insertPrivate(previous, newNode);
    }
    //插入到表头
    template <typename Type>
    void DoubleList<Type>::push_front(const Type &data)
    {
        DoubleListNode<Type> *newNode = new DoubleListNode<Type>(data);
        //插入到first之后
        insertPrivate(first, newNode);
    }
    
    //插入到任意位置(依position指定)
    template <typename Type>
    void DoubleList<Type>::insert(int position, const Type &data)
    {
        if (position == 1)
            return push_front(data);
    
        int count = 1;
        //previous 代表着要插入位置之前的一个位置
        DoubleListNode<Type> *previous = first->next;
    
        //如果position过大, 则previous查找到first就会停止
        //此时应该将该元素插入到链表结尾
        while (count < position-1 && previous != first)
        {
            ++ count;
            previous = previous->next;
        }
    
        //如果查找到了链表结尾或此时链表为空, 因此插入到表尾
        if (previous == first)
            return push_back(data);
    
        //如果找到了合适的插入位置
        DoubleListNode<Type> *newNode = new DoubleListNode<Type>(data);
        insertPrivate(previous, newNode);
    }

    提供给客户的删除:

    //删除表尾元素
    template <typename Type>
    void DoubleList<Type>::pop_back()
    {
        removePrivate(first->prev);
    }
    //删除表头元素
    template <typename Type>
    void DoubleList<Type>::pop_front()
    {
        removePrivate(first->next);
    }
    
    //删除元素值为removeData的所有元素
    template <typename Type>
    void DoubleList<Type>::remove(const Type &removeData)
    {
        if (isEmpty())
            throw std::range_error("link list is empty");
    
        for( DoubleListNode<Type> *searchNode = first->next;
                searchNode != first;
                searchNode = searchNode->next)
        {
            if (searchNode->data == removeData)
                removePrivate(searchNode);
        }
    }

    查看是否存在于链表中:

    template <typename Type>
    bool DoubleList<Type>::search(const Type &searchData) const
    {
        DoubleListNode<Type> *searchNode = first->next;
        while (searchNode != first)
        {
            if (searchNode->data == searchData)
                return true;
    
            searchNode = searchNode->next;
        }
        return false;
    }

    输出链表所有元素(测试用):

    template <typename Type>
    ostream &operator<<(ostream &os, const DoubleList<Type> &list)
    {
        for (DoubleListNode<Type> *currentNode = (list.first)->next;
                currentNode != list.first;
                currentNode = currentNode->next)
            os << currentNode->data << ' ';
    
        return os;
    }

    双向循环链表迭代器的设计与实现:

    //除了添加了operator--, 几乎没做任何改变
    template <typename Type>
    class ListIterator
    {
    public:
        ListIterator(const DoubleList<Type> &_list):
            list(_list),
            currentNode((_list.first)->next) {}
    
        //重载 *operator
        const Type &operator*() const throw (std::out_of_range);
        Type &operator*() throw (std::out_of_range);
    
        //重载 ->operator
        const DoubleListNode<Type> *operator->() const throw (std::out_of_range);
        DoubleListNode<Type> *operator->() throw (std::out_of_range);
    
        //重载 ++operator
        ListIterator &operator++() throw (std::out_of_range);
        //注意:此处返回的是值,而不是reference
        ListIterator operator++(int) throw (std::out_of_range);
    
        //重载 --operator,
        // 其实这个版本的--operator是不完美的,
        // 因为他没有做任何的判错控制
        ListIterator &operator--();
        //注意:此处返回的是值,而不是reference
        ListIterator operator--(int);
    
        bool isEmpty() const
        {
            return (currentNode == list.first);
        }
    
    private:
        const DoubleList<Type> &list;
        DoubleListNode<Type> *currentNode;
    };
    template <typename Type>
    const Type &ListIterator<Type>::operator*() const
    throw (std::out_of_range)
    {
        if (isEmpty())
            throw std::out_of_range("iterator is out of range");
        // 返回当前指针指向的内容
        return currentNode->data;
    }
    template <typename Type>
    Type &ListIterator<Type>::operator*()
    throw (std::out_of_range)
    {
        return
            const_cast<Type &>(
                static_cast<const ListIterator<Type> &>(*this).operator*()
            );
    }
    template <typename Type>
    const DoubleListNode<Type> *ListIterator<Type>::operator->() const
    throw (std::out_of_range)
    {
        if (isEmpty())
            throw std::out_of_range("iterator is out of range");
    
        //直接返回指针
        return currentNode;
    }
    
    template <typename Type>
    DoubleListNode<Type> *ListIterator<Type>::operator->()
    throw (std::out_of_range)
    {
        return
            const_cast<DoubleListNode<Type> *> (
                static_cast<const ListIterator<Type> >(*this).operator->()
            );
    }
    template <typename Type>
    ListIterator<Type> &ListIterator<Type>::operator++()
    throw (std::out_of_range)
    {
        if (isEmpty())
            throw std::out_of_range("iterator is out of range");
        //指针前移
        currentNode = currentNode->next;
        return *this;
    }
    template <typename Type>
    ListIterator<Type> ListIterator<Type>::operator++(int)
    throw (std::out_of_range)
    {
        ListIterator tmp(*this);
        ++ (*this); //调用前向++版本
    
        return tmp;
    }
    template <typename Type>
    ListIterator<Type> &ListIterator<Type>::operator--()
    {
        //指针前移
        currentNode = currentNode->prev;
        return *this;
    }
    template <typename Type>
    ListIterator<Type> ListIterator<Type>::operator--(int)
    {
        ListIterator<Type> tmp(*this);
        -- (*this);
    
        return tmp;
    }

    测试代码:

    int main()
    {
        cout << "-------- 1 --------" << endl;
        DoubleList<int> myList;
    
        for (int i = 0; i < 3; ++i)
            myList.push_back(i+1);
        for (int i = 0; i < 5; ++i)
            myList.push_front(10+i);
        for (int i = 0; i < 3; ++i)
            myList.push_back(i+1);
    
        ListIterator<int> iter(myList), iter2(myList);
        while (!iter.isEmpty())
        {
            cout << *iter << ' ';
            ++ iter;
    
            ++ iter2;
        }
        cout << endl;
    
        -- iter2;
        while (!iter2.isEmpty())
        {
            cout << *iter2 << ' ';
            iter2 --;
        }
        cout << endl;
    
        cout << "-------- 2 --------" << endl;
    
        cout << myList << endl;
        cout << "Test insert..." << endl;
        myList.insert(1, 14);
        myList.insert(2, 13);
        myList.insert(2, 13);
        myList.insert(88, 88);
        cout << myList << endl;
    
        myList.pop_back();
        myList.pop_front();
        cout << myList << endl;
    
        for (int i = 0; i < 5; ++i)
        {
            if (myList.search(i))
                cout << i << ": Have found!" << endl;
            else
                cout << i << ": Not in the list!" << endl;
        }
    
        cout << "Test remove..." << endl;
        cout << myList << endl;
        int value;
        while (cin >> value)
        {
            try
            {
                myList.remove(value);
            }
            catch (const std::exception &e)
            {
                cerr << e.what() << endl;
            }
    
            cout << myList << endl;
            if (myList.isEmpty())
            {
                cout << "empty" << endl;
            }
            else
            {
                cout << "not empty" << endl;
            }
        }
    
        return 0;
    }

  • 相关阅读:
    SELECT SCREEN 整理2 转载
    SELECT SCREEN 整理1 转载
    ABAP面向对象 转载
    [OO]ABAP OO 语法--实例看 "="与"?=" 的区别[转]
    cl_salv_table
    sapui5 组件重用
    sapui5 使用common(其他工程)的i18n 文件
    sapui5 app之间迁移
    导航与路由10-17(渣翻完结)
    导航与路由1-9 (渣翻)
  • 原文地址:https://www.cnblogs.com/itrena/p/5926994.html
Copyright © 2011-2022 走看看