4.2.2 算法之美--单链表实现

按照书上的要求实现了一下单链表;单链表的实现可能以前看过几次了;现在想想最主要的几个操作算法应该能够写了吧;遇到的问题:

1. 链表节点写成private;所已给出了访问的接口;

2.模板类的.h和.cpp实现写在同一个文件;

3.感觉以后的数据结构实现还是用纯c的实现好一些;然后书主要是思路

节点类:

#ifndef SINGLELIST_LISTNODE_H_
#define SINGLELIST_LISTNODE_H_

template <class T>
class ListNode
{
public: //定义为private时,所以在会用到访问
    T data;
    ListNode<T> * pNext;
public:
    ListNode() : pNext(nullptr){}
    ListNode(T value_) :data(value_), pNext(nullptr){}
    ~ListNode(){}

    void SetpNext(ListNode<T>* next_);
    void SetData(T value_);
    ListNode<T>* GetpNext();
    T& GetData();
};

template <class T>
void ListNode<T>::SetpNext(ListNode<T>* next_)
{
    pNext = next_;
}

template<class T>
void ListNode<T>::SetData(T value_)
{
    data = value_;
}

template<class T>
ListNode<T>* ListNode<T>::GetpNext()
{
    return pNext;
}

template<class T>
T& ListNode<T>::GetData()
{
    return data;
}

#endif

链表类:

#ifndef  SINGLELIST_SINGLELIST_H_
#define  SINGLELIST_SINGLELIST_H_

#include "ListNode.h"

template<class T>
class SingleList
{
private:
    ListNode<T>* head;
    ListNode<T>* tail;
public:
    SingleList();
    ~SingleList();

    bool AddTail(T value_);
    bool RemoveTail();
    bool InsertAt(int index_, T value_);
    bool RemoveAt(int index_);

    T& GetAt(int index_);
    bool IsEmpty();
    int GetCount();
    void RemoveAll();

    ListNode<T>* GetHead();
    ListNode<T>* GetTail();
    ListNode<T>* GetNodeAt(int index_);
    ListNode<T>* GetCur();
    ListNode<T>* TowardCur();

};

template<class T>
bool SingleList<T>::AddTail(T value_)
{
    ListNode<T>* pointer = new ListNode<T>(value_);
    tail->SetpNext(pointer);
    tail = tail->pNext;
    tail->pNext = nullptr;
    if (tail != nullptr)
    {
        return true;
    }
    else
    {
        return false;
    }
}

template<class T>
//在索引值指向的节点前插入新节点
bool SingleList<T>::InsertAt(int index_, T value_)
{
    if (index_ > this->GetCount() || index_ < 0)
    {
        cerr << "A wrong position!\n";
        return false;
    }

    ListNode<T>* current = head;
    while (index_)
    {
        current = current->pNext;
        index_--;
    }
    ListNode<T>* add = new ListNode<T>(value_);
    add->pNext = current->pNext;
    current->pNext = add;

    if (current != nullptr)
    {
        return true;
    }
    else
    {
        return false;
    }
}

template<class T>
bool SingleList<T>::RemoveTail()
{
    return RemoveAt(this->GetCount() - 1);
}

template<class T>
bool SingleList<T>::RemoveAt(int index_)
{
    if (index_ > this->GetCount() || index_ < 0)
    {
        cerr << "A wrong position!\n";
        return false;
    }
    ListNode<T>* current = head;
    while (index_ - 1)
    {
        current = current->pNext;
        index_--;
    }
    ListNode<T>* deletePoint = current->pNext;

    if (current->pNext->pNext == nullptr)
    {
        current->pNext = nullptr;
    }
    else
        current->pNext = current->pNext->pNext;
    delete deletePoint;
    return true;
}

template<class T>
SingleList<T>::SingleList()
{
    head = new ListNode<T>();
    tail = head;
    tail->pNext = NULL;
}

template<class T>
SingleList<T>::~SingleList()
{
    RemoveAll();
    delete head;
}

template<class T>
T& SingleList<T>::GetAt(int index_)
{
    if (index_ > GetCount() || index_ < 0)
    {
        cerr << "A wrong position!\n";
    }
    ListNode<T>* cur;
    cur = head->pNext;
    while (index_)
    {
        cur = cur->pNext;
        index_--;
    }
    return cur->GetData();
}

template<class T>
bool SingleList<T>::IsEmpty()
{
    return head->pNext == NULL;
}

template<class T>
int SingleList<T>::GetCount()
{
    int count = 0;
    ListNode<T>* cur = head->pNext;
    while (cur != nullptr)
    {
        cur = cur->pNext;
        count++;
    }
    return count;
}

template<class T>
void SingleList<T>::RemoveAll()
{
    ListNode<T>* cur;
    while (head->pNext != nullptr)
    {
        cur = head->pNext;
        head->pNext = cur->pNext;
        delete cur;
    }
    tail = head;
}

template<class T>
ListNode<T> * SingleList<T>::GetNodeAt(int index_)
{
    if (index_ > this->GetCount() - 1 || index_ < 0)
    {
        cerr << "A wrong position!\n";
    }
    ListNode<T>* handle = head->pNext;
    while (index_)
    {
        handle = handle->pNext;
        index_--;
    }
    return handle;
}

template <class T>
ListNode<T>* SingleList<T>::GetHead(){//返回头指针
    return head;
}

template <class T>
ListNode<T>* SingleList<T>::GetTail(){//返回尾指针
    return tail;
}

template <class T>
ListNode<T>* SingleList<T>::GetCur(){
    return cur;
}

