单向循环链表(建表、插入、删除、输出)

这个写法部分参考计蒜客,目前正在学习该网站的数据结构课程。
其实,这个写法看得很变扭,我适当的改了一下,感觉还是很变扭,莫非是我改变扭了?。。。

这里用插入函数来完成建表,所以插入函数既可以在建表时使用,也可以在建表完成后再进行插入时使用。

删节点的函数既可以删除整个表,也可以删除某个节点。
(Ps:这里由于函数有两个用途,所以在删除第一个节点时需要判断,判断删除第一个节点后是否还有节点,如果表已经剩下第一个节点了,注意将tail置为NULL,方便输出判断。如果删除第一个结点后还有节点,则进行相应的操作)

特别需要注意删除最后一个节点时尾指针需要更新

#include <iostream>
#include <stdlib.h>

using namespace std;

class Node
{
public:
    int data;
    Node *next;
public:
    Node(int _data){
        data = _data;
        next = NULL;
    }
};

class LinkList
{
private:
    Node *tail;
public:
    LinkList(){
        tail = NULL;
    }

    /*注index的含义,这里将链表下标看成从1开始*/
    /*默认输入的n合法*/
    void insertNode(Node *node, int index){

        /*当前链表为空,则将插进来的节点作为头节点,并且将它的指针指向自己,形成循环*/
        if(tail==NULL){
            tail = node;
            tail->next = tail;
            //cout<<"if(tail==NULL)"<<endl;
            return;
        }


        /*建表成功后的额外插入到链表首位置的判断语句*/
        /*tail->next表示第一个节点,那么node->next = tail->next则将node插到表头之前,形成新的表头*/
        /*tail为最后一个节点,表头更新了,所以tail->next=node*/
        if(index==1){
            node->next = tail->next;
            tail->next = node;
            return;
        }


        int tot = 1;
        Node *currentNode = tail->next;
        /*curentNode代表头结点*/

        /*注意判断条件*/
        while(currentNode != tail && tot < index-1){
            currentNode = currentNode->next;
            tot++;
        }


        /*理解currentNode代表的值*/
        if(tot == index-1){
            node->next = currentNode->next;
            currentNode->next = node;
            //cout<<"if(tot==index-1):"<<endl;
        }


        /*将node插入到当前链表末尾时,将进行这个判断*/
        /*判断时,tail还没更新,代表倒数第二个节点,而node代表最后一个节点*/
        if(node == tail->next){
            tail = node;
            //cout<<"if(node==tail->next)"<<endl;
        }
    }


    void deleteNode(int index){
        int tot = 1;
        Node *currentNode, *NodeOfDelete;

        if(tail==NULL){
            //cout<<"链表已空!!!"<<endl;
            return;
        }

        /*链表长度等于1*/
        if(index==1 && (tail->next)==tail) {
            NodeOfDelete = tail;
            delete NodeOfDelete;
            tail = NULL;
            return;
        }

        /*链表长度大于等于2*/
        if(index==1 && (tail->next->next)!=NULL ) {
            NodeOfDelete = tail->next;
            tail->next = NodeOfDelete->next;
            delete NodeOfDelete;
            return;
        }

        currentNode = tail->next;
        while(currentNode != tail && tot<index-1){
            currentNode = currentNode->next;
            tot++;
        }

        /*得在删除最后一个节点前更新tail*/
        if(currentNode->next == tail)
            tail = currentNode;

        /*包含尾节点删除*/
        if(tot==index-1){
            NodeOfDelete = currentNode->next;
            currentNode->next = NodeOfDelete->next;
            delete NodeOfDelete;
        }


    }

    void outputList(){
        int tot = 1;
        if(tail==NULL){
            cout<<"链表已空!!!"<<endl;
            return;
        }

        Node *currentNode = tail->next;
        while(currentNode != tail){
            cout<<currentNode->data<<" ";
            currentNode = currentNode->next;
        }
        /*尾节点由于循环条件影响需要额输出*/
        cout<<currentNode->data<<endl;
        cout<<"-------------分割线-------------------\n\n\n";
    }
};

int main()
{
    int n;
    while(cin>>n){
        LinkList linklist;
        for(int i=1; i<=n; i++){
            Node *node = new Node(i);
            linklist.insertNode(node, i);
        }

        linklist.outputList();


        /*下面的试验n的大小有限制*/
        cout<<"删除第一个节点:"<<endl;
        linklist.deleteNode(1);
        linklist.outputList();

        cout<<"删除第3个节点:"<<endl;
        linklist.deleteNode(3);
        linklist.outputList();

        cout<<"删除最后一个节点:"<<endl;
        linklist.deleteNode(n-2);
        linklist.outputList();

        cout<<"删除列表并且额外删除两次看看如何:"<<endl;
        for(int i=0; i<n;i++){
            linklist.deleteNode(1);
            linklist.outputList();
        }

        system("pause");
    }

    return 0;
}

如果有错误的话欢迎指出,谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值