新手向链表及其基本操作的代码实现(C++)

本文介绍了链表的基本概念,包括链表的逻辑和存储结构,并详细讲解了如何使用C++实现链表的创建、在链表头部添加节点、任意位置插入节点、删除节点以及迭代和递归方式反转链表的操作。通过代码示例和运行结果展示了具体步骤。

链表

一、链表的逻辑,存储结构

链表由链表头节点及其他节点构成。其中每一个节点都有其对应的数据和指向下一元素的指针。

二、链表的代码实现

在这里插入图片描述

三、实现简单的链表

在这里插入图片描述

在这里插入图片描述


三、链表的操作

一、添加节点至链表头部


实现思路:
1.将数据写入一个新建的节点
2.将表头指向的地址(即首个节点的地址)写入新建的节点
3.将表头指向的地址改为新建的节点


代码:

#include<iostream>
using namespace std;

struct Node{
    int data;//数据
    struct Node* next;//指向下一数据元素的指针
};
struct Node* head;//链表头

void Insert(int _data){
    Node* temp = new Node();
    temp->data = _data;//写入数据
    temp->next = head;//写入首位节点指针,使节点联结原首各节点。
    head = temp;//使链表头指向该节点
}

void Print(){
    Node* temp = head;
    cout<<"List is:";
    while(temp!=NULL){
        cout<<" "<<temp->data;//输出当前节点的数据
        temp = temp->next;//使该临时节点指向下一节点
    }
    cout<<endl;
}

int main (){
    head = NULL; //设置链表头为空指针

    Insert(1);//在首位插入节点
    Insert(2);
    Insert(3);
    Insert(4);
    Print();
    //DONE
}

运行结果:
在这里插入图片描述

二、任意位置插入节点


实现思路:
1.将数据写入一个新建的节点
2.如果不是插入到首位,则取出要插入位置的前一位的节点中保存的下一节点地址,赋给新建节点,使得新建节点与下一节点联结。如果插入到第一位,那么将节点指向的地址指向表头,然后将表头指向该节点。
3.将前一位节点的下一节点地址修改为新建节点的地址,使得新建节点与前一节点形成联结。


代码:

#include<iostream>
using namespace std;

struct Node{
    int data;//数据
    struct Node* next;//指向下一数据元素的指针
};
struct Node* head;//链表头

void Insert(int pos,int _data){
    Node* temp = new Node();
    temp->data = _data;//写入数据
    temp->next = NULL;

    if(pos == 1){//插入到首位的情况
        temp->next = head;
        head = temp;
    }else{//插入到非首位的情况
        Node* temp2 = head;
        for(int i =0;i<pos-2;i++){//循环到插入位前一位
            temp2 = temp2->next;
        }
        if(temp2 == NULL) exit(0);//插入位置非法
        
        temp->next = temp2->next;//将插入节点指向的地址修改为下一节点(即插入位置前一节点保存的地址)
        temp2->next = temp;//将前一位节点指向的地址改为该节点的地址。
    }

}

void Print(){
    Node* temp = head;
    cout<<"List is:";
    while(temp!=NULL){
        cout<<" "<<temp->data;//输出当前节点的数据
        temp = temp->next;//使该临时节点指向下一节点
    }
    cout<<endl;
}

int main (){
    head = NULL; //设置链表头为空指针

    Insert(1,2);
    Insert(2,3);
    Insert(3,4);
    Insert(4,5);
    Print();
}

运行结果:
在这里插入图片描述

三、删除某个节点


实现思路:
1.如果删除位置为首位,则将第二位设为表头
2.如果删除位置为非首位,则将第其前一位指向的地址指向其下一位元素,并将删除位置的空间释放。


代码:

#include<iostream>
using namespace std;

struct Node{
    int data;//数据
    struct Node* next;//指向下一数据元素的指针
};
struct Node* head;//链表头

void Delete(int pos){
    Node* temp = head;
    if(pos == 1){
        free(head);
        head = temp->next;
    }else{
        for(int i =0;i<pos-2;i++){//获得删除位前一位
            temp = temp->next;
        }
        Node* temp2 = temp->next;//获得删除位

        temp->next = temp2->next;//将删除为前一位指向的地址改为删除位下一位
        free(temp2);
    }
}

void Insert(int pos,int _data){
    Node* temp = new Node();
    temp->data = _data;//写入数据
    temp->next = NULL;

    if(pos == 1){//插入到首位的情况
        temp->next = head;
        head = temp;
    }else{//插入到非首位的情况
        Node* temp2 = head;
        for(int i =0;i<pos-2;i++){//循环到插入位前一位
            temp2 = temp2->next;
        }
        if(temp2 == NULL) exit(0);//插入位置非法

        temp->next = temp2->next;//将插入节点指向的地址修改为下一节点(即插入位置前一节点保存的地址)
        temp2->next = temp;//将前一位节点指向的地址改为该节点的地址。
    }

}

void Print(){
    Node* temp = head;
    cout<<"List is:";
    while(temp!=NULL){
        cout<<" "<<temp->data;//输出当前节点的数据
        temp = temp->next;//使该临时节点指向下一节点
    }
    cout<<endl;
}

