C++ 实现链表(单双循环链表)

单链表

template <typename T>
class LinkedList {
	typedef LinkedList self;
    typedef T          value_type;
    
class Node {
    friend LinkedList;
public:
    template <typename R>
    constexpr Node(const R &value, Node *next) : value_(value), next_(next) {}
    constexpr Node(const value_type &value, Node *next) : value_(value), next_(next) {}
    constexpr Node(const value_type &value) : Node(value, nullptr) {}
    constexpr Node() : value_(), next_(nullptr) {}
    ~Node() { next_ = nullptr; }
private:
    value_type value_;
    Node *next_;
}; // class Node

public:
    LinkedList() : head_(nullptr), tail_(nullptr), size_(0) {}
    ~LinkedList() {
        while (head_) {
            Node *next = head_->next_;
            delete head_;
            head_ = next;
        }
        tail_ = nullptr;
    }

    size_t size() const { return size_; }
    
    value_type &at(size_t index) {
        return const_cast<value_type&>(const_cast<const self*>(this)->at(index));
    }
    
    const value_type &at(size_t index) const {
        if (index < 0 || index >= size_) throw std::out_of_range(
            std::string("LinkedList.at(") +
            std::to_string(index) +
            ") failed as the size is " +
            std::to_string(size_)
        );
        Node *node = head_;
        while (index--) node = node->next_;
        return node->value_;
    }
    
    void add_at_head(const value_type &val) {
        ++size_;
        if (head_) head_ = new Node(val, head_);
        else head_ = tail_ = new Node(val);
    }
    
    void add_at_tail(const value_type &val) {
        ++size_;
        if (tail_) tail_ = tail_->next_ = new Node(val);
        else head_ = tail_ = new Node(val);
    }
    
    void add_by_index(size_t index, const value_type &val) {
        if (index > size_) return;
        if (index <= 0) {
            add_at_head(val);
            return;
        }
        if (index == size_) {
            add_at_tail(val);
            return;
        }
        ++size_;
        Node *node = head_;
        while (--index) node = node->next_;
        node->next_ = new Node(val, node->next_);
    }
    
    void delete_by_index(size_t index) {
        if (index < 0 || index >= size_) return;
        --size_;
        if (size_ == 0) {
            delete head_;
            head_ = tail_ = nullptr;
            return;
        }
        Node *del = head_;
        if (index == 0) head_ = head_->next_;
        else {
            Node *node = head_;
            while (--index) node = node->next_;
            del = node->next_;
            if (del == tail_) tail_ = node;
            node->next_ = del->next_;
        }
        delete del;
    }
private:
    Node *head_, *tail_;
    size_t size_;
};

单循环链表

template <typename T>
class CircularlyLinkedList {
    typedef CircularlyLinkedList self;
    typedef T                    value_type;

class Node {
    friend CircularlyLinkedList;
public:
    template <typename R>
    constexpr Node(const R &value, Node *next) : value_(value), next_(next) {}
    constexpr Node(const value_type &value, Node *next) : value_(value), next_(next) {}
    constexpr Node(const value_type &value) : Node(value, nullptr) {}
    constexpr Node() : value_(), next_(nullptr) {}
    ~Node() { next_ = nullptr; }
private:
    const value_type & value_;
    Node *next_;
}; // class Node

public:
    CircularlyLinkedList() : tail_(nullptr), size_(0) {}
    ~CircularlyLinkedList() { 
        if (tail_) {
            Node *node = tail_->next_;
            while (node != tail_) {
                Node *next = node->next_;
                delete node;
                node = next;
            }
            delete tail_;
            tail_ = nullptr;
        }
    }
    
    size_t size() const { return size_; }
    
    value_type &at(size_t index) {
        return const_cast<value_type&>(const_cast<const self*>(this)->at(index));
    }
    
    const value_type &at(size_t index) const {
        if (index < 0 || index >= size_) throw std::out_of_range(
            std::string("CircularlyLinkedList.at(") +
            std::to_string(index) +
            ") failed as the size is " +
            std::to_string(size_)
        );
        Node *node = tail_->next_;
        while (index--) node = node->next_;
        return node->value_;
    }
    
    void add_head(const value_type &val) {
        ++size_;
        if (tail_) tail_->next_ = new Node(val, tail_->next_);
        else init_head(val);
    }
    
