带头结点的链表

本文介绍了链表的基本概念,强调了链表作为数据结构在内存中的非连续性存储特性,并对比了与数组的区别。文章详细阐述了在C++中如何初始化头结点、插入节点、删除节点、修改节点值、查找节点以及反转链表的操作,并提供了完整的代码示例。

链表

链表是一种线性表,是数据结构中的一种。在内存中是一种非连续性的存储结构,数据元素的逻辑是依靠指针来实现链接。所以,链表不支持随机访问,和另一种数据结构数组时不同的。但是比数组好的一点是她在插入删除中会非常高效。数组在这方面不如链表理想。
在这里插入图片描述

链表包括数据域和指针

初始化头结点

在C++的构造函数里面对头指针进行初始化:

Link::Link()
{
    head = new Node;
    head->_val = -1;
    head->_next = NULL;
}

插入节点

需要先new一个新节点cur出来,然后将cur的next指针指向head->next的地址,最后再将head->next指向cur。
在这里插入图片描述

删除节点

先遍历到指定节点的前一个节点,然后将next指针指向被删除的节点的next。然后delete那个悬空节点。
在这里插入图片描述

修改节点的值

先遍历找到节点,然后将data修改就可以了。
在这里插入图片描述

查找节点

通过遍历节点找到相应的节点。

链表反转

需要创建三个指针,分别指向第一个第二个第三个节点,将第一个结点的指针指向NULL,然后把第二个结点指向第一个结点,用第三个节点进行遍历,依次修改节点的next指针。
在这里插入图片描述

完整代码:

#include <iostream>

using namespace std;

class Node
{
public:
    int _val;
    Node* _next;
};

class Link
{
private:
    Node* head;
public:
    Link(); //构造函数
    ~Link();    //析构函数
    int CreateLink(int n);     // 创建链表
    int getLength(); //获取链表长度
    bool isEmpty(); //判断是否为空表
    void insert(const int& data);  // 尾部插入元素
    void insertAthead(const int& data); // 头部插入元素
    void insert_pos(const int& pos, const int& data);   // 按位置插入元素
    void erase(const int& data);   //删除指定数据
    void eraseAthead();     //删除头结点
    void eraseAtEnd();      //删除尾结点
    int update(const int& n, const int& data);  //修改指定位置的数据
    void reverse(); //反转链表
    void print();   //打印链表
    int find_pos(const int& data);   //查找数据下标
    int find(const int& n);   //查找第n个元素是什么
    void destory(); //销毁链表
};

Link::Link()
{
    head = new Node;
    head->_val = -1;
    head->_next = NULL;
}

Link::~Link()
{
    cout << "下次再见!" << endl;
}

// 创建链表
int Link::CreateLink(int n) {
    if (n < 0) return -1;
    Node* ptr, * tmp;
    ptr = head;
    for (int i = 0; i < n; ++i) {
        cout << "请输入链表第" << i + 1 << "的值" << endl;
        tmp = new Node;
        cin >> tmp->_val;
        ptr->_next = tmp;
        tmp->_next = NULL;
        ptr = tmp;
    }
    return 0;
}

//销毁链表
void Link::destory() {
    if (head == NULL || head->_next == NULL) {
        cout << "链表为空!" << endl;
        return;
    }
    else {
        // 从头结点的下一个开始销毁
        Node* ptr = head->_next;
        while (ptr->_next != NULL) {
            Node* tmp = ptr->_next;
            delete ptr;
            ptr = tmp;
        }
    }
}

//获取链表长度
int Link::getLength() {
    if (head == NULL) return 0;
    Node* ptr = head->_next;
    // 从头结点的下一个开始计算
    int sum = 0;
    while (ptr != NULL) {
        ptr = ptr->_next;
        ++sum;
    }
    return sum;
}

//判断是否为空表,空表返回false,非空返回true
bool Link::isEmpty() {
    if (head->_next == NULL) return false;
    return true;
}

// 尾部插入元素
void Link::insert(const int& data) {
    if (head == NULL || head->_next == NULL) {
        cout << "链表为空!" << endl;
        return;
    }
    // 创建结点将值赋给新节点
    Node* ptr = new Node;
    ptr->_next = NULL;
    ptr->_val = data;
    Node* p = head;
    while (p->_next != NULL) {
        p = p->_next;
    }
    p->_next = ptr;
}