template <class T>
ListNode<T>* SingleList<T>::TowardCur(){
    cur = cur->GetLink();
    return cur
}

#endif

测试函数:

#include <iostream>
#include "SingleList.h"  

using namespace std;

int main()
{
    SingleList<int> list;
    for (int i = 0; i < 9; i++)
        list.AddTail(i);

    cout << list.GetCount() << endl;

    cout << list.GetAt(3) << endl;

    list.RemoveAt(3);

    cout << list.GetCount() << endl;
    cout << list.GetAt(3) << endl;

    list.RemoveAll();
    cout << list.GetCount() << endl;

    system("PAUSE");
    return 0;
}

结果:

后续用纯c实现链表的基本操作:创建,增,删,改,查。

时间: 2024-10-13 00:54:35

4.2.2 算法之美--单链表实现的相关文章

009实现一个算法来删除单链表中的一个结点,只给出指向那个结点的指针(keep it up)

呵呵,这个题不能直接删除已知的结点,因为是单链表,不知道前驱,只知道 后继结点,直接删除会使链表断开.不过我们可以删除已知结点的后继结点, 把后继结点的值赋值给已知结点. #include <iostream> struct Node { int data; Node* next; }; bool removeNode(Node* vNode) { if (vNode == NULL || vNode->next == NULL) return false; Node* pNext =

实现一个算法从一个单链表中返回倒数第n个元素(keep it up)

我们维护两个指针, 它们之间的距离为n.然后,我将这两个指针同步地在这个单链表上移动,保持它们的距离 为n不变.那么, 当第二个指针指到空时,第一个指针即为所求. #include <iostream> struct Node { int data; Node* next; }; void initList(Node* vNode) { for (int i=0; i < 20; ++i) { Node* TempNode = new Node; TempNode->data =

cc150:实现一个算法来删除单链表中间的一个结点,只给出指向那个结点的指针

实现一个算法来删除单链表中间的一个结点,只给出指向那个结点的指针. 例子: 输入:指向链表a->b->c->d->e中结点c的指针 结果:不需要返回什么,得到一个新链表:a->b->d->e 解答 这个问题的关键是你只有一个指向要删除结点的指针,如果直接删除它,这条链表就断了. 但你又没办法得到该结点之前结点的指针,是的,它连头结点也不提供.在这种情况下, 你只能另觅他径.重新审视一下这个问题,我们只能获得从c结点开始后的指针, 如果让你删除c结点后的某个结点,那

cc150:实现一个算法来删除单链表中间的一个结点,仅仅给出指向那个结点的指针

实现一个算法来删除单链表中间的一个结点,仅仅给出指向那个结点的指针. 样例: 输入:指向链表a->b->c->d->e中结点c的指针 结果:不须要返回什么,得到一个新链表:a->b->d->e 解答 这个问题的关键是你仅仅有一个指向要删除结点的指针,假设直接删除它,这条链表就断了. 但你又没办法得到该结点之前结点的指针,是的,它连头结点也不提供.在这样的情况下, 你仅仅能另觅他径.又一次审视一下这个问题,我们仅仅能获得从c结点開始后的指针, 假设让你删除c结点后的

数据结构之自建算法库——循环单链表

本文针对数据结构基础系列网络课程(2):线性表中第13课时双链表. 按照"0207将算法变程序"[视频]部分建议的方法,建设自己的专业基础设施算法库. 双链表算法库算法库采用程序的多文件组织形式,包括两个文件: 1.头文件:clinklist.h,包含定义双链表数据结构的代码.宏定义.要实现算法的函数的声明: #ifndef CLINKLIST_H_INCLUDED #define CLINKLIST_H_INCLUDED //循环单链表基本运算函数 typedef int ElemT

常见算法题:单链表二路归并

题目:现有两个递增的单链表L1和L2,设计一个算法将L1与L2的所有结点归并到递增的单链表L3中.要求:空间复杂度为O(1). 思路:本题可采用二路归并思路,但题目要求空间复杂度为O(1),因此不能复制结点,只能破坏L1和L2将结点插入到L3中. 代码: void Merge(LinkList &L1,LinkList &L2,LinkList &L3) { LinkList *p=L1.head->next, *q=L2.head->next; LinkList *p

算法初探001——单链表反转

单链表的反转问题是一道很基本的问题.题目如下: 有一个单链表 1 ->2->3->4->5->6 反转后链表为:6->5->4->3->2->1. 方法一 解析:可以使用三个指针pre ,temp,next对逐个节点进行反转.详细流程如下: (4) 初始状态 pre = head; tmp = head->next; pre->next = null; (2)第一次循环: next = tmp->next; tmp->ne

008实现一个算法从一个单链表中返回倒数第n个元素(keep it up)

我们维护两个指针, 它们之间的距离为n. 然后.我将这两个指针同步地在这个单链表上移动,保持它们的距离 为n不变. 那么, 当第二个指针指到空时.第一个指针即为所求. #include <iostream> struct Node { int data; Node* next; }; void initList(Node* vNode) { for (int i=0; i < 20; ++i) { Node* TempNode = new Node; TempNode->data

009实现一个算法来删除单链表中的一个结点,仅仅给出指向那个结点的指针(keep it up)

呵呵,这个题不能直接删除已知的结点.由于是单链表,不知道前驱,仅仅知道 后继结点,直接删除会使链表断开.只是我们能够删除已知结点的后继结点, 把后继结点的值赋值给已知结点. #include <iostream> struct Node { int data; Node* next; }; bool removeNode(Node* vNode) { if (vNode == NULL || vNode->next == NULL) return false; Node* pNext =