    void add_tail(const value_type &val) {
        ++size_;
        if (tail_) tail_ = tail_->next_ = new Node(val, tail_->next_);
        else init_head(val);
    }
    
    void add_by_index(size_t index, const value_type &val) {
        if (index > size_) return;
        if (index <= 0) {
            add_head(val);
            return;
        }
        if (index == size_) {
            add_tail(val);
            return;
        }
        ++size_;
        Node *node = tail_;
        while (index--) node = node->next_;
        node->next_ = new Node(val, node->next_);
    }
    
    void delete_by_index(size_t index) {
        if (index < 0 || index >= size_) return;
        --size_;
        if (size_ == 0) {
            delete_head();
            return;
        }

        Node *node = tail_;
        while (index--) node = node->next_;

        Node *del = node->next_;
        if (del == tail_) tail_ = node;
        node->next_ = del->next_;
        delete del;
    }
private:
    void init_head(const value_type &val) {
        tail_ = new Node(val);
        tail_->next_ = tail_;
    }
    void delete_head() {
        delete tail_;
        tail_ = nullptr;
    }
    Node *tail_; // tail_->next_ is head_
    size_t size_;
}; // class CircularlyLinkedList

双循环链表

template <typename T>
class CircularlyDoubleLinkedList {
    typedef CircularlyDoubleLinkedList self;
	typedef T                          value_type;

class Node {
    friend CircularlyDoubleLinkedList;
public:
    template <typename R>
    constexpr Node(const R &value, Node *prev, Node *next)
        : value_(value), prev_(prev), next_(next) {}
    constexpr Node(const value_type &value, Node *prev, Node *next)
        : value_(value), prev_(prev), next_(next) {}
    constexpr Node(const value_type &value) : Node(value, nullptr, nullptr) {}
    constexpr Node() : value_(), prev_(nullptr), next_(nullptr) {}
    ~Node() { prev_ = next_ = nullptr; }
private:
    value_type value_;
    Node *prev_, *next_;
}; // class Node

public:
    CircularlyDoubleLinkedList()
        : entry_(new Node), size_(0){ entry_->prev_ = entry_->next_ = entry_; }
    ~CircularlyDoubleLinkedList() {
        Node *node = entry_;
        do {
            Node *next = node->next_;
            delete node;
            node = next;
        } while (node != entry_);
        entry_ = nullptr;
    }

    size_t size() const { return size_; }
    
    value_type &at(size_t index) {
        return const_cast<value_type&>(const_cast<const self*>(this)->at(index));
    }
    
    const value_type &at(size_t index) const {
        if (index < 0 || index >= size_) throw std::out_of_range(
            std::string("CircularlyDoubleLinkedList.at(") +
            std::to_string(index) +
            ") failed as the size is " +
            std::to_string(size_)
        );
        return get_node(index)->value_;
    }
    
    void add_at_head(const value_type &val) {
        ++size_;
        entry_->next_ = entry_->next_->prev_ = new Node(val, entry_, entry_->next_);
    }
    
    void add_at_tail(const value_type &val) {
        ++size_;
        entry_->prev_ = entry_->prev_->next_ = new Node(val, entry_->prev_, entry_);
    }
    
    void add_by_index(size_t index, const value_type &val) {
        if (index > size_) return;
        if (index <= 0) {
            add_at_head(val);
            return;
        }
        if (index == size_) {
            add_at_tail(val);
            return;
        }
        Node *node = get_node(index);
        node->prev_ = node->prev_->next_ = new Node(val, node->prev_, node);
        ++size_;
    }
    
    void delete_by_index(size_t index) {
        if (index < 0 || index >= size_) return;
        Node *del = get_node(index);
        --size_;
        del->prev_->next_ = del->next_;
        del->next_->prev_ = del->prev_;
        delete del;
    }
private:
    Node *get_node(size_t index) const {
        Node *node = entry_;
        if (index > size_ >> 1) {
            index = size_ - index - 1;
            do node = node->prev_; while (index--);
        } else {
            do node = node->next_; while (index--);
        }
        return node;
    }

    Node *entry_;
    size_t size_;
};
posted @ 2022-10-28 11:30  Violeshnv  阅读(25)  评论(0编辑  收藏  举报