C++链表(linked list)

目录

基础知识

链表的基本操作——创建、遍历、插入、删除

1.单向链表的创建和遍历

(1)无头结点

(2)有头结点

2.单向链表的插入、删除

单向链表的插入

单向链表的删除

代码实现:

常见的链表面试问题

1.翻转链表


基础知识

链表也是一种线性表。链表的内存结构是不连续的内存空间,是将一组零散的内存块串联起来,从而进行数据存储的数据结构。
插入、删除数据效率O(1)级别(只需更改指针指向即可),随机访问效率O(n)级别(需要从链头至链尾进行遍历)。此外和数组相比,内存空间消耗更大,因为每个存储数据的节点都需要额外的空间存储指针。
常用链表:
     单链表:每个节点只包含一个指针,即后继指针。首节点地址表示整条链表,尾节点的后继指针指向空地址null
     循环链表:除了尾节点的后继指针指向首节点的地址外均与单链表一致。适用于存储有循环特点的数据,比如约瑟夫问题。
     双向链表:节点除了存储数据外,还有两个指针分别指向前一个节点地址(前驱指针prev)和下一个节点地址(后继指针next)。首节点的前驱指针prev和尾节点的后继指针均指向空地址。虽然理论上链表的插入删除效率都为O(1),但某些情况下,单链表的插入删除效率为O(n),而双向链表可达O(1)。双向链表的按值查询速度一般来说也比单链表快一倍。但双向链表所耗储存空间比单链表更多。详见(https://time.geekbang.org/column/article/41013)
     双向循环链表:除首节点的前驱指针指向尾节点,尾节点的后继指针指向首节点外与双向链表一致
缺点:
     内存空间消耗更大,因为需要额外的空间存储指针信息。
     对链表进行频繁的插入和删除操作,会导致频繁的内存申请和释放,容易造成内存碎片
链表代码的注意事项:
     针对链表的插入、删除操作,需要对插入第一个结点和删除最后一个结点的情况进行特殊处理。如不想进行,可以利用哨兵结点写带头链表。
     重要边界条件检查:如果链表为空时,代码是否能正常工作?如果链表只包含一个结点时,代码是否能正常工作?如果链表只包含两个结点时,代码是否能正常工作?代码逻辑在处理头结点和尾结点的时候,是否能正常工作?(https://time.geekbang.org/column/article/41149)

链表的基本操作——创建、遍历、插入、删除

1.单向链表的创建和遍历

(1)无头结点

#include<iostream>
using namespace std;
struct list {  //定义链表的结构
	int value;
	list* next;
};

int main()
{
	list* head = new list;   //创建头指针
	int n;
	cout << "请输入将要储存的元素个数: ";
	cin >> n;
	cout << "请依次输入将要储存的元素:\n";
	cin >> head->value;
	list* p = head;
	for (int i = 0;i < n - 1;i++)
	
  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
链表翻转是链表操作中的一项基本操作,可以将链表中的节点按照相反的顺序排列。C语言中可以使用指针来实现链表的翻转。 下面是一个简单的链表翻转的例子: ```c #include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node* next; } Node; Node* reverseList(Node* head) { if (head == NULL || head->next == NULL) { return head; } Node* p = reverseList(head->next); head->next->next = head; head->next = NULL; return p; } void printList(Node* head) { Node* p = head; while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); } int main() { Node* head = (Node*)malloc(sizeof(Node)); head->data = 1; Node* p1 = (Node*)malloc(sizeof(Node)); p1->data = 2; head->next = p1; Node* p2 = (Node*)malloc(sizeof(Node)); p2->data = 3; p1->next = p2; p2->next = NULL; printf("原链表:"); printList(head); Node* newHead = reverseList(head); printf("翻转后的链表:"); printList(newHead); return 0; } ``` 在上面的代码中,我们定义了一个包含数据和下一个节点指针的结构体Node,然后我们定义了一个reverseList函数,该函数使用递归来翻转链表。在翻转链表的过程中,我们首先递归遍历链表,然后将当前节点的下一个节点的next指针指向当前节点,最后将当前节点的next指针设为NULL,以防止链表出现环。最后返回递归遍历的第一个节点,也就是翻转后的链表的头节点。 最后在main函数中,我们创建了一个包含3个节点的链表,然后打印出原链表和翻转后的链表

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值