C++实现自己的STL List 数据结构

原来以为双向链表很简单,
但到了真正自己动手实现一个的时候才发现,
能正确实现双向链表的各种操作,也不是很容易,
指针操作很容易出错。
话不多说,上代码吧:

#pragma once                                                                                                                        
                                                                                                        
#include <cstdio>                                                                                       
#include <cstdlib>                                                                                      
#include <cassert>                                                                                      
#include <utility>                                                                                      
#include <cstddef>              // ptrdiff_t                                                            
#include <iterator>             // std::input_iterator_tag                                              
                                                                                                        
template <typename T>                                                                                   
struct HengList {                                                                                       
    struct Node {                                                                                       
        T val;                                                                                          
        Node *prev;                                                                                     
        Node *next;                                                                                     
    };                                                                                                  
    typedef Node *nPtr;                                                                                 
    struct iterator {                                                                                   
        friend struct HengList<T>;                                                                      
        typedef ptrdiff_t difference_type;                                                              
        typedef T value_type;                                                                           
        typedef const value_type *pointer;                                                              
        typedef const value_type &reference;                                                            
        typedef std::bidirectional_iterator_tag  iterator_category;                                     
                                                                                                        
        iterator() noexcept : np_(nullptr) {}                                                           
        explicit iterator(nPtr np) noexcept : np_(np) {}                                                
                                                                                                        
        reference operator*() const noexcept { return np_->val; }                                       
        pointer operator->() const noexcept { return &np_->val; }                                       
                                                                                                        
        iterator &operator++()                                                                          
        {                                                                                               
            np_ = np_->next;                                                                            
            return *this;                                                                               
        }                                                                                               
        iterator operator++(int)                                                                        
        { // postfix                                                                                    
            iterator temp(*this);                                                                       
            ++*this;                                                                                    
            return temp;                                                                                
        }                                                                                               
        iterator &operator--()                                                                          
        {                                                                                               
            np_ = np_->prev;                                                                            
            return *this;                                                                               
        }                                                                                               
        iterator operator--(int)                                                                        
        { // postfix                                                                                    
            iterator temp(*this);                                                                       
            --*this;                                                                                    
            return temp;                                                                                
        }                                                                                               
        bool operator==(const iterator &rhs) const noexcept                                             
        {                                                                                               
            return np_ == rhs.np_;                                                                      
        }                                                                                               
        bool operator!=(const iterator &rhs) const noexcept                                             
        {                                                                                               
            return !operator==(rhs);                                                                    
        }                                                                                               
    private:                                                                                            
        nPtr get() { return np_; }                                                                      
        nPtr np_;                                                                                       
    };                                                                                                  
                                                                                                        
    HengList() = default;                                                                               
    HengList(std::initializer_list<T> il);                                                              
    HengList(const HengList &) = delete;                                                                
    HengList &operator=(const HengList &) = delete;                                                     
    ~HengList() { clearup(); }                                                                          
                                                                                                        
    void push_back(const T &val);
                                                                                                                                        
    void pop_back();                                                                                
    void pop_front();                                                                               
                                                                                                    
    iterator find(const T &val);                                                                    
    iterator insert(iterator position, const T &val);                                               
                                                                                                    
    void remove(const T &val);                                                                      
    iterator erase(iterator position);                                                              
                                                                                                    
    iterator begin() { return iterator(head_); }                                                    
    iterator end() { return iterator(); }                                                           
                                                                                                    
    size_t size() { return length_; }                                                               
                                                                                                    
private:                                                                                            
    void clearup();                                                                                 
                                                                                                    
    size_t length_ = 0;                                                                             
    nPtr head_ = nullptr;                                                                           
    nPtr tail_ = nullptr;                                                                           
};                                                                                                  
                                                                                                    
template<typename T>                                                                                
void HengList<T>::clearup()                                                                         
{                                                                                                   
    for (auto it = begin(), tmp = it; it != end(); tmp = it) {                                      
        ++it;                                                                                       
        free(tmp.get());                                                                            
    }                                                                                               
}                                                                                                   
                                                                                                    
