C++ 手动实现单向循环链表(课后作业版)

单向循环链表,并实现增删查改等功能

首先定义节点类,类成员包含当前节点的值, 指向下一个节点的指针

循环链表的尾节点指向头节点

节点定义:

//node definition
template <typename T>
class Node {
public:
    T value;
    Node<T>* next;

    Node() {}
    Node(const T& value) {
        this->value = value;
        next = nullptr;
    }
    Node(const T& value, const Node<T>& next) {
        this->value = value;
        this->next = next;
    }
};

然后是链表类的定义,主要包含了增删查改等功能

//LinkList_cycle definition
template <typename T>
class LinkList_cycle {
public:
    Node<T>* headnode;

    LinkList_cycle();
    LinkList_cycle(const T* arr, int len);  //array initial
    LinkList_cycle(const LinkList_cycle<T>& link);
    ~LinkList_cycle();
    LinkList_cycle<T>& push_back(T n);
    LinkList_cycle<T>& push_front(T n);
    LinkList_cycle<T>& insert(int pos, int n, T* arr);
    LinkList_cycle<T>& pop_front();
    LinkList_cycle<T>& pop_back();
    LinkList_cycle<T>& remove(int pos, int num);
    LinkList_cycle<T>& reverse();
    T& operator[](int n);
    T& at(int n);
    LinkList_cycle<T>& replace(int pos, int n, T* arr);
    int getLen() {return len;}
    void clear() {this->~LinkList_cycle();}
    void display();
private:
    int len = 0;
    Node<T>* getNode(int n);

};

各个函数解释:

LinkList_cycle();      默认构造函数

LinkList_cycle(const T* arr, int len);      一般构造函数

LinkList_cycle(const LinkList_cycle<T>& link)           拷贝构造函数

~LinkList_cycle();     析构函数

LinkList_cycle<T>& push_back(T n);    在尾部添加一个元素

LinkList_cycle<T>& push_front(T n);     在头部添加一个元素

LinkList_cycle<T>& insert(int pos, int n, T* arr);   在pos处插入n个元素

LinkList_cycle<T>& pop_front();    删除第一个节点

LinkList_cycle<T>& pop_back();    删除最后一个节点

LinkList_cycle<T>& remove(int pos, int num);     删除pos开始的num个元素

LinkList_cycle<T>& reverse();     反转链表

T& operator[](int n);     重载[ ]运算符,返回第n个节点的值

T& at(int n);                 与[ ]一样,只不过会检查索引是否越界

LinkList_cycle<T>& replace(int pos, int n, T* arr);    替换n个节点

int getLen() {return len;}     返回长度,因为len是private

void clear() {this->~LinkList_cycle();}    清除链表

void display();    显示链表所有元素

Node<T>* getNode(int n);     返回第n个节点的指针,是private函数,在其他函数中经常用到
 

完整代码:

#include <iostream>
using namespace std;

//node definition
template <typename T>
class Node {
public:
    T value;
    Node<T>* next;

    Node() {}
    Node(const T& value) {
        this->value = value;
        next = nullptr;
    }
    Node(const T& value, const Node<T>& next) {
        this->value = value;
        this->next = next;
    }
};

//LinkList_cycle definition
template <typename T>
class LinkList_cycle {
public:
    Node<T>* headnode;

    LinkList_cycle();
    LinkList_cycle(const T* arr, int len);  //array initial
    LinkList_cycle(const LinkList_cycle<T>& link);
    ~LinkList_cycle();
    LinkList_cycle<T>& push_back(T n);
    LinkList_cycle<T>& push_front(T n);
    LinkList_cycle<T>& insert(int pos, int n, T* arr);
    LinkList_cycle<T>& pop_front();
    LinkList_cycle<T>& pop_back();
    LinkList_cycle<T>& remove(int pos, int num);
    LinkList_cycle<T>& reverse();
    T& operator[](int n);
    T& at(int n);
    LinkList_cycle<T>& replace(int pos, int n, T* arr);
    int getLen() {return len;}
    void clear() {this->~LinkList_cycle();}
    void display();
private:
    int len = 0;
    Node<T>* getNode(int n);

};

