C++和数据结构

链表(C++)

2019-11-07  本文已影响0人  眷卿三世

单向链表(C++)

Node节点定义:

class IntSLLNode {
public:
    IntSLLNode() {
        next = 0;
    }

    IntSLLNode(int val, IntSLLNode *in = 0) {
        info = val;
        next = in;
    }

    int info;
    IntSLLNode *next;
};

这里有个地方,带参数的构造函数中的第二个参数是个小细节,在后面管理链表的InSLList类中,addToHead里面,通过这个参数来连接节点,从而使每次new出来的节点都是头节点。

接下来就是构造用来管理链表的管理类,增加头结点,增加尾节点等等功能,这里我们起名为IntSLList,刚才提到过:

#include "IntSLLNode.h"

class IntSLList {
public:
    IntSLList() {
        head = tail = 0;
    }

    ~IntSLList();
    int isEmpty() {
        return head == 0;
    }

    void addToHead(int);
    void addToTail(int);
    int deleteFromHead();
    int deleteFromTail();
    void deleteNode(int);

    bool isInList(int) const;

private:
    IntSLLNode *head, *tail;
};

接下来实现这个类中的每个函数的功能
1、addToHead(int):

void IntSLList::addToHead(int val) {
    head = new IntSLLNode(val, head);
    if (tail == 0) {
        tail = head;
    }
}

这个函数很简单,主要就是构建头节点和判断头节点是否相同,如果相同就是指向同一个节点。其中head每次都是最新的头节点,这个地方刚才上面有所提到,不再描述。接下来我们来看addToTail这个函数
2、addToTail(int):

void IntSLList::addToTail(int val) {
    if (tail != 0) {
        tail->next = new IntSLLNode(val);
        tail = tail->next;
    } else
        head = tail = new IntSLLNode(val);
}

这个函数也很简单,主要就是两个思路,第一个判断当前链表里面有没有节点,如果有直接创建一个新的,并赋值给tail->next,然后再讲next赋值给tail更新一下节点就好了。如果当前链表里面没有节点,那就让head和tail同时指向新节点即可。

以上就是添加节点的两个函数,下面来看看删除节点的三个函数:
1、deleteFromHead():

int IntSLList::deleteFromHead() {
    int val = head->info;
    IntSLLNode* temp = head;
    if (head == tail) {
        head = tail = 0;
    } else
        head = head->next;

    delete temp;
    return val;
}

函数返回值为Int,代表着你删除头节点存储的val值是多少,这么设计主要是为了当节点要删除时,但是一时间还有用,就将val返回用来处理外部逻辑,然后进入函数中之后,用一个临时int变量把要删除的head存储的值存储起来用来返回,再用一个临时指针保存当前头结点,其次判断当前头结点和尾节点是否相同,如果相同,先将这两个指针指向null,然后删除,如果不相等,先将当前头结点的下个结点赋值给当前头指针,让这个结点成为新的节点,然后再把保存的节点删除,然后被删除头结点的值。
删除完了头结点我们来看一下删除尾节点,删除尾节点代码稍微多一些。
2、deleteFromTail():

int IntSLList::deleteFromTail() {
    int val = tail->info;
    if (head == tail) {
       delete head;
       head = tail = 0;
    } else {
        IntSLLNode *temp;
        for (temp = head; temp->next != tail; temp = temp->next);
        delete tail;
        tail = temp;
        tail->next = 0;
    }

    return val;
}

跟删除头结点一样,先用一个int的临时变量保存要删除尾节点存储的值,用于返回,接下来判断头指针和尾指针是不是指向同一个节点,如果是的话,将tail节点删除,然后将两个指针都指向null,如果不是,声明一个临时节点指针,然后for循环查找尾节点的前一个节点并让临时节点指针指向这个节点,删除tail尾几点,然后并重新更新tail,让tail=tmp,更新完之后,让这个新尾尾节点的next指向null。
下面我们来看看最后一个删除函数
3、deleteNode(int):

void IntSLList::deleteNode(int val) {
    if (head != 0) {
        if (head == tail) {
            delete head;
            head = tail = 0;
        } else if(val == head->info) {
            IntSLLNode *temp = head;
            head = head->next;
            delete temp;
        } else {
            IntSLLNode *pred, *tmp;
            for (pred = head, tmp = head->next; tmp != 0 && !(tmp->info == val);pred=pred->next, tmp=tmp->next);
            if (tmp != 0) {
                pred->next = tmp->next;
                if (tmp == tail) {
                    tail = pred;
                }
                delete tmp;
            }
        }

    }
}

先判断当前链表里面是否有节点,如果没有就不做任何处理,如果有,有三种情况需要处理,第一种是不是只有一个节点,如果是的话,删除节点,然后将head和tail指针指向null,第二种情况,要删除的节点刚好是头结点,方法跟以前一样,用一根临时节点指针保存当前头结点,然后将head指针指向下一个节点,然后删除刚才保存的节点,这样就删除掉了,第三种情况,如果要删除节点不符合上述两种情况,就代表删除链表其中某个一个节点,我们用两个节点指针来操作,一个是pred,一个是tmp,为什么要声明两个节点指针,我们一会再讨论,第一个思路,用tmp找出要删除节点的位置,当找到了之后并且节点指针指向的不是null,现在将上一个节点的next更新到tmp的next,用来断开删除的节点,然后判断是否等于尾节点,如果是,这个时候pred就起到作用了,更新tail尾节点指针,然后将tmp指向的节点删除,如果不是,直接删除tmp节点。
根据上述分析,链表的增删的管理类就完成了,改和查,相对简单,这里就不描述了,感兴趣的可以自己研究一下

上一篇下一篇

猜你喜欢

热点阅读