单链表的基本操作(C++实现)

什么是链表

链表属于线性表的一种,所有的数据按线性顺序排列。还有一种线性表是数组,这种数据结构各有各的优点,数组可以随机访问,并且可以根据下标在O(1)的时间内访问数据,而链表不可以随机访问,链表的顺序是由各个对象里的指针决定的。数组在内存中是顺序存储,所以会占一大部分连续的存储空间,而链表可以分散存储,之间的联系靠指针指向就可以,方便使用内存的零碎的空间。在增删方面,数组也是不理想的,每次增删都要移动数据,最坏的情况下是O(n-1),而链表则可以修改指针的指向在O(1)的时间内就可以完成增删,非常方便。
这里写图片描述

链表的节点一般包括数据域和指针域
头节点的数据域一般存放链表的整体信息,比如链表的长度信息。

需求

编写链表数据结构,要包括基本的增删改查,此次我用c++实现,既接近底层,又可以用类的思想,更好理解面向对象编程。

代码实现

首先新建一个头文件,用于声明要用到结构体的定义和类Linklist的定义。head.h

#include <iostream>
using namespace std;
struct Node {
    int value;
    Node* next;
    Node(int num) :value(num),next(NULL) {};
    Node() {};
};
class LinkList {
public:
    void create();           //初始化
    void insertHead(Node*);  //头插法
    void insertTail(Node*);  //尾插法
    Node* findByIndex(int);  //根据索引查找节点,并返回节点的指针,注意0返回头节点
    Node* findByValue(int);  //根据值查找节点,并返回节点的指针,注意0返回头节点
    int  getLength();        //获取链表的长度
    void deleteByIndex(int); //根据索引删除节点
    void deleteByValueOnce(int); //根据节点值删除第一个节点
    void deleteByValueAll(int);//根据节点值删除所有节点
    void editByIndex(int,int);   //根据索引修改节点的值
    void print();
private:
    Node* head;        //头节点指针,value用于存放链表的长度
};

LinkList实现的cpp文件

#include "head.h"
void LinkList::create() {
    head = new Node();
    head->next = NULL;
    head->value = 0;
}
void LinkList::insertHead(Node* p) {
    p->next = head->next;
    head->next = p;
    head->value++;
}
void LinkList::insertTail(Node* p) {
    Node* tail = findByIndex(head->value);
    if (tail == NULL)
        insertHead(p);
    else {
        p->next = tail->next;
        tail->next = p;
    }
    head->value++;
}
Node* LinkList::findByIndex(int index){
    Node* p = head;
    int i = 0;
    if (index<0||index >getLength()) {
        cout << "索引非法!" << endl;
        return NULL;
    }
    while (p) {
        if (i == index) 
            return p;
        else {
            p = p->next;
            i++;
        }
    }
    return NULL;
}
Node* LinkList::findByValue(int value) {
    Node* p = head->next;
    for (;p;p=p->next){
        if (p->value == value)
            return p;
    }
    return NULL;
}
int LinkList::getLength() {
    return head->value;
}
void LinkList::deleteByIndex(int index) {
    if (index == 0) {
        cout << "不能删除头节点!" << endl;
        return;
    }
    Node* p = findByIndex(index);
    if (!p) {
        cout << "删除失败!" << endl;
        return;
    }
    else {
        Node* q = findByIndex(index - 1);
        q->next = p->next;
        head->value--;
        delete p;
    }
}
void LinkList::deleteByValueOnce(int value) {
    Node* p = head->next;
    Node* q = head;
    bool flag = false;
    for (;p;p = p->next,q=q->next) {
        if (p->value == value) {
            q->next = p->next;
            delete p;
            flag = true;
            head->value--;
            break;
        }
    }
    if (!flag) {
        cout << "链表中不存在值为:" << value << "的节点" << endl;
    }
}
void LinkList::deleteByValueAll(int value) {
    Node* p = head->next;
    Node* q = head;
    bool flag = false;
    while(p){
        if (p->value == value) {
            q->next = p->next;
            Node* temp = p;
            p = p->next; //此处q不动,留给你们思考,不会再留言,嘻嘻
            delete temp;
            head->value--;
            flag = true;
        }
        else {
            p = p->next;
            q = q->next;
        }
    }
    if (!flag) {
        cout << "链表中不存在值为:" << value << "的节点" << endl;
    }
}
void LinkList::editByIndex(int index,int value) {
    if (index == 0) {
        cout << "不能修改头节点!" << endl;
        return;
    }
    Node* p = findByIndex(index);
    if (!p) {
        cout << "修改失败!" << endl;
        return;
    }
    else {
        p->value = value;
    }
}
void LinkList::print() {
    for (Node* p = head->next;p;p = p->next) {
        cout << p->value << " ";
    }
    cout << endl;
}

测试函数

main.cpp

#include"head.h"
void printAnswer(LinkList linklist) {
    linklist.print();
    cout << "当前长度:";
    cout << linklist.getLength() << endl;
}
int main() {
    int n;
    cout << "请输入节点个数:";
    cin >> n;
    LinkList linklist;
    linklist.create();
    int num;
    while (n--) {
        cin >> num;
        linklist.insertHead(new Node(num));
    }
    cout << "头插法结果:";
    printAnswer(linklist);
    cout << "尾插一个数:";
    cin >> num;
    linklist.insertTail(new Node(num));
    cout << "尾插法结果:";
    printAnswer(linklist);
    cout << "想删除第几个:";
    cin >> num;
    linklist.deleteByIndex(num);
    cout << "删除结果:";
    printAnswer(linklist);
    cout << "输入你想删除值为多少的节点(只删除首个):";
    cin >> num;
    linklist.deleteByValueOnce(num);
    cout << "删除结果:";
    printAnswer(linklist);
    cout << "输入你想删除值为多少的节点(所有的):";
    cin >> num;
    linklist.deleteByValueAll(num);
    cout << "删除结果:";
    printAnswer(linklist);
    int replace;
    cout << "输入你想修改第几个节点并改成值为多少:";
    cin >> num >> replace;
    linklist.editByIndex(num, replace);
    cout << "修改结果:";
    printAnswer(linklist);
}

测试结果

这里写图片描述

总结

链表的操作有很多,以后遇见了再进行补充。

  • 15
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值