//default constructor
template <typename T>
LinkList_cycle<T>::LinkList_cycle() {
    headnode = nullptr;
    len = 0;
}

//normal constructor
template <typename T>
LinkList_cycle<T>::LinkList_cycle(const T* arr, int len) {
    Node<T>* temp = nullptr;
    Node<T>* node = nullptr;
    if ( len < 0 ) {
        cout << "[error]: illegal length of LinkList_cycle" << endl;
        exit(0);
    }
    node = new Node<T>(arr[0]);
    headnode = node;
    temp = node;
    for ( int i = 1; i < len; i++ ) {
        node = nullptr;
        node = new Node<T> (arr[i]);
        temp->next = node;
        temp = temp->next;
    }
    temp->next = headnode;;
    this->len = len;
}

//copy constructor
template <typename T>
LinkList_cycle<T>::LinkList_cycle(const LinkList_cycle<T>& link) {
    this->len = link.getLen();
    this->headnode = link.headnode;
}

//deconstructor
template <typename T>
LinkList_cycle<T>::~LinkList_cycle() {
    if ( headnode == nullptr || len == 0 ) {
        headnode = nullptr;
        len = 0;
        return;
    }
    this->len = 0;
    Node<T>* temp1 = headnode;
    Node<T>* temp2 = headnode;  //保存headnode
    while ( headnode != nullptr ) {
        temp1 = headnode;
        headnode = headnode->next;
        delete temp1;
        if ( headnode == temp2 ) //如果next指向headnode了,说明当前的temp1就是最后一个节点了
            break;
        temp1 = nullptr;
    }
    headnode = nullptr;
}

//display all elements in LinkList_cycle<T>
template <typename T>
void LinkList_cycle<T>::display() {
    if ( this->len == 0 ) {
        cout << "[warning]: can not display empty linkedlist" << endl;
        return;
    }
    Node<T> *node = headnode;
    for ( int i = 0; i < len; i++ ) {
        cout << node->value << " ";
        node = node->next;
    }
    if ( node != headnode ) {
        cout << "[error]: the last node->next do not point to headnode, check again" << endl;
    }
    node = nullptr;
    cout << endl;
}

//add one node at the last position
template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::push_back(T n) {
    Node<T> *node = this->getNode(len-1); //获取指向第len-1个node的指针,即len-2节点的next,所以node就是指向最后节点的指针

    if ( node->next == headnode ) {   //再加一层保护
        Node<T> *temp = new Node<T>(n);  //创建新node
        node->next = temp;           //将最后一个节点的next指向新node
        temp->next = headnode;       //将新node->next指向headnode
        this->len++;
    }
    return *this;
}

//add one node at the first position
template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::push_front(T n) {
    Node<T>* node_new = new Node<T>(n);   //新节点
    Node<T> *node_end = this->getNode(len-1);   //最后节点
    node_new->next = headnode;            //新节点的next指向第一个节点
    node_end->next = node_new;            //最后节点的next指向新节点
    headnode = node_new;                  //再让headnode指向新节点
    this->len++;
    return *this;
}

//insert elements to LinkList_cycle
template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::insert(int pos, int n, T* arr) {
    if ( pos > len-1 || len < 0 ) {
        cout << "[error]: illegal insert position, please check again" << endl;
        exit(0);
    }
    Node<T>* node_N = getNode(len-1); //前半部分
    Node<T>* temp = node_N->next;    //后半部分
    Node<T>* node_new = nullptr;     //新增加的
    for ( int i = 0; i < n; i++ ) {
        node_new = new Node<T> (arr[n-1-i]);
        node_new->next = temp;
        temp = node_new;
        node_new = nullptr;
    }
    node_N->next = temp;
    if ( pos == 0)    //唯有再0处插入的时候,需要改变头节点,其实对pos=0,一直push_front也行
        headnode = temp;
    this->len += n;
    return *this;
}

//delete the first element
template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::pop_front() {
    if ( this->len == 0 ) {
        cout << "[error]: LinkList_cycle don't has any element" << endl;
        exit(0);
    }
    Node<T>* temp = headnode;  //先复制一份headnode
    headnode = headnode->next;  //headnode 前进一步
    delete temp;             //把第一个节点释放掉
    this->len--;
    temp = getNode(len-1);   //获取最后一个节点
    temp->next = headnode;   //把最后一个节点的next指向新的headnode
    return *this;
}