template<typename T> HengList<T>::HengList(std::initializer_list<T> il)                             
{                                                                                                   
    for (auto it = il.begin(); it != il.end(); ++it) {                                              
        push_back(*it);                                                                             
    }                                                                                               
}                                                                                                   
                                                                                                    
template<typename T>                                                                                
void HengList<T>::push_back(const T &val)                                                           
{                                                                                                   
    nPtr raw = static_cast<nPtr>(calloc(1, sizeof(Node)));                                          
    assert(raw);                                                                                    
    ++length_;                                                                                      
    raw->val = val;                                                                                 
    raw->prev = tail_;                                                                              
    if (tail_) {                                                                                    
        tail_->next = raw;                                                                          
    }                                                                                               
    if (!head_) {                                                                                   
        head_ = raw;                                                                                
    }                                                                                               
    tail_ = raw;                                                                                    
    return;                                                                                         
}                                                                                                   
                                                                                                    
template<typename T>                                                                                
void HengList<T>::push_front(const T &val)                                                          
{                                                                                                   
    nPtr raw = static_cast<nPtr>(calloc(1, sizeof(Node)));                                          
    assert(raw);                                                                                    
    ++length_;                                                                                      
    raw->val = val;                                                                                 
    raw->next = head_;                                                                              
    if (head_) {                                                                                    
        head_->prev = raw;                                                                          
    }                                                                                               
    if (!tail_) {                                                                                   
        tail_ = raw;                                                                                
    }                                                                                               
    head_ = raw; 
    return;                                                                                                                         
}                                                                                                                                   
                                                                                                                                    
template<typename T>                                                                                                                
void HengList<T>::pop_back()                                                                                                        
{                                                                                                                                   
    if (!tail_) { return; }                                                                                                         
    nPtr prev = tail_->prev;                                                                                                        
    free(tail_);                                                                                                                    
    if (prev) {                                                                                                                     
        prev->next = nullptr;                                                                                                       
    } else {                                                                                                                        
        head_ = nullptr;                                                                                                            
    }                                                                                                                               
    tail_ = prev;                                                                                                                   
    --length_;                                                                                                                      
}                                                                                                                                   
                                                                                                                                    
template<typename T>                                                                                                                
void HengList<T>::pop_front()                                                                                                       
{                                                                                                                                   
    if (!head_) { return; }                                                                                                         
    nPtr next = head_->next;                                                                                                        
    free(head_);                                                                                                                    
    if (next) {                                                                                                                     
        next->prev = nullptr;                                                                                                       
    } else {                                                                                                                        
        tail_ = nullptr;                                                                                                            
    }                                                                                                                               
    head_ = next;                                                                                                                   
    --length_;                                                                                                                      
}                                                                                                                                   
                                                                                                                                    
                                                                                                                                    
template<typename T>                                                                                                                
typename HengList<T>::iterator HengList<T>::find(const T &val)                                                                      
{                                                                                                                                   
    for (auto it = begin(); it != end(); ++it) {                                                                                    
        if (*it == val) { return it; }                                                                                              
    }                                                                                                                               
    return end();                                                                                                                   
}                                                                                                                                   
                                                                                                                                    
template<typename T>                                                                                                                
typename HengList<T>::iterator HengList<T>::insert(iterator position, const T &val)                                                 
{                                                                                                                                   
    nPtr curr = position.get();                                                                                                     
    if (!curr) {                                                                                                                    
        push_back(val);                                                                                                             
        return iterator(tail_);                                                                                                     
    }                                                                                                                               
    nPtr prev = curr->prev;                                                                                                         
    if (!prev) {                                                                                                                    
        push_front(val);                                                                                                            
        return begin();                                                                                                             
    }                                                                                                                               
                                                                                                                                    
    nPtr raw = static_cast<nPtr>(calloc(1, sizeof(Node)));                                                                          
    assert(raw);                                                                                                                    
    ++length_;                                                                                                                      
    raw->val = val;                                                                                                                 
                                                                                                                                    
    raw->next = curr;                                                                                                               
    curr->prev = raw;                                                                                                               
                                                                                                                                    
    prev->next = raw;                                                                                                               
    raw->prev = prev;                                                                                                               
    return iterator(raw);                                                                                                           
}                                                                                                                                   
                                                                                                                                    
