C++链表的增删改查实现原理

  1. 本人开始觉得链表这种数据结构很难,但是在学习编程的过程中,渐渐认识到这种数据结构的重要性,于是花了点时间研究了下链表。
  2. 对于链表。首先,要知道它和顺序表相比有什么优点,最大的优点就是增加元素,和删除元素的速度快,顺序表增加一个元素和删除一个元素就会用循环移动很多元素,这样对于代码运行效率有很大影响。所以必须理解链表。
  3. 我们要从其本质去理解它,链表分为单链表,环形链表(和环形队列相似),双向链表等。链表由一个一个节点构成,链表的结构体或者类如下:分为数据域和指针域两部分
#ifndef Node_h_
#define Node_h_

class Node
{
public:
    int data;//data不一定是int,可以用自己定义的类实现
    Node* next;//这里必须是Node* 型指针
};

#endif

每个链表的节点有3个参数(不要总认为只有data和next两个,还有节点本生的地址。这个地址值等于上一个节点中next存储的值)。
比如Node* p1;p1本身存储本节点地址,p1->data是本节点数据,p1->next是本节点存储的下一个节点地址。
有了这个理解,再来看看这些函数

#ifndef List_h_
#define List_h_

#include"Node.h"

class List
{
public:
    void CreatList(Node*& f, int n);//建立链表
    void CreatList1(Node*& f, int n);//建立反顺序链表
    void Insertlist(Node*& f, int x);//插入元素(增加)
    bool DeleteList(Node*& f, int x);//删除元素(删除)
    bool UpdateList(Node*& f, int x, int y);//修改指定元素(修改)
    void TravelList(Node* f);//遍历链表
private:
    int m_iLength;

};

#endif

以上这些函数中,形参f都是代表传入的链表头结点
下面是这些函数具体实现

#include"List.h"
#include<iostream>
using namespace std;


/*
函数名称:建立一个链表,手动输入n个整数,这个链表顺序和输入整数顺序一样。
函数实现:f为头结点地址,n为输入的节点个数
*/
void List::CreatList(Node*& f, int n)
{
    if (n < 0)
    {
        cerr << "n值无效" << endl;
        exit(1);
    }
    if (n == 0)
    {
        f = NULL;
        return;
    }//前两个if判断是判断节点个数的n值输入是否合法,不合法返回
    cout << "从键盘上输入" << n << "个整数" << endl;
    int x;
    cin >> x;//这是输入的第一个数据,将存储在头结点中
    f = new Node;//堆上开辟一个节点内存空间
    f->data = x;
    f->next = NULL;//刚建立的第一个头结点都是有数据,但没有下一个节点,所以其指针域为空。
    Node* p = f;//p和f都代表头结点地址,之所以产生p,是因为后面的节点建立都是p的移动产生的,而f不变,一直指向头结点
    for (int i = 1; i <= n - 1; i++)//循环n-1次,新建n-1个节点,因为前面有了1个头节点
    {
        cin >> x;
        p->next = new Node;//每次循环堆上产生一个新节点内存,新节点的地址存储于p的节点的指针域

        p = p->next;//p移到了下一个新节点
        p->data = x;//x新的节点数据域存储了新的数据x
    }
    p->next = NULL;//最后p移到尾节点时候,指针域要为空
}

/*
函数功能:创建一个链表,链表从头到尾的顺序与输入的整数顺序相反。
函数实现:
*/
void List::CreatList1(Node*& f, int n)
{
    if (n < 0)
    {
        cerr << "n值无效" << endl;
        exit(1);
    }
    if (n == 0)
    {
        f = NULL;
        return;
    }
    cout << "从键盘上输入" << n << "个整数" << endl;
    int x;
    cin >> x;
    f = new Node;
    f->data = x; f->next = NULL;
    Node* p;
    for (int i = 1; i < n - 1; i++)
    {
        cin >> x;
        p = new Node;
        p->data = x;
        p->next = f;
        f = p;
    }
}

/*
函数功能:插入个元素,按要求插入
要求:从表头节点开始顺序查找,若x小于表头节点的值或者链表头为空,则插入到表头,若大于等于一个节点值而小于其后继
            节点值则插入到他们之间。
*/
void List::Insertlist(Node*& f, int x)//f表示从头结点为f的链表插入元素,x表示要插入的元素
{
    Node* p = new Node;//待插入新节点
    p->data = x; p->next = NULL;//x存入新节点
    if (f ==NULL)
    {
        f = p;
        return;
    }
    //cout << endl << f->data << endl;
    if (x < f->data)//将x插入,成为新的头节点
    {
        p->next = f;//将p节点和原来的头结点扯上关系
        f=p;       //p成为了新的头节点后,但是还是要用f表示头结点,因为函数传入参数为Node*& f
        return;
    }
    Node* p1 = f;  Node*p2 = f->next;
    while (p2 != NULL)//一直后移节点,通过p1和p2后移
    {
        if (x < p2->data) break;
        else
        {
            p1 = p2;
            p2 = p2->next;
        }
    }
    p1->next = p; p->next = p2;//这条代码就是将p节点插入p1和p2之间
    return;
}
/*
函数名称:链表的删除
函数功能:删除链表中某个节点
*/
bool List::DeleteList(Node*& f, int x)//同上,f表示对头结点为f的链表操作删除。x表示要删除的内容
{
    if (f == NULL)  return false;//判断表是否为空
    if (f->data == x)
    {
        f = f->next;//如果删除头结点,则头结点后移一个,也就是把f存储的地址值变为下一个节点的地址
        return true;
    }
    Node* p1 = f, *p2 = f->next;
    while (p2 != NULL)//当p1为最后一个节点的时候,p2就为NULL了,当p1位倒数第二个节点时候,p2就是最后一个尾节点。
    {
        if (x == p2->data) break;
        else
        {
            p1 = p2;
            p2 = p2->next;//让p1,p2后移动
        }
    }
    if (p2 == NULL) return false;//p1移到最后都没有找到匹配元素,返回的false表示没有删除元素
    p1->next = p2->next;//表示删除了元素,将p2节点删除了。
    return true;
}
/*
函数功能:跟新指定元素
函数实现:
*/

bool List::UpdateList(Node*& f, int x, int y)//x是要变得元素,y则是要将链表中的x变为y
{
    if (f == NULL) return false;
    Node* p1 = f;
    while (p1 != NULL)
    {
        if (x == p1->data)
        {
            p1->data = y;
        }
        p1 = p1->next;
    }
    if (p1 == NULL)  return false;
    return true;
}


/*
函数名称:遍历链表
函数功能:将链表每个节点的数据输出来
*/
void List::TravelList(Node* f)
{
    Node*p1 = f;
    while (p1 != NULL)
    {
        cout << p1->data << " ";
        p1 = p1->next;

    }
    /*while (f != NULL)
    {
        cout << f->data << '   ';
        f = f->next;
    }
    cout << endl;*/
}
  • 下面是主函数的调用
#include <iostream>
#include"List.h"
using namespace std;

int main()
{   
    Node* head1;//为头结点分配一个地址。这是必不可少的
    List* pList = new List;
    pList->CreatList(head1,5);
    pList->Insertlist(head1, 3);
    pList->DeleteList(head1, 2);
    pList->UpdateList(head1, 5, 6);
    pList->TravelList(head1);


    system("pause");
    return 0;
}
  • 以上代码简单实现了链表的一些操作,可以参考学习!
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值