数据结构之链表(看不懂你来找我)

数据结构🚀链表



一、👿什么是链表?

链表是一种常见的数据结构,由一系列节点构成,每个节点包含当前节点的数据和一个指针(单向链表)或者两个指针(双向链表),链表是一种动态的数据结构,可以动态的增删节点。它的特点是插入与删除数据十分方便,但寻找与读取数据的表现欠佳。

1、链表的特点

  • 动态内存分配:链表中的节点是在运行时动态创建的,可以根据需要分配和释放内存。
  • 可扩展性:链表的大小可以根据需要动态增长或缩小,没有固定的大小限制。
  • 非连续存储:链表中的节点可以分散在内存的不同位置,每个节点包含数据和指向下一个节点的指针。

二、🤡单向链表

  • 每个节点包含一个数据域和一个指针域。指针域指向下一个节点,直到最后一个节点指向空指针(Null)
    单项链表

Head:指向头节点的指针。这里Head=200,表示第一个数据的地址。
每个节点包含当前的数据和一个指针(指向下一个数据),不懂指针的同学可以复习一下指针。

1、构建一个单项链表

  • 这里使用C++语言
struct Node{
    int data;    // 数据
    struct Node* next;  //地址
};
struct Node* head;   //创建一个头节点,以便后续使用

2、插入数据

  • 在链表中的任意位置插入数据
void Insert(int data ,int n){      // n表示要插入的位置,从1开始算
        Node* temp1 = new Node();  // 创建一个节点先承载我们要插入的数据
        temp1->data = data;
        temp1->next = NULL;
        if(n==1){        // 如果要插入第一个位置就把temp1的地址给head
            head = temp1;
            return;
        }
        Node* temp2 = head; // 如果不插入第一个位置就创建第二个节点
        for(int i=1;i<n-1;i++){    //temp2从第一个节点一直走到第n-1个节点
            temp2 = temp2->next;
        }
        temp2->next = temp1;//因为temp2指向第n-1个节点,所以temp2->next就是第n个节点的地址,将temp1的地址赋给temp2->next
}

3、删除数据

  • 在链表的任何一个位置删除一个数据
void Delete(int n){  // 删除第n个节点
    Node* temp1 = head;    // 此时temp1指向第一个节点
    if(n==1){
        head = temp1->next;    // 如果删除第一个节点,就把head指向第二个节点(temp1->next)
        delete temp1;
        return;
    }
    for(int i=1;i<n-1;i++){
        temp1 = temp1->next;   //temp1指向目标节点的前一个节点
    }
    Node* temp2 = temp1->next;  // 此时temp2指向要删除的那个节点(目标节点)
    temp1->next = temp2->next; //将目标节点的下一个节点接到目标节点的下一个节点
    delete temp2;  // 删除temp2
}

4、打印链表

  • 迭代方式实现
void Print(){
    struct Node* temp = head;
    while(temp != NULL){   //从第一个循环到最后一个
        std::cout<<temp->data<<" ";
        temp = temp->next;
    }
    std::cout<<std::endl;
}
  • 递归方式实现
void Rec_print(struct Node* p){  //递归打印 p:头节点的指针
    if(p == NULL) return;  // 退出条件
    printf("%d ",p-> data);
    Rec_print(p->next);
}

5、反转链表

反转链表

  • 迭代方式实现
void Reverse(){       
    Node* prev = NULL;
    Node* curr = head;
    Node* next;
    while(curr != NULL){
        next = curr->next;//next指向curr的下一个节点,使用next先存着curr节点
        curr->next = prev;// curr指向prev
        prev = curr;	  
        curr = next;
    }
    head = prev;
}

这里的循环可能不太好理解,可以看看下面这张图

while循环注解

  • 递归方式实现
void Recursion_reverse(struct Node* p){   //p节点及其往后的节点全部反转
    if(p->next == NULL){
        head = p;
        return;
    }
    Recursion_reverse(p->next);
    struct Node* q = p->next;
    q->next = p;
    p->next = NULL;
}

三、🤡双向链表

  • 双向链表中同样有数据域和指针域。不同之处在于,指针域有左右(或上一个、下一个)之分,用来连接上一个结点、当前结点、下一个结点。
    双向链表

1、创建一个双向链表

struct Double_Node{  // 双向链表
    int data;
    struct Double_Node* next;
    struct Double_Node* prev;
};
struct Double_Node* head2;//创建头节点

2、插入节点

  • 如果看不懂可以自己Debug一下或者画图看看
void Double_insert(int x,int n){//在任意位置插入一个节点
    struct Double_Node *NewNode = new Double_Node();
    NewNode->data = x;
    NewNode->prev = NULL;
    NewNode->next = NULL;
    if(n==1){  //使NewNode成为头节点
        NewNode->next = head2;//头节点
        head2->prev = NewNode;
        head2 = NewNode;
        return;
    }
    struct Double_Node* temp = head2;
    for(int i=1;i<n-1;i++){   //temp循环到第n-1个节点
        temp = temp->next;
    }
    NewNode->next = temp->next;//插入节点
    NewNode->prev = temp;
    temp->next = NewNode;
    temp->next->prev = NewNode;
}

3、删除节点

void Double_delete(int n){  //删除第n个节点
    struct Double_Node* temp = head2;
    if(n==1){
        head2 = temp->next;
        head2->prev = NULL;
        delete temp;
        return;
    }
    for(int i=1;i<n-1;i++){
        temp = temp->next;
    }
    struct Double_Node* temp2 = temp->next;
    temp->next = temp2->next;
    temp2->next->prev = temp;
}

4、打印双向链表

  • 双向链表的打印实现和单项链表的一样,这里就不写了

四、🤡总结

双向链表的方法实现和单向列表的实现相似,实现方式有很多种,在学习中,重要的是学习链表的这种思想,并不是单单的使用代码,不理解的可以多Debug几次,深入理解。

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang&xin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值