单向链表的一些理解

为什么有链表:数组很棒,但是插入和删除时需要移动大量的元素,消耗时间。在第一个位置插入元素时后面的元素都要向后移动

链表的基本思维:利用结构体的设置,额外开辟出一份内存空间去作指针,它总是指向下一个结点,一个个结点通过NEXT指针相互串联,就形成了链表。

一个是自己的数据,另外一个是指针指向下一个数据所在的位置。

插入新值后,

下面是实现单链表的实例                                               

#include 

// 定义链表节点结构
struct Node {
 int data; // 数据部分
 Node* next; // 指针部分,指向下一个节点的位置
};

class LinkedList {
private:
 Node* head; // 头节点指针,指向链表的第一个节点
public:
 // 构造函数
 LinkedList() {
 head = nullptr; // 初始化头节点为空
 }

// 在链表尾部插入新节点
void append(int value) {
 Node* newNode = new Node; // 创建新节点
 newNode->data = value; // 设置新节点的数据
 newNode->next = nullptr; // 新节点的next指针指向空值

 if (head == nullptr) {
 head = newNode; // 如果链表为空,直接将新节点设置为头节点
 } else {
 Node* current = head;//如果不为空,从头节点找最后节点
 while (current->next != nullptr) {
 current = current->next; // 找到链表最后一个节点
 }
 current->next = newNode; // 将新节点连接到最后一个节点后面
 }
}

// 删除链表中指定数值的节点
void remove(int value) {
 if (head == nullptr) {//链表是空,就提示
 std::cout << "Empty list. Nothing to remove." << std::endl;
 return;
 }

 if (head->data == value) {//这个值是头节点就删除
 Node* temp = head;
 head = head->next;
 delete temp;
 return;
 }

 Node* current = head;
 while (current->next != nullptr) {//遍历节点
 if (current->next->data == value) {
 Node* temp = current->next;
 current->next = current->next->next;
 delete temp;
 return;
 }
 current = current->next;
 }

 std::cout << "Value " << value << " not found in the list." << std::endl;
}

// 打印链表元素
void print() {
 Node* current = head;
 while (current != nullptr) {
 std::cout << current->data << " ";
 current = current->next;
 }
 std::cout << std::endl;
}
//指定·位置插入数值
void insertAt(int value, int position) {
    Node* newNode = new Node;  // 创建新节点
    newNode->data = value;     // 设置新节点的数据

if (position == 0) {
    newNode->next = head;  // 将新节点的next指针指向当前的头节点
    head = newNode;        // 更新头节点为新节点
    return;
}

// 寻找要插入位置的前一个节点
Node* current = head;
for (int i = 0; i < position - 1 && current != nullptr; i++) {
    current = current->next;
}

if (current == nullptr) {
    std::cout << "Invalid position." << std::endl;
    return;
}

newNode->next = current->next;  // 将新节点的next指针指向当前节点的next节点
current->next = newNode;        // 将当前节点的next指针指向新节点


}
};

int main() {
 LinkedList list;
 list.insert(5);
 list.insert(10);
 list.insert(15);

list.print(); // 输出:5 10 15

list.remove(10);
list.print(); // 输出:5 15

return 0;


}
```

单链表删除节点操作

LinkedList LinkedListDelete(LinkedList L,int x) {
    Node *p,*pre;                   //pre为前驱结点,p为查找的结点。
    p = L->next;//下一个节点
     
    while(p->data != x) {              //查找值为x的元素
        pre = p;
        p = p->next;//没有就下一个
    }
    pre->next = p->next;          //删除操作,将其前驱next指向其后继。
    free(p);//释放地址
     
    return L;
}

        链表主要注意元素的next指向位置,没有在第几个这个概念,删除的原理换成python写比较清楚一些,思维方面需要转变。一般通过循环找到响应的位置进行删除。

class ListNode:
    def init(self, val=0, next=None):
        self.val = val
        self.next = next

def deleteAtIndex(head, index):
    # 处理删除头节点的情况
    if index == 0:
        return head.next

prev = None
curr = head
# 遍历链表,找到目标位置的节点
while curr and index > 0:
    prev = curr
    curr = curr.next
    index -= 1

# 如果链表长度不足,无法删除节点
if index > 0:
    return head

prev.next = curr.next  # 跳过 curr 节点,将 prev 的 next 指向 curr 的下一个节点
curr.next = None  # 释放 curr 节点的内存空间
return head


创建链表 1 -> 2 -> 3 -> 4 -> 5

head = ListNode(1)
node2 = ListNode(2)
node3 = ListNode(3)
node4 = ListNode(4)
node5 = ListNode(5)
head.next = node2
node2.next = node3
node3.next = node4
node4.next = node5

删除第3个节点

head = deleteAtIndex(head, 2)

打印链表

curr = head
while curr:
    print(curr.val, end=" -> ")
    curr = curr.next
```

输出结果为:

1 -> 2 -> 4 -> 5 ->

一些力扣题:(一)实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。

/**遍历链表并统计链表长度,记链表长度为 N;
设置一个节点指针向前走 N−k步,便可找到链表倒数第 k 个节点


初始化双指针 pre , cur 都指向头节点 head ;
先令 cur 走 k 步,此时 pre , cur 的距离为 k ;
令 pre , cur 一起走,直到 cur 走过尾节点时跳出,此时 pre 指向「倒数第 k个节点」,返回之即可;
(不知道链表的末尾在,也不知道在具体哪个位置)

 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    int kthToLast(ListNode* head, int k) {
        ListNode *pre = head, *cur = head;
        for (int i = 0; i < k; i++)//建立循环,一直数下去
            cur = cur->next;//cur先走k步
        while (cur != nullptr) {
            pre = pre->next;
            cur = cur->next;//cur和pre一起走,cur到末尾,pre到达倒数第k个
        }
        return pre->val;

    }
};

(二)若链表中的某个节点,既不是链表头节点,也不是链表尾节点,则称其为该链表的「中间节点」。假定已知链表的某一个中间节点,请实现一种算法,将该节点从链表中删除。

class Solution {
public:
    void deleteNode(ListNode* node) {
        node->val = node->next->val;
        node->next = node->next->next;
    }
};


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值