//delete the last element
template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::pop_back() {
    if ( this->len == 0 ) {
        cout << "[error]: LinkList_cycle don't has any element" << endl;
        exit(0);
    }
    Node<T>* temp1 = getNode(len-2);
    Node<T>* temp2 = temp1->next;
    delete temp2;
    temp1->next = headnode;
    this->len--;
    return *this;
}

//get the last node pointer
template <typename T>
Node<T>* LinkList_cycle<T>::getNode(int n) {
    if ( n > len-1 || n < 0) {
        cout << "[warning]: index out of range" <<endl;
    }
    n = n%len;
    if ( n < 0 )
        n = n + len;
    Node<T> *node = headnode;
    for( int i = 0; i < n; i++ ) {
        node = node->next;
    }
    return node;
}

//remove n elements
template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::remove(int pos, int num) {
    if ( pos > len-1 || len < 0 ) {
        cout << "[error]: illegal remove position, please check again" << endl;
        exit(0);
    } else if ( pos + num > len) {
        cout << "[error]: remove index out of range" << endl;
        exit(0);
    }
    Node<T>* node_N = getNode(pos-1);
    Node<T>* node_N_num = getNode(pos+num);
    Node<T>* temp = getNode(pos);
    while ( 1 ) {
        Node<T>* node = temp;
        temp = temp->next;
        if ( temp == node_N_num ) {
            break;
        }
        delete node;
    }
    if ( pos == 0 ) {   //如果从0位置开始删除,要修改头节点
        headnode = node_N_num;
        node_N->next = headnode;
    }
    node_N->next = node_N_num;
    this->len -= num;
    return *this;
}

//reverse LinkList_cycle
template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::reverse() {
    const int num = len;
    T arr[num];
    Node<T>* temp = headnode;
    for ( int i = 0; i < this->len; i++ ) {
        arr[i] = temp->value;
        temp = temp->next;
    }
    temp = headnode;
    for ( int i = 0; i < this->len; i++ ) {
        temp->value = arr[len-i-1];
        temp = temp->next;
    }
    return *this;
}

template <typename T>
T& LinkList_cycle<T>::operator[](int n) {
    return this->getNode(n)->value;
}

template <typename T>
LinkList_cycle<T>& LinkList_cycle<T>::replace(int pos, int n, T* arr) {
    if ( pos > len-1 || len < 0 ) {
        cout << "[error]: illegal remove position, please check again" << endl;
        exit(0);
    } else if ( pos + n > len) {
        cout << "[error]: remove index out of range" << endl;
        exit(0);
    }
    Node<T>* temp = nullptr;
    if ( pos == 0 )
        temp = headnode;
    else
        temp = this->getNode(pos);
    for ( int i = 0; i < n; i++ ) {
        temp->value = arr[i];
        temp = temp->next;
    }
    return *this;
}

int main(){
    int arr[]{1,2,4,5,0};
    LinkList_cycle<int> link(arr, sizeof(arr)/sizeof(int));
    cout << "LinkLint init with arr: " <<endl;
    link.display();
    cout << "push_back:" << endl;
    link.push_back(34);
    link.display();
    cout << "push_front:" << endl;
    link.push_front(10);
    link.display();
    cout << "insert:" << endl;
    link.insert(0,4,arr);
    link.display();
    cout << "pop_front:" << endl;
    link.pop_front();
    link.display();
    cout << "pop_back:" << endl;
    link.pop_back();
    link.display();
    cout << "remove:" << endl;
    link.remove(0,3);
    link.display();
    cout << "[] operator:" << endl;
    cout << link[2] << endl;
    cout << "replace:" << endl;
    int a[] = {6,5,2};
    link.replace(0, sizeof(a)/sizeof(int), a);
    link.display();
    cout << "LinkList_cycle reserve:" << endl;
    link.reverse();
    link.display();
    cout << "clear:" << endl;
    link.clear();
    cout << "len=" << link.getLen() << endl;
    link.display();
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值