【数据结构】手搓链表

一、定义

cpp 复制代码
typedef struct node_s
{
    int _data;
    struct node_s *_next;
} node_t;

typedef struct list_s
{
    node_t *_head;
    node_t *_tail;
} list_t;
  1. 节点结构体(node_s):

    • int _data;存储节点中的数据
    • struct node_s *_next;:指向 node_s 类型的指针,用来指向链表中的下一个节点
  2. 链表结构体(list_s):

    • node_t *_head;:这是一个指向 node_s 类型的指针,用来指向链表的第一个节点,即头节点。如果链表为空,那么 _head 应该指向 NULL。
    • node_t *_tail;:这是一个指向 node_s 类型的指针,用来指向链表的最后一个节点,即尾节点。如果链表为空,那么 _tail 也应该指向 NULL。

链表的结构图如下:

初始化:

头尾结点指针均置为空

cpp 复制代码
void init(list_t *l)
{
    l->_head = NULL;
    l->_tail = NULL;
}

二、插入

1、头插法

由于函数需要更改pHead的指向,而pHead是指向Head结点的指针类型为node_t *,所以函数需要传入pHead的地址即:node_t **二级指针,如图所示传入ppHead和ppTail

  • 若链表为空,则头尾指针均指向新节点
  • 若不为空,则新结点与pHead指向相同,即指向Head,再将pHead前移
cpp 复制代码
void headInsert(node_t **ppHead, node_t **ppTail, int data)
{
    node_t *pNew = (node_t *)malloc(sizeof(node_t));
    bzero(pNew, sizeof(node_t));
    pNew->_data = data;
    if (*ppHead == NULL)
    {
        *ppHead = pNew;
        *ppTail = pNew;
    }
    else
    {
        pNew->_next = *ppHead;
        *ppHead = pNew;
    }
}

2、尾插法

参数与头插法相同

  • 若链表为空,则头尾指针均指向新节点
  • 若不为空,则pTail指向的Tail结点的_next指向新节点,再将pTail后移
cpp 复制代码
void tailInsert(node_t **ppHead, node_t **ppTail, int data)
{
    node_t *pNew = (node_t *)malloc(sizeof(node_t));
    bzero(pNew, sizeof(node_t));
    pNew->_data = data;
    if (*ppHead == NULL)
    {
        *ppHead = pNew;
        *ppTail = pNew;
    }
    else
    {
        (*ppTail)->_next = pNew;
        *ppTail = pNew;
    }
}

三、遍历

cpp 复制代码
void visit(node_t *pHead)
{
    node_t *pCur = pHead;
    while (pCur)
    {
        printf("%d ", (*pCur)._data);
        pCur = pCur->_next;
    }
    printf("\n");
}

四、测试

1、头插法

cpp 复制代码
list_t list;
init(&list);
for (int i = 0; i < 10; i++)
{
    headInsert(&list._head, &list._tail, i);
    visit(list._head);
}

运行结果:

2、尾插法

cpp 复制代码
list_t list;
init(&list);
for (int i = 0; i < 10; i++)
{
    tailInsert(&list._head, &list._tail, i);
    visit(list._head);
}
return 0;

运行结果:

五、使用C++对其封装

cpp 复制代码
class List
{
public:
    List();
    ~List();
    void push_back(int data);
    void push_front(int data);
    void visit();

private:
    typedef struct node_s
    {
        int _data;
        struct node_s *_next;
    } node_t;

    node_t *_pHead;
    node_t *_pTail;
};
List::List()
{
    _pHead = nullptr;
    _pTail = nullptr;
}
List::~List()
{
    node_t *pCur = _pHead;
    node_t *temp = nullptr;
    while (pCur)
    {
        temp = pCur;
        pCur = pCur->_next;
        delete temp;
        temp = nullptr;
    }
}
void List::push_back(int data)
{
    node_t *pNew = new node_t();
    pNew->_data = data;
    pNew->_next = nullptr;
    if (_pHead == nullptr)
    {
        _pHead = pNew;
        _pTail = pNew;
    }
    else
    {
        pNew->_next = _pHead;
        _pHead = pNew;
    }
}
void List::push_front(int data)
{
    node_t *pNew = new node_t();
    pNew->_data = data;
    pNew->_next = nullptr;
    if (_pHead == nullptr)
    {
        _pHead = pNew;
        _pTail = pNew;
    }
    else
    {
        _pTail->_next = pNew;
        _pTail = pNew;
    }
}
void List::visit()
{
    node_t *pCur = _pHead;
    while (pCur)
    {
        std::cout << (*pCur)._data << " ";
        pCur = pCur->_next;
    }
    std::cout << "\n";
}
相关推荐
罗湖老棍子6 小时前
【例 1】Sightseeing Trip(信息学奥赛一本通- P1494)(洛谷-P10927)
数据结构·算法·图论·最短路·floyd·最小环
郝亚军10 小时前
manifest 中 `sha256` 与 `signValue` 的作用
java·开发语言·数据结构
Nil20810 小时前
LeetCode 283移动零
数据结构·算法·leetcode
库玛西12 小时前
外部排序全解析:败者树、置换-选择排序与最佳归并树
c语言·数据结构·c++·笔记·考研·算法
花间相见16 小时前
【计算基础|MySQL08】索引(上):为什么是 B+ 树
数据结构·mysql·算法·架构
夊16 小时前
数据结构第二课:顺序表揭秘
数据结构
OKkankan18 小时前
python 进阶(三):面向对象进阶——从“会写 class”到设计可维护的后端对象
开发语言·数据结构·python
闻缺陷则喜何志丹19 小时前
vc入门宝典(九)
数据结构·list·mfc·存储·null·class
quaer1 天前
弗洛伊德算法--判圈法寻找环的入口O(n) O(1)
数据结构·算法
xys_6781 天前
深挖数据结构:树和二叉树(上)
数据结构·算法