6. 帶哨兵的單向循環鏈表

  • 《算法導論》10.2-5 使用單向循環鏈表實現字典操做插入、刪除、查找,並給出運行時間。ios

    單鏈表雖然不能像雙鏈表同樣,實如今任意位置上時間O(1)的插入刪除,可是能夠在預先指定的位置上實現O(1)時間的插入刪除。由於只有該位置的前驅後繼兩個元素會受到影響,只要維護起這兩個元素的信息就夠了。算法

    也由於這一點,當使用鏈表實現棧和隊列的時候,採用單鏈表和雙鏈表的運行時間是同樣的,單鏈表更節省空間。
    ~~~this

    include

    include <string.h>

    template
    class SingleLinkedList
    {
    public:
    SingleLinkedList()
    {
    init();
    }
    SingleLinkedList(const SingleLinkedList& rhs)
    {
    init();
    for(Node* p = rhs.sentinel->next; p != rhs.sentinel; p = p->next)//Error Note: ++p
    push_back(p->object);
    }
    SingleLinkedList(SingleLinkedList&& rhs)
    {
    sentinel = rhs.sentinel;
    sentinelPrev = rhs.sentinelPrev;
    rhs.sentinel = rhs.sentinelPrev = nullptr;
    }
    SingleLinkedList& operator =(const SingleLinkedList& rhs)
    {
    auto copy(rhs);
    std::swap(copy.sentinel, this->sentinel);
    std::swap(copy.sentinelPrev, this->sentinelPrev);
    return this;
    }
    SingleLinkedList& operator =(SingleLinkedList&& rhs)
    {
    std::swap(rhs.sentinel, this->sentinel);
    std::swap(rhs.sentinelPrev, this->sentinelPrev);
    return
    this;
    }
    ~SingleLinkedList()
    {
    if(sentinel)
    {
    while(!empty())
    pop_front();
    delete sentinel;
    sentinel = sentinelPrev = nullptr;
    }
    }
    spa

    //push操做的運行時間都是O(1)
    void push_back(const Object& object)
    {
    Node* pNew = new Node{object, sentinel};
    sentinelPrev->next = pNew;
    sentinelPrev = pNew;
    }code

    void push_back(Object&& object)
    {
    Node* pNew = new Node{std::move(object), sentinel};
    sentinelPrev->next = pNew;
    sentinelPrev = pNew;
    }遞歸

    void push_front(const Object& object)
    {
    Node* pNew = new Node{object, sentinel->next};
    if(empty())
    sentinelPrev = pNew;
    sentinel->next = pNew;
    }隊列

    void push_front(Object&& object)
    {
    Node* pNew = new Node{std::move(object), sentinel->next};
    if(empty())
    sentinelPrev = pNew;
    sentinel->next = pNew;
    }string

    void pop_front()
    {
    if(!empty())
    erase(sentinel);
    }it

    void erase(const Object& object)
    {
    Node* prev = findPrev(object);
    if(prev)
    erase(prev);
    }io

    Object* find(const Object& object) //運行時間O(n)
    {
    Node* prev = findPrev(object);
    if(prev)
    return &(prev->next->object);
    else
    return nullptr;
    }

    const Object* find(const Object &object) const
    {
    const Node* prev = findPrev(object);
    if(prev)
    return &(prev->next->object);
    else
    return nullptr;
    }

    bool empty()const{ return sentinelPrev == sentinel;}

    /《算法導論》10.2-7 給出一個O(n)時間的非遞歸過程,實現對一個含有n個元素的單鏈表的逆轉,要求除存儲鏈表自己所需的空間外,該過程只能使用固定大小的存儲空間/
    void invert()
    {
    Node* prev = sentinel, current = sentinel->next, next = nullptr;
    while(current != sentinel)
    {
    next = current->next;
    current->next = prev;
    prev = current;
    current = next;
    }
    current->next = prev;
    }

private:
struct Node
{
Object object;
Node* next;
};
Node* sentinel;
Node* sentinelPrev;

void init()
{
    sentinel = new Node;
    sentinel->next = sentinelPrev = sentinel;
}

//刪除p的後繼節點, 運行時間O(1)
void erase(Node* p)
{
    auto pDelete = p->next;
    p->next = pDelete->next;
    if(p->next == sentinel)
        sentinelPrev = p;
    delete pDelete; //Error Note: delete p->next;  pDelete should be used
}

const Node* findPrev(const Object& object) const 
{
    for(const Node *prev = sentinel, *current = sentinel->next; current != sentinel; prev = current, current = current->next)
    {
        if(current->object == object)
            return prev;
    }
    return nullptr;//Error Note: forgotten
}
Node* findPrev(const Object& object)
{
    for(Node *prev = sentinel, *current = sentinel->next; current != sentinel; prev = current, current = current->next)
    {
        if(current->object == object)
            return prev;
    }
    return nullptr;
}

};

void testSingleLinkedList()
{
using namespace std;
struct Student
{
const char* name;
int age;
bool operator ==(const Student& rhs) const
{
return 0 == strcmp(name, rhs.name) && age == rhs.age;
}
};
constexpr int NUM = 5;
Student students[NUM] = {Student{"Tom", 12},Student{"Micheal", 13},
Student{"Anna", 14},Student{"Lily", 10},
Student{"James", 19}};
SingleLinkedList sl;
sl.push_back(students[0]);
sl.push_back(students[1]);
sl.push_back(Student{"Anna", 14});
sl.push_front(students[3]);
sl.push_front(students[4]);
Student* tom = sl.find(students[0]);
tom->age = 20;
tom = sl.find(students[0]);
if(tom == nullptr)
cout << "cannot find {Tom, 12}" << endl;
students[0].age = 20;
sl.pop_front();
sl.erase(students[3]);
sl.erase(students[1]);
sl.erase(students[2]);
tom = sl.find(students[0]);
cout << tom->age << endl;
const decltype(sl) sl_copy(sl);
const Student* tom1 = sl_copy.find(students[0]);
cout << tom1->age << endl;
decltype(sl) sl_move(sl);
tom = sl_move.find(students[0]);
cout << tom->age << endl;
sl_move = sl_copy;
tom = sl_move.find(students[0]);
cout << tom->age << endl;
}

/test output: cannot find {Tom, 12} 20 20 20 20/ ~~~

相關文章
相關標籤/搜索