int main (){
    head = NULL; //设置链表头为空指针

    Insert(1,1);
    Insert(2,2);
    Insert(3,3);
    Insert(4,4);
    Insert(5,5);
    Insert(6,6);
    Insert(7,7);
    Insert(8,8);
    Delete(1);
    Delete(5);//本次删除的是 2 3 4 5 6 7 8 的第五位6.
    Print();
}

运行结果:
在这里插入图片描述

反转链表(迭代方式)


实现思路:

保存当前节点前,当前,后节点地址。先将当前节点存储的地址转为前一节点,随后转至后一节点进行操作


代码:

#include<iostream>
using namespace std;

struct Node{
    int data;//数据
    struct Node* next;//指向下一数据元素的指针
};
struct Node* head;//链表头

void Reserve(){
    Node* pre,*current,*next;
    current = head;
    pre = NULL;
    while(current!=NULL){
        next = current->next;//保存下一节点地址
        current->next = pre;//将当前节点的下一地址改为前一位
        //移动至下一节点
        pre = current;//保存当前地址到pre
        current = next;//修改current地址
    }
    head = pre;//修改表头
}

void Insert(int pos,int _data){
    Node* temp = new Node();
    temp->data = _data;//写入数据
    temp->next = NULL;

    if(pos == 1){//插入到首位的情况
        temp->next = head;
        head = temp;
    }else{//插入到非首位的情况
        Node* temp2 = head;
        for(int i =0;i<pos-2;i++){//循环到插入位前一位
            temp2 = temp2->next;
        }
        if(temp2 == NULL) exit(0);//插入位置非法

        temp->next = temp2->next;//将插入节点指向的地址修改为下一节点(即插入位置前一节点保存的地址)
        temp2->next = temp;//将前一位节点指向的地址改为该节点的地址。
    }

}

void Print(){
    Node* temp = head;
    cout<<"List is:";
    while(temp!=NULL){
        cout<<" "<<temp->data;//输出当前节点的数据
        temp = temp->next;//使该临时节点指向下一节点
    }
    cout<<endl;
}

int main (){
    head = NULL; //设置链表头为空指针

    Insert(1,1);
    Insert(2,2);
    Insert(3,3);
    Insert(4,4);
    Insert(5,5);
    Insert(6,6);
    Insert(7,7);
    Insert(8,8);
    Print();
    Reserve();
    Print();
}

运行结果:
在这里插入图片描述

扩展

一、打印一个链表(递归的方式)

#include<iostream>
using namespace std;

struct Node{
    int data;//数据
    struct Node* next;//指向下一数据元素的指针
};
struct Node* head;//链表头

void Print(struct Node* p){
    if(p != NULL){
        cout<<" "<<p->data;
        Print(p->next);
    }else{
        return;
    }

}

void Insert(int pos,int _data){
    Node* temp = new Node();
    temp->data = _data;//写入数据
    temp->next = NULL;

    if(pos == 1){//插入到首位的情况
        temp->next = head;
        head = temp;
    }else{//插入到非首位的情况
        Node* temp2 = head;
        for(int i =0;i<pos-2;i++){//循环到插入位前一位
            temp2 = temp2->next;
        }
        if(temp2 == NULL) exit(0);//插入位置非法

        temp->next = temp2->next;//将插入节点指向的地址修改为下一节点(即插入位置前一节点保存的地址)
        temp2->next = temp;//将前一位节点指向的地址改为该节点的地址。
    }

}

int main (){
    head = NULL; //设置链表头为空指针

    Insert(1,1);
    Insert(2,2);
    Insert(3,3);
    Insert(4,4);
    Insert(5,5);
    Insert(6,6);
    Insert(7,7);
    Insert(8,8);
    Print(head);
}

运行结果:
在这里插入图片描述

逆转链表(递归的方法)

#include<iostream>
using namespace std;

struct Node{
    int data;//数据
    struct Node* next;//指向下一数据元素的指针
};
struct Node* head;//链表头

void Reserve(struct Node* p){
    if(p->next==NULL){
        head = p;
        return;
    }
    Reserve(p->next);
    struct Node* temp = p->next;
    temp->next = p;
    p->next = NULL;
}

void Print(struct Node* p){
    if(p != NULL){
        cout<<" "<<p->data;
        Print(p->next);
    }else{
        return;
    }

}

void Insert(int pos,int _data){
    Node* temp = new Node();
    temp->data = _data;//写入数据
    temp->next = NULL;

    if(pos == 1){//插入到首位的情况
        temp->next = head;
        head = temp;
    }else{//插入到非首位的情况
        Node* temp2 = head;
        for(int i =0;i<pos-2;i++){//循环到插入位前一位
            temp2 = temp2->next;
        }
        if(temp2 == NULL) exit(0);//插入位置非法

        temp->next = temp2->next;//将插入节点指向的地址修改为下一节点(即插入位置前一节点保存的地址)
        temp2->next = temp;//将前一位节点指向的地址改为该节点的地址。
    }

}

int main (){
    head = NULL; //设置链表头为空指针

    Insert(1,1);
    Insert(2,2);
    Insert(3,3);
    Insert(4,4);
    Insert(5,5);
    Insert(6,6);
    Insert(7,7);
    Insert(8,8);
    Reserve(head);
    Print(head);
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值