数据结构之链表分析与实现

链表由多个数据节点组成,每个数据节点由数据域和指针域两部分组成,如下图

 其中数据域的类型取决于节点数据类型,若节点为字符,则数据域类型为字符型。指针域类型为地址,存储着其他节点的内存地址,在C/C++中表现为节点类型的指针。

计算机存储链表的过程中以数据节点为基本单位,每个节点都是不可再分的,每次只申请一个节点大小的内存空间,不同节点之间通过指针域连接。这意味着如果在原链表上增加和删除节点十分方便,不必移动其他数据,只需要更改相应的指针域中的内存地址就好,但是当我们访问链表时将会变得十分不方便,只能通过一个又一个节点的指针域不断跳转。

常见链表分为单链表和双链表,区别在于指针域中指针的个数。单链表节点的指针域中只有一个指向下一个节点的指针,指针域为空时代表该节点为最后一个节点。这就意味着如果是一个单链表,当我们访问的时候,就只能“一条路走到黑”,没有其他标记的时候就没有办法返回到上一个节点。为了弥补单链表的这种缺陷,我们可以设计双链表,双链表的指针域中不仅有指向下一个节点的指针,还有一个指向上一个节点的指针。

链表的增加与删除,以单链表为例。假设某单链表有三个节点a、 b、 c如下,它们的内存地址分别是0x10、0x20、0x30

如果我们要删除节点b,只需要修改a节点的指针域地址为c节点的所在地址(0x30),释放b节点的内存资源即可。

       增加节点则恰恰相反,加入我们需要在a、c两节点之间在添加一个节点时,只需要申请一个节点b的内存,设置b节点的指针域为c的节点的地址,然后把a节点的指针域修改为b节点的地址。一般情况下我们的需求可能是把b节点添加到a节点后面,是没有c节点的,一定要先将b的指针域设置为a的指针域的值,然后在设置a的指针域,否则我们将无法找到原本a节点后面的节点

节点的查询,修改过程不再赘述。

下面是单链表的C++简单实现。

定义节点数据

#define dataType int    //节点数据类型

typedef struct Node {
    dataType data;  //数据域
    struct Node *next;  //指针域
} *list;

插值函数,后插法可以改进非递归实现,非递归实现的时候需要注意因为参数L是引用,不要更头部节点L以及判断L是否为空

void insert(list &L, dataType value) {  //链表插值函数,L为链表,value为插入的值
    //以下为前插法,即每次添加的节点都位于链表的第一个
    list p = L;
    L = (list) malloc(sizeof(list));
    L->data = value;
    L->next = p;
    //以下为后插法,每次插入的节点位于链表结尾
    // if(L == NULL) {
    //     L = (list)malloc(sizeof(list));
    //     L->data = value;
    //     L->next = NULL;
    //     return;
    // }
    // else {
    //     insert(L->next, value);
    // }
}

从链表中删除指定值,因为传参的过程中L是引用,所以删除节点后链表的结构不会被破坏。

void deleteByValue(list &L, dataType value) {   //删除指定值的节点,L为链表,value为匹配值
    if(L == NULL) {
        return;
    }
    if(L->data == value) {  //当前节点需要删除
        list p = L;
        L = L->next;
        free(p);
        deleteByValue(L, value);
    }
    else {  //当前节点无需删除
        deleteByValue(L->next, value);
    }
}

链表的打印以及销毁

void printList(list L) {   //打印链表
    if(L == NULL) {
        return;
    }
    cout << L->data;
    for (L = L->next; L != NULL; L = L->next) {
        cout << "--->" << L->data;
    }
    cout << endl;
}

void destoryList(list &L) { //销毁链表
    list p;
    while(L != NULL) {
        p = L;
        L = L->next;
        free(p);
    }
}

文件下载

单链表.cpp

双链表.cpp

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章