// 头部插入元素
void Link::insertAthead(const int& data) {
    if (head == NULL || head->_next == NULL) {
        cout << "链表为空!" << endl;
        return;
    }
    else {
        Node* ptr = head;
        Node* p = new Node;
        p->_val = data;
        p->_next = ptr->_next;
        ptr->_next = p;
        cout << "插入成功!" << endl;
    }
}

// 按位置插入
void Link::insert_pos(const int& pos, const int& data) {
    if (pos < 1 || getLength() < pos) {
        cout << "插入位置有误!" << endl;
        return;
    }
    Node* ptr = head;
    int i = 0;
    while (i < pos && ptr->_next != NULL) {
        ptr = ptr->_next;
        ++i;
    }
    Node* tmp = new Node;
    tmp->_val = data;
    Node* cur = ptr->_next;
    tmp->_next = cur;
    ptr->_next = tmp;
    cout << "插入成功!" << endl;
}

//删除指定数据
void Link::erase(const int& data) {
    if (!isEmpty()) {
        cout << "链表为空!无法删除!" << endl;
        return;
    }
    else {
        Node* ptr = head->_next,*cur;
        while (ptr->_next != NULL) {
            if (ptr->_next->_val == data) {
                cur = ptr->_next->_next;
                ptr->_next = cur;
            }
            else {
                ptr = ptr->_next;
            }
        }
        if (ptr->_val == data) {
            eraseAtEnd();
        }
    }
}

//删除头结点
void Link::eraseAthead() {
    if (head == NULL || head->_next == NULL) {
        cout << "链表为空!" << endl;
    }
    else {
        Node* ptr = head->_next;
        Node* p = head->_next->_next;
        delete ptr;
        head->_next = p;
    }
}

//删除尾结点
void Link::eraseAtEnd() {
    if (head == NULL || head->_next == NULL)
    {
        cout << "链表为空!" << endl;
    }
    else {
        Node* ptr = head;
        Node* cur = NULL;
        while (ptr->_next != NULL) {
            cur = ptr;
            ptr = ptr->_next;
        }
        delete ptr;
        ptr = NULL;
        cur->_next = NULL;
    }
}

//修改指定位置的数据
int Link::update(const int& n, const int& data) {
    if (!isEmpty()) {
        cout << "链表为空,无法修改" << endl;
        return -1;
    }
    //长度不到n无法修改
    else if(n < 0 || n > getLength()){
        cout << "该位置没有元素,无法修改!" << endl;
        return -1;
    }
    else {
        int i = 1;
        Node* ptr = head;
        while (i <= n) {
            ptr = ptr->_next;
            i++;
        }
        ptr->_val = data;
    }
    return 0;
}

//反转链表
void Link::reverse() {
    if (head == NULL || head->_next == NULL) {
        cout << "链表为空!" << endl;
        return;
    }
    // 头结点后的是哪个结点为了进行反转
    Node* ptr = head->_next;
    Node* cur = head->_next->_next;
    Node* tmp = head->_next->_next->_next;
    // 第二个指针指向第一个结点,然后结点互相换位置
    ptr->_next = NULL;
    while (tmp != NULL) {
        cur->_next = ptr;
        ptr = cur;
        cur = tmp;
        tmp = tmp->_next;
    }
    // 将尾结点指向倒数第二个结点
    cur->_next = ptr;
    // 修改头结点位置
    head->_next = cur;
}

//打印链表
void Link::print() {
    if (!isEmpty()) {
        cout << "链表为空!" << endl;
        return;
    }
    else {
        Node* ptr = head;
        while (ptr->_next != NULL) {
            cout << ptr->_val << "->";
            ptr = ptr->_next;
        }
        cout << ptr->_val << endl;
    }
}

//查找数据下标
int Link::find_pos(const int& data) {
    Node* ptr = head;
    if (!isEmpty()) {
        cout << "链表为空!" << endl;
        return 0;
    }
    else {
        int i = 0;
        //
        while (ptr != NULL) {
            if (ptr->_val == data) {
                return i;
            }
            ptr = ptr->_next;
            ++i;
        }
    }

    return 0;
}

