STL之雙向鏈表及其迭代器簡單實現

最近在看STL,試着寫一個自己的鏈表模板,與STL相比沒有使用空間配置器,方法也只實現了幾個簡單的插入刪除元素。但是理清了容器、迭代器之間的關係。代碼及測試用例如下。

list_test.h文件
# ifndef LIST_TEST
# define LIST_TEST

#include<iostream>

template <typename T>
class listnode
{
    public:
    listnode<T>* prev;
    listnode<T>* next;
    T data;
};

template <typename T>
class list_iterator
{
    typedef listnode<T>* link_type;
    public:
        listnode<T>* node;
        list_iterator()
        {
            node = NULL;
        }
        list_iterator(link_type n)
        {
            node = n;
        }
        bool operator==(const list_iterator& x) const
        {
            return node == x.node;
        }
        bool operator!=(const list_iterator& x)const
        {
            return node != x.node;
        }
        T operator*() const
        {
            return node->data;
        }
        list_iterator operator++()
        {
            node = node->next;
            return *this;
        }
        list_iterator operator++(int)
        {
            list_iterator tmp=*this;
            ++*this;
            return tmp;
        }
        list_iterator operator--()
        {
            node = node->prev;
            return *this;
        }
        list_iterator operator--(int)
        {
            list_iterator tmp = *this;
            --*this;
            return tmp;
        }
};

template <typename T>
class list_test
{
    typedef listnode<T> list_node;
    typedef listnode<T>* link_type;
    typedef list_iterator<T> iterator;
    public:
        link_type head;
        link_type get_node()
        {
            return new list_node();
        }
        list_test()
        {
            head = get_node();
            head->next = head;
            head->prev = head;
        }
        list_test(const list_test& source)
        {
            this->head = get_node();           //此處三行不可以直接調用構造函數
            this->head->next = head;
            this->head->prev = head;
            link_type tmp = source.head->prev;
            while (tmp != source.head)
            {
                this->put_front(tmp->data);
                tmp = tmp->prev;
            }
        }
        ~list_test()
        {
            link_type tmp1 = head;
            link_type tmp2 = head->prev;
            while (tmp2 != head)
            {
                tmp1 = tmp2->prev;
                delete tmp2;
                tmp2 = tmp1;
            }
            delete head;
            head = NULL;
        }

        iterator insert(iterator pos,const T value)
        {
            link_type temp = get_node();
            temp->data = value;
            temp->next = pos.node;
            temp->prev = pos.node->prev;
            pos.node->prev->next = temp;
            pos.node->prev = temp;
            return temp;
        }

        iterator put_back(const T value)
        {
            iterator temp = this->insert(head, value);
            return temp;
        }
        iterator put_front(const T value)
        {
            iterator temp = this->insert(head->next, value);
            return temp;
        }

        iterator begin()
        {
            return head->next;
        }
        iterator end()
        {
            return head;
        }
        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;
            delete position.node;
            return iterator(next_node);
        }

};

# endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "list_test.h"
using namespace std;
int main(int argv, char** argc)
{
    list_test < int > test ;
    for (int n = 0; n < 5; ++n)
    {
        test.put_front(n);                       //方法測試
    }
    for (auto i = test.begin(); i != test.end();i++)
    {
        cout << *i << " ";
    }
    cout << endl;

    list_test < int > *test1 = new list_test < int >();            
    for (int n = 0; n < 5; ++n)
    {
        test1->put_front(n);
    }
    for (auto i = test1->begin(); i != test1->end(); i++)
    {
        cout << *i << " ";
    }
    cout << endl;
    delete test1;                      //析構函數測試

    list_test < int > test2(test);     //拷貝複製函數測試
    test2.erase(++test2.begin());      //方法測試
    test2.put_back(-1);                //方法測試
    test2.put_front(5);                //方法測試
    for (auto i = test2.begin(); i != test2.end(); i++)
    {
        cout << *i << " ";
    }
    cout << endl;
}

測試結果如下圖這裏寫圖片描述

另外給出析構函數的測試截圖
執行析構函數前,test1所指鏈表的head指向0x00319288內存單元
這裏寫圖片描述
執行析構指令後head被複位爲0xfeee,但test1存在與棧上,仍然存在,此時test1便成爲野指針。
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章