template<typename T>
void HengList<T>::remove(const T &val)                                                              
{                                                                                                   
    for (auto it = begin(); it != end(); ++it) {                                                    
        if (*it == val) { erase(it); }                                                              
    }                                                                                               
}                                                                                                   
                                                                                                    
template<typename T>                                                                                
typename HengList<T>::iterator HengList<T>::erase(iterator position)                                
{                                                                                                   
    nPtr curr = position.get();                                                                     
    if (!curr) { return end(); }                                                                    
    if (curr == head_) {                                                                            
        pop_front();                                                                                
        return begin();                                                                             
    }                                                                                               
    if (curr == tail_) {                                                                            
        pop_back();                                                                                 
        return end();                                                                               
    }                                                                                               
                                                                                                    
    nPtr next = curr->next;                                                                         
    curr->prev->next = next;                                                                        
    next->prev = curr->prev;                                                                        
    free(curr);                                                                                     
    --length_;                                                                                      
    return iterator(next);                                                                          
} 

测试代码:

#include "HengList.h"                                                                                                               
#include <cstdlib>                                                                                  
#include <cstdio>                                                                                   
                                                                                                    
void test_push(int argc, char *argv[])                                                              
{                                                                                                   
    HengList<int> li;                                                                               
    for (int i = 1; i < argc; ++i) {                                                                
        li.push_back(atoi(argv[i]));                                                                
    }                                                                                               
    for (int i = 1; i < argc; ++i) {                                                                                                
        li.push_front(atoi(argv[i]));                                                                                               
    }                                                                                                                               
                                                                                                                                    
    printf("size: %u\n", li.size());                                                                                                
    for (HengList<int>::iterator it = li.begin(); it != li.end(); ++it) {                                                           
        printf("%d ", *it);                                                                                                         
    }                                                                                                                               
    printf("\n");                                                                                                                   
}                                                                                                                                   
                                                                                                                                    
void test_init()                                                                                                                    
{                                                                                                                                   
    HengList<int> li {10, 20, 30, 40};                                                                                              
                                                                                                                                    
    printf("size: %u\n", li.size());                                                                                                
    for (HengList<int>::iterator it = li.begin(); it != li.end(); ++it) {                                                           
        printf("%d ", *it);                                                                                                         
    }                                                                                               
    printf("\n");                                                                                   
}                                                                                                   
                                                                                                    
void test_pop(int argc, char *argv[])                                                               
{                                                                                                   
    HengList<int> li;                                                                               
    for (int i = 1; i < argc; ++i) {                                                                
        li.push_back(atoi(argv[i]));                                                                
    }                                                                                               
                                                                                                    
    printf("before pop size: %u\n", li.size());                                                     
    for (HengList<int>::iterator it = li.begin(); it != li.end(); ++it) {                           
        printf("%d ", *it);                                                                         
    }                                                                                               
    printf("\n");                                                                                   
                                                                                                    
    li.pop_front();                                                                                 
    li.pop_back();                                                                                  
                                                                                                    
    printf("after pop size: %u\n", li.size());                                                      
    for (HengList<int>::iterator it = li.begin(); it != li.end(); ++it) {                           
        printf("%d ", *it);                                                                         
    }                                                                                               
    printf("\n");                                                                                   
}  

void test_find(int argc, char *argv[])                                                              
{                                                                                                   
    HengList<int> li;                                                                               
    for (int i = 1; i < argc - 1; ++i) {                                                            
        li.push_back(atoi(argv[i]));                                                                
    }                                                                                               
    printf("size: %u\n", li.size());                                                                
    for (HengList<int>::iterator it = li.begin(); it != li.end(); ++it) {                           
        printf("%d ", *it);                                                                         
    }                                                                                               
    printf("\n");                                                                                                                   
                                                                                                                                    
    auto it = li.find(atoi(argv[argc - 1]));                                                                                        
    if (it != li.end()) {                                                                                                           
        printf("found: %d\n", *it);                                                                                                 
    } else {                                                                                                                        
        printf("not found: %s\n", argv[argc - 1]);                                                                                  
    }                                                                                                                               
}                                                                                                   
                                                                                                    
