【008】数据结构:线性表之链式存储结构——C++单向链表的代码实现(使用模板类)

线性表:

  • 最基本和最常用的一种数据结构
  • 由零个或多个数据元素组成的有限序列,表示线性结构
  • 分为顺序存储结构和链式存储结构两种。

特点:

  • 数据元素的数据类型相同
  • 位顺从1开始
  • 有唯一前驱和后继(除第一个和最后一个元素外)

链式存储结构:

  • 用一段不连续的内存空间存储线性表中的数据元素。
    在这里插入图片描述

插入数据原理:

  1. 创建新的节点
  2. 使用循环指针变量找到需要插入节点的位置
  3. 插入节点:
    newnode->next = pCurrent->next;
    pCurrent->next = newnode;
  4. 更改size:size++

C++单向链表的代码实现

DynamicArray.hpp

注: 在使用模板类时,函数的声明和实现必须在同一个文件中,否则会报错

链表类的声明

#include <iostream>

//链表节点
template <typename T>
class LinkNode
{
public:
    T data;
    LinkNode<T> *next;
};

//链表类
template <typename T>
class SList
{
private:
    LinkNode<T> *head;
    int size;

public:
    SList(/* args */);
    ~SList();

    //指定位置插入数据
    void insert(T data, int pos);
    //删除指定位置的值
    void remove(int pos);
    //获得链表的长度
    int getSize();
    //返回第一个节点
    T front();
    //查找位置
    int find(T data);
    //查找数据
    T at(int pos);
    //清空链表
    void clear();
    //打印链表节点
    void show();
};

链表类的定义(实现)

template <typename T>
SList<T>::SList()
{
    size = 0;
    //头节点(不保存数据),目的:使链表实现起来更加方便
    head = new LinkNode<T>;
    head->next = NULL;
}

template <typename T>
SList<T>::~SList()
{
    clear();
    delete head;
}

//指定位置插入数据
template <typename T>
void SList<T>::insert(T data, int pos)
{
    //友好处理:若pos越界,默认插入到尾部
    if (pos < 0 || pos > size)
        pos = size;

    //创建新的节点
    LinkNode<T> *newnode = new LinkNode<T>;
    newnode->data = data;
    newnode->next = NULL;

    //找节点:辅助指针变量
    LinkNode<T> *pCurrent = head;
    for (int i = 0; pCurrent != NULL && i < pos; i++)
        pCurrent = pCurrent->next;
    //新节点插入链表
    newnode->next = pCurrent->next;
    pCurrent->next = newnode;
    size++;
}

//删除指定位置的值
template <typename T>
void SList<T>::remove(int pos)
{
    if (pos < 0 || pos >= size)
    {
        std::cout << "ERROR: The pos is out of bounds!" << std::endl;
        return;
    }

    //找节点:辅助指针变量
    LinkNode<T> *pCurrent = head;
    for (int i = 0; pCurrent != NULL && i < pos; i++)
        pCurrent = pCurrent->next;
    //缓存要删除的节点
    LinkNode<T> *pDel = pCurrent->next;
    //删除节点
    pCurrent->next = pDel->next;
    delete pDel;
}

//获得链表的长度
template <typename T>
int SList<T>::getSize()
{
    return size;
}

//返回第一个节点
template <typename T>
T SList<T>::front()
{
    return head->next;
}

//查找位置
template <typename T>
int SList<T>::find(T data)
{
   //遍历查找
    LinkNode<T> *pCurrent = head->next;
    for (int i = 0; pCurrent != NULL; i++)
    {
        if (pCurrent->data == data) //注意 该类型必须支持 == 操作符,如果不支持需要进行运算符重载
            return i;
        pCurrent = pCurrent->next;
    }
    return -1;
}

//查找数据
template <typename T>
T SList<T>::at(int pos)
{
    if (pos < 0 || pos >= size)
    {
        std::cout << "ERROR: The pos is out of bounds!" << std::endl;
        exit(EXIT_FAILURE);
    }

    //遍历找节点:辅助指针变量
    LinkNode<T> *pCurrent = head;
    for (int i = 0; i <= pos; i++)
        pCurrent = pCurrent->next;
    return pCurrent->data;
}

//清空链表(除表头外)
template <typename T>
void SList<T>::clear()
{
    LinkNode<T> *pCurrent = head->next;
    while (pCurrent != NULL)
    {
        head->next = pCurrent->next;
        delete pCurrent;
        pCurrent = head->next;
    }
    size = 0;
}

//打印链表节点
template <typename T>
void SList<T>::show()
{
    if (size == 0)
    {
        std::cout << "There is no data in this list!" << std::endl;
        return;
    }

    LinkNode<T> *pCurrent = head->next;
    for (int i = 0; pCurrent != NULL && i < size; i++)
    {
        std::cout << i << ": " << pCurrent->data << std::endl;
        pCurrent = pCurrent->next;
    }
}
main.cpp

单链表的测试

#include <iostream>
#include "slist.hpp"

void test_01();
void test_02();

//自定义数据类型
struct Person
{
    char name[64];
    int age;
    int score;
};

int main()
{
	test_01();
    test_02();
    return 0;
}

//注意:自定义结构体时,未重载cout函数和==运算符,部分函数无法使用
void test_01()
{
    //创建链表
    SList<Person> list1;
    //创建数据
    Person p1 = {"XiaoMeng", 23, 95};
    Person p2 = {"aaa", 32, 90};
    Person p3 = {"bbb", 32, 53};
    Person p4 = {"ccc", 53, 76};
    Person p5 = {"ddd", 12, 43};

    //插入数据
    list1.insert(p5, 0);
    list1.insert(p4, 0);
    list1.insert(p3, 0);
    list1.insert(p2, 0);
    list1.insert(p1, 0);

    std::cout << "测试查找函数:" << std::endl;
    std::cout << list1.at(3).name << std::endl;

    //测试删除函数
    
    list1.remove(2);
    list1.clear();
}

//测试一般数据类型(int)
void test_02()
{
    //创建链表
    SList<int> list2;
    //插入数据
    list2.insert(5, 0);
    list2.insert(4, 0);
    list2.insert(3, 0);
    list2.insert(2, 0);
    list2.insert(1, 0);

    //打印数据
    list2.show();

    std::cout << "测试查找函数:" << std::endl;
    std::cout << list2.at(3) << std::endl;
    std::cout << list2.find(3) << std::endl;

    //测试删除函数
    list2.remove(2);
    list2.show();
    list2.clear();
    list2.show();
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值