//查找第n个元素是什么
int Link::find(const int& n) {
    if (n < 1 || n > getLength()) {
        return -1;
    }
    Node* ptr = head;
    int i = 1;
    
    while (i <= n) {
        ptr = ptr->_next;
        ++i;
    }
    return ptr->_val;
}

void menu() {
    cout << "*********************链表菜单*********************" << endl;
    cout << "1、创建链表                       2、尾部插入数据 " << endl;
    cout << "3、头部插入                       4、任意插入数据 " << endl;
    cout << "5、删除头结点                     6、删除尾结点   " << endl;
    cout << "7、任意删除元素                   8、销毁链表     " << endl;
    cout << "9、查找位置                       10、查找元素    " << endl;
    cout << "11、链表长度                      12、链表是否为空" << endl;
    cout << "13、修改元素                      14、反转链表    " << endl;
    cout << "0、退出 " << endl;
    cout << "**************************************************" << endl;
}

int main(void) {
    Link l;
    while (1) {
        //system("cls");	//这个会清空显示的屏幕,可选择性使用。
        menu();
        int data;
        int n;
        cout << "请输入选项:";
        cin >> n;
        if (n == 0) {
            break;
        }
        
        switch (n)
        {
         //创建链表
        case(1):
            cout << "请输入需要创建链表的长度:";
            int a;
            cin >> a;
            l.CreateLink(a);
            l.print();
            break;
        //尾部插入元素
        case(2):
            cout << "请输入需要添加的元素:";
            cin >> data;
            l.insert(data);
            l.print();
            break;
        //头部插入
        case(3):
            cout << "请输入需要添加的元素:";
            cin >> data;
            l.insertAthead(data);
            l.print();
            break;
        //任意位置插入元素
        case(4):
            cout << "请输入需要添加的元素:";
            cin >> data;
            cout << "请输入需要插入的位置:";
            cin >> n;
            l.insert_pos(n, data);
            l.print();
            break;
        //删除头结点
        case(5):
            cout << "原链表为:";
            l.print();
            cout << "删除头结点之后链表为:";
            l.eraseAthead();
            l.print();
            break;
        //删除尾结点
        case(6):
            cout << "原链表为:";
            l.print();
            cout << "删除尾结点之后链表为:";
            l.eraseAtEnd();
            l.print();
            break;
        //任意位置删除
        case(7):
            cout << "原链表为:";
            l.print();
            cout << "请输入需要删除的元素:";
            cin >> data;
            cout << "删除元素之后链表为:";
            l.erase(data);
            l.print();
            break;


        //销毁链表
        case(8):
            l.destory();
            cout << "销毁链表!程序结束!" << endl;
            system("pause");
            return 0;

        //查找位置
        case(9):
            cout << "请输入需要查找的位置:";
            cin >> n;
            if (l.find(n) != -1) {
                cout << "第" << n << "个位置元素为:" << l.find(n) << "!" << endl;
            }
            else {
                cout << "该位置没有元素!" << endl;
            }
            break;

        //查找元素
        case(10):
            cout << "请输入需要查找的元素:";
            cin >> data;
            if (l.find_pos(data) > 0) {
                cout << "元素" << data << "在第" << l.find_pos(data) << "个位置!" << endl;
            }
            else {
                cout << "该元素不在链表里面!" << endl;
            }
            break;
        //链表长度
        case(11):
            cout << "链表长度为:" << l.getLength() << endl;
            break;
        //链表是否为空
        case(12):
            if (l.isEmpty()) {
                cout << "链表不为空!" << endl;
                l.print();
            }
            else {
                cout << "链表为空!" << endl;
            }
            break;
        //修改元素
        case(13):
            cout << "原链表为:";
            l.print();
            cout << "请输入需要修改的链表位置:";
            cin >> n;
            cout << "请输入需要修改的链表元素元素:";
            cin >> data;
            if (l.update(n, data) != 0) {
                break;
            }
            cout << "修改成功!修改之后的链表为:";
            l.print();
            break;
        case(14):
            cout << "原链表为:";
            l.print();
            cout << "反转链表之后:";
            l.reverse();
            l.print();
            break;
        default:
            cout << "输入有误!" << endl;
            break;
        }
    }
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值