6. 带哨兵的单向循环链表

  • 《算法导论》10.2-5 使用单向循环链表实现字典操作插入、删除、查找,并给出运行时间。

    单链表虽然不能像双链表一样,实现在任意位置上时间O(1)的插入删除,但是可以在预先指定的位置上实现O(1)时间的插入删除。因为只有该位置的前驱后继两个元素会受到影响,只要维护起这两个元素的信息就够了。

    也因为这一点,当使用链表实现栈和队列的时候,采用单链表和双链表的运行时间是一样的,单链表更节省空间。
    ~~~

    include

    include

    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;
    }
    }

    //push操作的运行时间都是O(1)
    void push_back(const Object& object)
    {
    Node* pNew = new Node{object, sentinel};
    sentinelPrev->next = pNew;
    sentinelPrev = pNew;
    }

    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;
    }

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

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

    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
/
~~~

转载于:https://www.cnblogs.com/meixiaogua/p/10175608.html

你可能感兴趣的:(数据结构与算法)