• c++链表


    主函数文件:
    #include <iostream>

    #include "list_t.h"
    using namespace std;

    int main()
    {
        list_t lin;    // 定义类对象 lin

        lin.append(3);  //
        lin.append(4);
        lin.append(7);
        lin.append(67);
        lin.append(98);
        lin.append(23);
        lin.insertHead(1998);

        cout << lin;  //输出类对象lin

        lin.delNode(67);

        cout << lin;

        lin.delNode(23);

        cout << lin;
        //lin.delNode(&lin);
        lin.find(2);

        cout << "Hello World! "; 
    }
    类与函数声明及函数实现文件
    #pragma once

    #include <iostream>  //输出重载时调用
    using namespace std;

    struct  list_node  //双向链表元素结构体
    {
        int data;            //***元素数据,用于存储数据***
        list_node *next;        //
    $元素指针,访问节点,对数据进行操作
    $元素指针,访问节点,对数据进行操作
    $
        list_node *prev;
    };

    class list_t  //类的定义,用类来实现对链表数据的操作
    {
    private:
        int size;          //私用的三个类变量:链表元素个数,前一个元素结构体指针,后一个元素结构体指针
        list_node * head; 
        list_node * tail;
    public:
        list_t(void);   //类构造函数和析构函数
        ~list_t(void);

        //声明类成员函数之一:判断要操作的链表是否为空(是否没有元素)
        bool isEmpty(void);

        //声明类成员函数之二三:对链表的头插与尾插
        int insertHead(int d);
        int append(int d);

        //声明类成员函数之四五:对链表中指定的元素与指定的数据进行删除
        int delNode(list_node * node);
        int delNode(int d);

        //声明类成员函数之六: 对链表中的指定数据进行查找
        list_node * find(int d);

        //声明类的友元输出运算符重载函数,
        friend ostream & operator<<(ostream & out, const list_t & li);
    };

    //实现类构造函数和析构函数
    list_t::list_t(void)
    {
        head = tail = NULL;  //初始化(清空)链表的元素及元素个数
        size = 0;
    }

    list_t::~list_t(void)
    {
    }

    //实现类成员函数之一:判断要操作的链表是否为空(是否没有元素)
    bool list_t::isEmpty(void)
    {
        if(0 == size)  
        {
            return true;
        }
        return false;
    }
    //实现类成员函数之二三:对链表的头插与尾插

    int list_t::insertHead(int d)  //元素头插, 入参为一个整型数据
    {
        list_node * li = new list_node;  //1,定义并开辟链表指针 "li",给确定无疑的东西赋值处理
        li->data = d;  //!!!通过链表得元素中数据赋值,也可写为
    (∗li).data=d;
    (∗li).data=d;
    $$$
        li->prev = NULL;
        //2,其次,当遇到简单的情况下,我们该怎么办?
        //当链表为空时
        if (isEmpty())
        {
            head = tail = li;  //***给两个链表结构体指针(类内变量)进行 li的内存拷贝
            size++;    //元素个数加1
            return size;   //返回元素个数
        }
        //3,最后,遇到非简单的情况下我们又该怎么做?
        //当链表不为空时
        li->next = head;   //头部插入元素的后向指针 变为 原链表头部结构体元素地址
        head->prev = li;   //原链表头部结构体元素的前向指针变为 头插插入的元素 li

        head = li;   //更新原链表头部结构体元素为 头插插入的元素 li
        size++;  //元素个数加1
        return size;  //返回元素个数
    }

    int list_t::append(int d)  //元素尾插, 入参为一个整型数据
    {
        list_node * li = new list_node;  //1,定义并开辟链表指针 "li",给确定无疑的东西赋值处理
        (*li).data = d;  //!!!通过链表得元素中数据赋值,也可写为
    li−>data=d;
    li−>data=d;
    $$$
        li->next = NULL;  //尾部插入元素的后向指针显然是NULL,指向为空
        //2,其次,当遇到简单的情况下,我们该怎么办?
        //当链表为空时
        if (isEmpty())  //???很奇怪,形参写入为void时报错,不写入时正确.
        {
            head = tail = li;  //***给两个链表结构体指针(类内变量)进行 li 的内存拷贝
            li->prev = NULL;  //链表元素的前向指针赋值为空指针,因为现在的情况是该表中只有他一个元素!!!我们常常会忘掉前提条件
            size++;  //链表元素个数加1
            return size;  //返回链表元素个数
        }
        //3,最后,遇到非简单的情况下我们又该怎么做?
        //当链表不为空时
        tail->next = li;  //(类内保存的)原链表尾部结构体元素的后向指针 更新为 li (打扫屋子)
        li->prev = tail;  //尾部插入元素的前向指针 变为 原链表尾部结构体元素的指针
        
        tail = li;  //将 原链表尾部结构体元素 更新为 新尾部插入的元素
        size++;  //元素个数加1
        return size;  //返回元素个数
    }

    ////声明类成员函数之四五:对链表中指定的元素与指定的数据进行删除
    //int list_t::delNode(list_node * node)  //删除链表的一个结点(形参为该结点的地址)
    //{
    //    if (isEmpty())  //若是空表则不删除
    //    {
    //        return 0;
    //    }
    //
    //    list_node * tmp = head;  //若不是空表,则内存拷贝一份头元素 命名为 tmp
    //    while (tmp)
    //    {
    //        if (tmp->data != node->data)  //依据该结点的数据来遍历寻找这个结点(这不对,要是表中有至少两个元素数据一样就会产生误操作)
    //        {
    //            tmp = tmp->next;  //遍历移位找出要删除的结点tmp
    //            continue;
    //        }
    //
    //        if (head == tmp)  //1.若要删除的结点是头结点时
    //        {
    //            head = head->next;  //新的头结点就成为了 原头结点的后向指针
    //            head->prev = NULL;  //新头结点的前向指针 变为 NULL
    //            delete tmp;  //删除结点(释放指针的指向->变为随机地址值->变成野指针->危险(应处理为NULL))
    //            tmp = NULL;
    //            size--;  //元素个数减1
    //            break;
    //        }
    //
    //        if (tmp == tail)  //若要删除的结点是尾结点时
    //        {
    //            tail = tail->prev;  //新尾结点就成为了 原尾结点的前向结点
    //            tail->next = NULL;  //新尾结点的后向指针 变为 NULL
    //            delete tmp;  //删除结点(释放指针的指向->变为随机地址值->变成野指针->危险(应处理为NULL))
    //            tmp = NULL;
    //
    //            size--;  //元素个数减1
    //            break;
    //        }
    //        //2.若要删除的结点时中间结点时
    //        tmp->prev->next = tmp->next;  //要删除结点的前1个结点的后向指针 指向 要删除结点的后1个结点
    //        tmp->next->prev = tmp->prev;  //要删除结点的后1个结点的前向指针 指向 要删除结点的前1个结点
    //
    //        delete tmp;  //删除结点
    //        tmp = NULL;
    //        size--;
    //        break;
    //    }
    //    return size;  //返回链表元素个数
    //}

    int list_t::delNode(int d)  //删除链表的一个结点(形参为该结点的数据),同上面一样
    {
        if (isEmpty())  
        {
            return 0;
        }

        list_node * tmp = head;  

        while (tmp)
        {
            if (tmp->data != d)
            {
                tmp = tmp->next;
                continue;
            }

            if (head == tmp)
            {
                head = head->next;
                head->prev = NULL;
                delete tmp;
                tmp = NULL;
                size--;
                break;
            }

            if (tmp == tail)
            {
                tail = tail->prev;
                tail->next = NULL;
                delete tmp;
                size--;
                break;
            }

            tmp->prev->next = tmp->next;
            tmp->next->prev = tmp->prev;

            delete tmp;
            tmp = NULL;
            size--;
            break;
        }
        return size;
    }
    //实现类成员函数之六: 对链表中的指定数据进行查找
    list_node * list_t::find(int d)
    {
        if (isEmpty())
        {
            return NULL;
        }

        list_node * tmp = head;  //从头开始遍历查找,找到后返回元素指针,找不到则返回尾指针
        while (tmp)
        {
            if (tmp->data == d)
            {
                break;
            }
            tmp = tmp->next;
        }

        return tmp;
    }

    //实现类的友元输出运算符重载函数,
    ostream & operator<<(ostream & out, const list_t & li)
    {
        list_node * tmp = li.head;  //从头遍历输出

        out << "list content:"<<endl;
        while (tmp)
        {
            out << tmp->data << " ";
            tmp = tmp->next;
        }
        out << endl;

        return out;
    }
    ---------------------

  • 相关阅读:
    CF 793 B (队列中的交换位置)
    WPF转换器
    WPF自定义控件指针仪表(依赖属性)
    面试可能会问到的问题
    返回局部变量是一个指向常量的字符串指针
    自定义c++二维动态数组
    1. 文件乱码 行远
    Nginx自启动脚本
    实验一密码引擎商用密码算法实现2交叉测试
    ARC117F Gateau
  • 原文地址:https://www.cnblogs.com/-lhy-to-s/p/10664911.html
Copyright © 2020-2023  润新知