00001_C++实现单链表(代码带有详细注释)

线性表(单链表)

Node.h单一节点定义

#pragma once
#ifndef NODE_H
#define NODE_H
#include <iostream>
using namespace std;
class Node
{
public:
    int data;//数据域
    Node* next;//next指针域
    void printNode();//打印节点信息
private:
};
void Node::printNode()
{
    cout << data << endl;
}
#endif       // !NODE_H

List.h链表定义

#pragma once
#ifndef LIST_H
#define LIST_H//引入List.h
#include "Node.h"
using namespace std;
class List
{
public:
     List();                                           //创建线性表
    ~List();                                           //销毁线性表
    void ClearList();                                  //清空线性表
    bool ListEmpty();                                  //判断线性表是否为空
    int ListLength();                                  //获取线性表的长度
    bool GetElem(int n, Node* pNode);                  //获取指定元素
    int LocateElem(Node* pNode);                       //寻找第一个满足e的数据元素的位序
    bool PriorElem(Node* pCurrentNode, Node* pPreNode);//获取指定元素的前驱
    bool NextElem(Node* pCurrentNode, Node* pNextNode);//获取指定元素的后继
    bool ListInsert(int n, Node* pNode);               //在第n个位置上插入元素
    bool ListDelete(int n, Node* pNode);               //删除第n个位置上的元素
    bool ListInsertHead(Node* pNode);                  //头插法
    bool ListInsertTail(Node* pNode);                  //尾插法
    void ListTraverse();                               //便利线性表
private:
    Node* m_pList;
    int m_iLength;
};
List::List()
{
    m_pList = new Node;//node类型的指针new一个Node类型数据
    m_pList->data = 0;//默认头节点的数值为0
    m_pList->next = NULL;
    m_iLength = 0;//设置当前链表长度为0
}
List::~List()
{
    ClearList();//执行清理链表的程序,类中声明,类外定义,删除 除了头节点以外的所有结点
    delete m_pList;//释放头节点
    m_pList = NULL;//设置头节点指针为NULL
}
void List::ClearList()//函数定义
{
    Node* currentNode = m_pList->next;//创建currentNode指针指向头节点的下一个节点
    while (currentNode != NULL)//循环结束条件:头节点的next指针为空,即只剩下头节点
    {
        Node* temp = currentNode->next;//C++中指针访问指向数据的成员用->访问,将currentNode所指向数据的next指针赋值给 Node类型的temp指针
        delete currentNode;//释放currentNode所指向的内容
        currentNode = temp;//将下一节点的指针继续赋值给currentNode
    }
    m_pList->next = NULL;//m_pList指针所指向内容的next指针指向的内容已被释放,所以设置这个next指针为空(NULL)
}
bool List::ListEmpty()
{
    if (m_iLength == 0)
    {
        return true;
    }
    else
    {
        return false;
    }
    //return m_iLength == 0 ? true : false;
}
int List::ListLength()
{
    return m_iLength;
}
bool List::GetElem(int n, Node* pNode)//获得指定位置的节点内容,n负责定位,pNode负责将数据带出来
{
    if (n < 0 || n >= m_iLength)//如果n小于0或者大于当前链表的长度,则无法定位
    {
        return false;//定位失败
    }
    else
    {
        Node* currentNode = m_pList;//从头节点的下一个节点开始遍历
        for (int i = 0; i <= n; i++)
        {
            currentNode = currentNode->next;
        }
        pNode->data = currentNode->data;//将定位的节点数据赋值给pNode的data变量
        return true;//返回定位成功
    }
}
int List::LocateElem(Node* pNode)//定位元素的位置
{
    Node* currentNode = m_pList;//将头节点指针赋值给currentNode指针
    int count = 0;
    while (currentNode != NULL)
    {
        currentNode = currentNode->next;//遍历除头节点外的所有节点
        if (currentNode->data == pNode->data)
        {
            return count;//返回count值,即定位的节点位置
        }
        count++;
    }
    return -1;//如果没有查找成功则返回-1
}
bool List::PriorElem(Node* pCurrentNode, Node* pPreNode)//pCurrentNode 就是想要查找此节点的前驱节点,用pPreNode指针将内容带出来
{
    Node* currentNode = m_pList;//头节点指针赋值给currentNode
    Node* tempNode = NULL;
    while (currentNode != NULL)//直到当前指针所指内容为空(NULL)
    {
        tempNode = currentNode;
        currentNode = currentNode->next;//回溯到头节点的下一个节点
        if (currentNode->data == pCurrentNode->data)//定位到想要查找的节点
        {
            if (tempNode == m_pList)//如果定位的节点为头节点,则失败,因为头节点没有前驱节点
            {
                return false;
            }
            pPreNode->data = tempNode->data;//将数据带出去
            return true;
        }
    }
    return false;
}
bool List::NextElem(Node* pCurrentNode, Node* pNextNode)//pCurrentNode 就是想要查找此节点的后继节点,用pNextNode指针将内容带出
{
    Node* currentNode = m_pList;
    Node* tempNode = NULL;
    while (currentNode != NULL)
    {
        currentNode = currentNode->next;
        if (currentNode->data == pCurrentNode->data)//定位到想要查找的节点
        {
            if (currentNode->next == NULL)//如果定位的节点为尾节点,则失败,因为尾节点没有后继节点
            {
                return false;
            }
            pNextNode->data = currentNode->next->data;//将数据带出去
            return true;
        }
    }
    return false;
}
void List::ListTraverse()//遍历链表
{
    Node* currentNode = m_pList;
    while (currentNode->next != NULL)//直到遍历到尾节点
    {
        currentNode = currentNode->next;
        currentNode->printNode();//调用Node类的printNode()方法
    }
}
bool List::ListInsert(int n, Node* pNode)//在指定位置插入节点,传入想要插入的节点
{
    if (n < 0 || n > m_iLength)
    {
        return false;
    }
    else
    {
        Node* currentNode = m_pList;
        for (int i = 0; i < n; i++)
        {
            currentNode = currentNode->next;
        }
        Node* newNode = new Node;//内存爆掉的情况,无法new一个Node对象的时候
        if (newNode == NULL)
        {
            return false;
        }
        newNode->data = pNode->data;
        newNode->next = currentNode->next;//newNode指针与currentNode指针所指向内容的next指针指向同一个Node节点
        currentNode->next = newNode;//currentNode指针所指向内容的next指针指向newNode
        m_iLength++;//更新链表的长度
        return true;//返回插入成功
    }
}
bool List::ListDelete(int n, Node* pNode)//删除指定位置的节点,并将节点信息带出来
{
    if (n < 0 || n >= m_iLength)
    {
        return false;
    }
    else
    {
        Node* currentNode = m_pList;
        Node* currentNodeBefore = NULL;
        for (int i = 0; i <= n; i++)//一直遍历到指定位置
        {
            currentNodeBefore = currentNode;
            currentNode = currentNode->next;
        }
        currentNodeBefore->next = currentNode->next;//将当前节点的前驱节点的next指针指向当前节点next指针所指向的内容(即后继节点)
        pNode->data = currentNode->data;//将删除节点的内容带出来
        currentNode = NULL;//当前节点指向内容为空
        m_iLength--;//更新链表长度
        return true;//返回删除成功
    }
}
bool List::ListInsertHead(Node* pNode)//头插法插入节点
{
    Node* temp = m_pList->next;
    Node* newNode = new Node;//内存爆掉的情况,无法new一个Node对象的时候
    if (newNode == NULL)
    {
        return false;
    }
    newNode->data = pNode->data;//将需要插入节点的信息赋值给newNode
    newNode->next = temp;//newNode的next指针指向头节点的下一个节点
    m_pList->next = newNode;//头节点的next指针指向newNode
    m_iLength++;//更新链表长度
    return true;//返回插入成功
}
bool List::ListInsertTail(Node* pNode)//尾插法插入节点
{
    Node* currentNode = m_pList;
    Node* tempNode = NULL;
    while (currentNode != NULL)//先遍历到尾节点,最终tempNode为尾节点,currentNode是尾节点的next指针所指向的内容为空(NULL)
    {
        tempNode = currentNode;
        currentNode = currentNode->next;
    }
    Node* newNode = new Node;
    if (newNode == NULL)
    {
        return false;
    }
    newNode->data = pNode->data;//将需要插入节点的信息赋值给newNode
    newNode->next = NULL;//尾插法,插入节点作为尾节点所以其next指针内容为空(NULL)
    tempNode->next = newNode;//未插入前链表的尾节点的next指针指向newNode
    m_iLength++;//更新链表长度
    return true;//返回插入成功
}
#endif // !LIST_H