void test_insert(int argc, char *argv[])                                                            
{                                                                                                   
    HengList<int> li;                                                                               
    for (int i = 1; i < argc - 1; ++i) {                                                            
        li.push_back(atoi(argv[i]));                                                                
    }                                                                                               
    printf("size: %u\n", li.size());                                                                
    for (HengList<int>::iterator it = li.begin(); it != li.end(); ++it) {                           
        printf("%d ", *it);                                                                         
    }                                                                                               
    printf("\n");                                                                                   
                                                                                                    
    li.insert(li.begin(), atoi(argv[argc - 1]));                                                    
    li.insert(++++li.begin(), atoi(argv[argc - 1]));                                                
    auto it = li.insert(li.end(), atoi(argv[argc - 1]));                                            
    printf("%d\n", *it);                                                                            
    printf("after insert size: %u\n", li.size());                                                   
    for (HengList<int>::iterator it = li.begin(); it != li.end(); ++it) {                           
        printf("%d ", *it);                                                                         
    }                                                                                               
    printf("\n");                                                                                   
}                                                                                                   
                                                                                                    
void test_remove(int argc, char *argv[])                                                            
{                                                                                                   
    HengList<int> li;                                                                               
    for (int i = 1; i < argc - 1; ++i) {                                                            
        li.push_back(atoi(argv[i]));                                                                
    }                                                                                               
    printf("size: %u\n", li.size());                                                                
    for (HengList<int>::iterator it = li.begin(); it != li.end(); ++it) {                           
        printf("%d ", *it);                                                                         
    }                                                                                               
    printf("\n");                                                                                   
                                                                                                    
    li.remove(atoi(argv[argc - 1]));                                                                
    //li.insert(++++li.begin(), atoi(argv[argc-1]));                                                
    //auto it = li.insert(li.end(), atoi(argv[argc-1]));                                            
    //printf("*it: %d\n", *it);                                                                     
    printf("after insert size: %u\n", li.size());                                                   
    for (HengList<int>::iterator it = li.begin(); it != li.end(); ++it) {                           
        printf("%d ", *it);                                                                         
    }                                                                                               
    printf("\n");                                                                                   
} 
                                                                                                    
void test_for()                                                                                     
{                                                                                                   
    HengList<int> li {10, 20, 30, 40};                                                              
                                                                                                    
    printf("size: %u\n", li.size());                                                                
    for (auto &&v : li) {                                                                           
        printf("%d ", v);                                                                           
    }                                                                                               
    printf("\n");                                                                                   
}                                                                                                   
                                                                                                    
void test_object()                                                                                  
{                                                                                                   
    struct obj {                                                                                    
        int i;                                                                                      
        double d;                                                                                   
    };                                                                                              
                                                                                                    
    obj o1 {10, 10.0};                                                                              
    obj o2 {20, 20.0};                                                                              
    obj o3 {30, 30.0};                                                                              
    obj o4 {40, 40.0};                                                                              
    HengList<obj> li {o1, o2, o3, o4};                                                              
                                                                                                    
    printf("size: %u\n", li.size());                                                                
    for (auto &&v : li) {                                                                           
        printf("%d, %f ", v.i, v.d);                                                                
    }                                                                                               
    printf("\n");                                                                                   
}                                                                                                   
                                                                                                    
int main(int argc, char *argv[])                                                                    
{                                                                                                   
    //test_push(argc, argv);                                                                        
    //test_init();                                                                                  
    //test_pop(argc, argv);                                                                         
    //test_find(argc, argv);                                                                        
    //test_insert(argc, argv);                                                                      
    //test_remove(argc, argv);                                                                      
    //test_for();                                                                                   
    test_object();                                                                                  
}        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值