链表及其基本操作

本文详细介绍了链表的数据结构,包括单链表的特点(如高效插入和删除但低随机访问),并提供了链表操作的示例,如计算链表长度、插入、删除元素和查找元素的方法,同时与数组进行了比较。
摘要由CSDN通过智能技术生成

链表

什么是链表

  • 和数组一样,链表也是一种线性表
  • .从内存结构来看,链表的内存结构是不连续的内存空间,是将一组零散的内存块串联起来,从而进行数据存储的数据结构。
  • 链表中的每一个内存块被称为节点Node。

特点

  • 插入、删除数据效率高O(1)级别(只需更改指针指向即可),随机访问效率低O(n)级别(需要从链头至链尾进行遍历)。
  • 和数组相比,内存空间消耗更大,因为每个存储数据的节点都需要额外的空间存储后继指针。

单链表

  • 每个节点只包含一个指针,即后继指针。
  • 单链表有两个特殊的节点,即首节点和尾节点。为什么特殊?用首节点地址表示整条链表,尾节点的后继指针指向空地址null。
  • 性能特点:插入和删除节点的时间复杂度为O(1),查找的时间复杂度为O(n)。

链表的操作

1、返回链表的长度

区别链表和数组

我们将数组比作货车,我们运输时要考虑的是货物的重量,不可以超过载重,而链表相当于是火车,不够就再加车厢,不用考虑载重的问题。即空间大小。

1、计算返回链表的长度(看有几个节点)

//首先定义节点
class Node:
 def _init_(self,data=None):
  self.data=data
  self.next=None;
//实现单链表类
class LinkedList:
count=0
current=self.head
while current!=None//循环结束的条件
current +=1:
current=current.next
return count;
     
//时间复杂度为O(n),遍历整个链表

2、打印链表的全部内容(完整代码)

#include <iostream>
#usingnamespace std;
class ListNode {  //首先创建一个ListNode的类表示链表中的节点
public:
    int value;//value表示节点的值
    ListNode* next;//next表示指向下一个节点的指针

    ListNode(int value) : value(value), next(nullptr) {}
};

class LinkedList {
public:
    ListNode* head;

    LinkedList() : head(nullptr) {}//构造函数,用于初始化链表的头节点为nullptr。

    void addNode(int value) {//用于表中添加节点
        ListNode* newNode = new ListNode(value);//创建一个新的ListNode类型的节点,并将其值设置为value
        if (head == nullptr) {//使用条件语句判断head指针是否为空。如果为空,将新节点设置为头结点。
            head = newNode;
        } else {
            ListNode* cur = head;
            while (cur->next != nullptr) {
                cur = cur->next;
            }//用于找到链表的尾节点。首先将cur指针指向头结点,然后遍历链表,直到找到最后一个节点,即cur->next为空
            cur->next = newNode;
        }
    }

    void disPlay() {//用于打印每个节点的值
        ListNode* cur = head;
        while (cur != nullptr) {
         cout << cur->value << " ";
            cur = cur->next;
        }
       cout << endl;
    }
};

int main() {
    LinkedList list;
    list.addNode(56);
    list.addNode(2);
    list.addNode(223);
    list.disPlay(); // 输出:56 2 223
    return 0;
}
时间复杂度为O(n)

shijianfuza

3、指定位置插入元素(在链表第三个元素后面插入一个元素)

(在第i-1个节点后插入一个新节点)

  • 先构造一个新节点,用S指向;
  • 再找到链表的第i-1个节点,用P指向;
  • 然后修改指针,插入节点(P之后插入新节点是S)
s->Next = p->Next;    //把p的Next赋值给S的Next
p->Next = s;   // 把S的值赋给P的Next  

顺序不能错!!!如果对调会丢失p->Next的值
注意是否是插入到第一个元素,以及这个元素是否存在。

#include <iostream>

// 定义链表节点结构体
struct ListNode {
    int val;            // 节点的值
    ListNode* next;     // 指向下一个节点的指针
    ListNode(int x) : val(x), next(nullptr) {}   // 构造函数,初始化节点的值和指针
};

// 在给定位置插入新节点
void insertNode(ListNode* head, int position, int value) {
    ListNode* newNode = new ListNode(value);   // 创建新节点
    ListNode* current = head;   // 当前节点指针

    // 遍历链表,找到指定位置的节点
    for (int i = 1; i < position && current != nullptr; i++) {
        current = current->next;
    }

    // 如果指定位置超出链表长度,则输出错误信息并返回
    if (current == nullptr) {
        std::cout << "Position is out of range." << std::endl;
        return;
    }

    // 注意点:插入新节点
    newNode->next = current->next;
    current->next = newNode;
}

// 打印链表内容
void printLinkedList(ListNode* head) {
    ListNode* current = head;   // 当前节点指针

    // 遍历链表,打印节点的值
    while (current != nullptr) {
        std::cout << current->val << " ";
        current = current->next;
    }
    std::cout << std::endl;
}

int main() {
    // 创建链表示例
    ListNode* head = new ListNode(1);
    head->next = new ListNode(2);
    head->next->next = new ListNode(3);

    // 在第三个元素后插入新元素
    insertNode(head, 3, 4);

    // 打印链表内容
    printLinkedList(head);

    return 0;
}
//整体时间复杂度为O(n)

4、删除元素(删除第i个位置处的节点)

  • 先找到链表的第(i-1)个节点,用P指向;
  • 再用指针S指向要被删除的节点(p的下一个节点);
  • 然后修改指针,删除S所指节点;
  • 最后,释放S所指节点空间
    P在前,S为要释放的空间。
s=p->Next;
p->Next=s->Next;
free(s);

5、查找某个元素是否存在

按照序号查找
List FindKth(int K,List Ptrl)
{
    List p=PtrL;//p设为链表的头
    int i=1;
    while(p!=NULL&&i<k)//当p为空或者i等于k的时候,循环停止
    {
        p=p->Next;
        i++;
    }
if(i==k) return p;//找到了,第k个
else return NULL;//到最后也没找到,返回空,即不存在这个数
}//时间复杂度为n,需要遍历整个列表
按值查找
List Find(ElementType X,List PtrL)
{
List P=PtrL;
while (p!=NULL&&P->Data!=X)
P=P->Next;
return P;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值