List.cpp主函数

#include "List.h"
#include "Node.h"
int main()
{
    List* pList = new List();
    Node e1, e2, e3, e4, e5, e6, e7, e8;
    e1.data = 1;
    e2.data = 2;
    e3.data = 3;
    e4.data = 4;
    e5.data = 5;
    e6.data = 6;
    e7.data = 7;
    pList->ListInsertHead(&e1);//头插法插入节点
    pList->ListInsertHead(&e2);//头插法插入节点
    pList->ListInsertHead(&e3);//头插法插入节点
    pList->ListInsertHead(&e4);//头插法插入节点
    pList->ListInsertHead(&e5);//头插法插入节点
    pList->ListInsertHead(&e6);//头插法插入节点
    pList->ListInsertTail(&e1);//尾插法插入节点
    pList->ListInsertTail(&e2);//尾插法插入节点
    pList->ListInsertTail(&e3);//尾插法插入节点
    pList->ListInsertTail(&e4);//尾插法插入节点
    pList->ListInsertTail(&e5);//尾插法插入节点
    pList->ListInsertTail(&e6);//尾插法插入节点
    //pList->ListInsert(6, &e7);//指定位置插入节点
    //pList->ListDelete(6, &e8);//指定位置删除节点
    pList->NextElem(&e4, &e8);//e8是将后继节点(e5)的内容带出去
    pList->ListTraverse();//遍历整个链表的内容
    cout << pList->ListLength() << " " << e8.data << endl;//获取整个链表的长度,e8的数据
    delete pList;//删除链表,pList会自动执行析构函数,自动释放链表的所有内容
    pList = NULL;//指针pList的内容为空
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值