【C++习题集】-- 顺序表、链表

(用于复习)

目录

线性表

顺序表

链表

单链表

单向 \ 双向

带哨兵位 \ 不带哨兵位

循环 \ 非循环

无头单向非循环链表实现

oj题

203. 移除链表元素

206. 反转链表

快慢指针

141.环形链表

【解题思路】

带头双向循环链表

顺序表和链表的区别


线性表

        常见的线性表:顺序表链表队列字符串...。

  • 逻辑上: 线性结构
  • 物理上: 不一定是连续

顺序表

#include <iostream>
#include <cassert>
#include <malloc.h>
#include <cstdlib>namespace qcr_vector
{typedef int VectorType;struct Vector{VectorType* _array;  // 指向动态开辟的数组uint64_t _size;        // 有效数据个数uint64_t _capacity;    // 容量空间的大小};/****************** 顺序表初始化*****************/void VectorInit(Vector* vector){assert(vector);vector->_array = nullptr;vector->_capacity = vector->_size = 0;}/****************** 检查空间,如果满了,进行增容*****************/void VectorCapacity(Vector* vector){assert(vector);if(vector->_capacity == vector->_size){uint64_t new_capacity = vector->_capacity == 0 ? 5 : vector->_capacity * 2;VectorType* tmp = (VectorType*)realloc(vector->_array, new_capacity * sizeof(VectorType));if(tmp == nullptr){perror("VectorCapacity::realloc");exit(-1);}vector->_array = tmp;vector->_capacity = new_capacity;}}// 顺序表在pos位置插入elementvoid VectorInsert(Vector *vector, uint64_t pos, VectorType element){assert(vector);assert(pos < vector->_size);VectorCapacity(vector);for(int i = vector->_size; i > pos; i--){vector->_array[i] = vector->_array[i - 1];}vector->_array[pos] = element;(vector->_size)++;}// 顺序表删除pos位置的值void VectorErase(Vector *vector, uint64_t pos){assert(vector);assert(pos < vector->_size);for(int i = pos; i < vector->_size - 1; i--){vector->_array[i] = vector->_array[i + 1];}(vector->_size)--;}// 顺序表尾插void VectorPushBack(Vector* vector, VectorType element){VectorInsert(vector, vector->_size, element);// assert(vector);// VectorCapacity(vector);// vector->_array[vector->_size] = element;// (vector->_size)++;}// 顺序表尾删void VectorPopBack(Vector* vector){VectorErase(vector, vector->_size - 1);// assert(vector);// (vector->_size)--;}// 顺序表头插void VectorPushFront(Vector* vector, VectorType element){VectorInsert(vector, 0, element);// assert(vector);// VectorCapacity(vector);// for(int i = vector->_size; i > 0; i--)// {//     vector->_array[i] = vector->_array[i - 1];// }// vector->_array[0] = element;// (vector->_size)++;}// 顺序表头删void VectorPopFront(Vector* vector){VectorErase(vector, 0);// assert(vector);// for(int i = 0; i < vector->_size - 1; i--)// {//     vector->_array[i] = vector->_array[i + 1];// }// (vector->_size)--;}// 顺序表查找int64_t VectorFind(Vector *vector, VectorType element){assert(vector);for(int i = 0; i < vector->_size; i++){if(vector->_array[i] == element){return i;}}return -1;}// 顺序表销毁void VectorDestory(Vector *vector){assert(vector);vector->_size = vector->_capacity = 0;if(vector->_array)free(vector->_array);vector->_array = nullptr;}// 顺序表打印void VectorPrint(Vector *vector){assert(vector);for(uint64_t i = 0; i < vector->_size; i++){std::cout << vector->_array[i] << " ";}std::cout << std::endl;}
};

链表

单链表

单向 \ 双向

带哨兵位 \ 不带哨兵位

循环 \ 非循环

最常用还是两种结构:

  • 无头单向非循环链表
  • 带头双向循环链表

  1. 无头单向非循环链表:一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。笔试面试出现很多)
  2. 带头双向循环链表:一般用在单独存储数据。

无头单向非循环链表实现

#include <iostream>
#include <cassert>namespace qcr_single_list
{typedef int SingleListType;struct SListNode{SingleListType _data;SListNode *_next;};/***************** 动态申请一个结点****************/SListNode *BuySListNode(SingleListType data){SListNode *single_list = (SListNode *)malloc(sizeof(SListNode));if (single_list == nullptr){perror("BuySListNode::malloc");exit(-1);}single_list->_data = data;single_list->_next = nullptr;return single_list;}/***************** 单链表在pos位置之后插入data****************/void SListInsertAfter(SListNode *pos, SingleListType data){assert(pos);SListNode *single_list = BuySListNode(data);single_list->_next = pos->_next;pos->_next = single_list;}/***************** 单链表删除pos位置之后的值****************/void SListEraseAfter(SListNode *pos){assert(pos);assert(pos->_next);SListNode *erase = pos->_next;pos->_next = pos->_next->_next;free(erase);}/***************** 单链表头插****************/void SListPushFront(SListNode **single_list, SingleListType data){SListNode *new_SListNode = BuySListNode(data);new_SListNode->_next = (*single_list);*single_list = new_SListNode;}/***************** 单链表尾插****************/void SListPushBack(SListNode **single_list, SingleListType data){SListNode *new_SListNode = BuySListNode(data);if (*single_list) // 尾插{SListNode *cur = *single_list;while (cur->_next){cur = cur->_next;}cur->_next = new_SListNode;}else // 头插{*single_list = new_SListNode;}}/***************** 单链表头删****************/void SListPopFront(SListNode **single_list){assert(*single_list);SListNode *erase = *single_list;*single_list = (*single_list)->_next;free(erase);}/***************** 单链表尾删****************/void SListPopBack(SListNode **single_list){assert(*single_list);if (nullptr == (*single_list)->_next){free(*single_list);*single_list = nullptr;}else{SListNode* cur = *single_list;while (cur->_next->_next){cur = cur->_next;}SListNode *erase = cur->_next;cur->_next = nullptr;free(erase);}}/***************** 单链表查找****************/SListNode *SListFind(SListNode *single_list, SingleListType data){assert(single_list);SListNode *cur = single_list;while (cur){if (cur->_data == data)return cur;cur = cur->_next;}return nullptr;}/***************** 单链表打印****************/void SListPrint(SListNode *single_list){SListNode *cur = single_list;while (cur != nullptr){printf("%d->", cur->_data);cur = cur->_next;}printf("nullptr\n");}/***************** 单链表销毁****************/void SListDestory(SListNode** single_list){assert(*single_list);SListNode* cur = *single_list;while (cur){SListNode* next = cur->_next;free(cur);cur = _next;}*single_list = nullptr;}
}

oj题

203. 移除链表元素

203. 移除链表元素 - 力扣(LeetCode)


/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* removeElements(ListNode* head, int val) {ListNode* cur = head;ListNode* prev = nullptr;while(cur){if(cur->val == val){if(prev == nullptr){head = head->next;cur = head;}else{prev->next = cur->next;cur = cur->next;}}else{prev = cur;cur = cur->next;}}return head;}
};

206. 反转链表

206. 反转链表 - 力扣(LeetCode)


/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* reverseList(ListNode* head){ListNode* ret = nullptr;ListNode* cur = head;while(cur){ListNode* next = cur->next;cur->next = ret;ret = cur;cur = next;}return ret;}
};

链表中倒数第k个结点_牛客题霸_牛客网 (nowcoder.com)
 


        双指针实现。

易错:
        两个临界需要全部关注到。

  • 1,{1,2,3,4,5}
  • 5,{1,2,3,4,5}
/*
struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}
};*/
#include <asm-generic/errno.h>
class Solution {
public:ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {ListNode* cur = pListHead;while(k--){if(cur)cur = cur->next;elsereturn nullptr;}ListNode* prev = pListHead;while(cur){cur = cur->next;prev = prev->next;}return prev;}
};

(链表OJ题一定要确定边界,防止使用nullptr指针)

快慢指针

141.环形链表

141. 环形链表 - 力扣(LeetCode)


【解题思路】
        让一个指针从链表起始位置开始遍历链表,同时让一个指针从判环时相遇点的位置开始绕环
运行,两个指针都是每次均走一步,最终肯定会在入口点的位置相遇。

带头双向循环链表

#include <iostream>
#include <malloc.h>
#include <cassert>namespace qcr_list
{typedef int ListDataList;struct ListNode{ListDataList _data;ListNode* _next;ListNode* _prev;};// 带头+双向+循环链表增删查改实现ListNode* Init(){ListNode* head_node = (ListNode*)malloc(sizeof(ListNode));head_node->_prev = head_node;head_node->_next = head_node;return head_node;} // 创建新结点ListNode* ListCreate(ListDataList data){ListNode* new_node = (ListNode*)malloc(sizeof(ListNode));if(nullptr == new_node)perror("ListCreate::malloc");new_node->_data = data;new_node->_prev = new_node->_next = nullptr;return new_node;}// 双向链表尾插void ListPushBack(ListNode* pHead, ListDataList data){assert(pHead);ListNode* tail = pHead->_prev;ListNode* new_node = ListCreate(data);tail->_next = new_node;new_node->_next = pHead;new_node->_prev = tail;pHead->_prev = new_node;}   // 双向链表头插void ListPushFront(ListNode* pHead, ListDataList data){assert(pHead);ListNode* next = pHead->_next;ListNode* new_node = ListCreate(data);pHead->_next = new_node;new_node->_next = next;new_node->_prev = pHead;next->_prev = new_node;}// 双向链表尾删void ListPopBack(ListNode* pHead){assert(pHead);if(pHead->_next == pHead)return;ListNode* erase = pHead->_prev;erase->_prev->_next = pHead;pHead->_prev = erase->_prev;erase->_next = erase->_prev = nullptr;free(erase);erase = nullptr;}// 双向链表头删void ListPopFront(ListNode* pHead){assert(pHead);if(pHead->_next == pHead)return;ListNode* erase = pHead->_next;erase->_next->_prev = pHead;pHead->_next = erase->_next;erase->_next = erase->_prev = nullptr;free(erase);erase = nullptr;}// 双向链表插入void ListInsert(ListNode* pos, ListDataList data){assert(pos);ListNode* new_node = ListCreate(data);ListNode* prev = pos->_prev;prev->_next = new_node;new_node->_next = pos;new_node->_prev = prev;pos->_prev = new_node;}// 双向链表删除void ListErase(ListNode* pos){assert(pos);ListNode* prev = pos->_prev;ListNode* next = pos->_next;pos->_next = pos->_prev = nullptr;free(pos);pos = nullptr;prev->_next = next;next->_prev = prev;}// 双向链表打印void ListPrint(ListNode* pHead){assert(pHead);ListNode* cur = pHead->_next;while(pHead != cur){std::cout << cur->_data << "->";cur = cur->_next;}std::cout << "nullptr" << std::endl;}// 双向链表查找ListNode* ListFind(ListNode* pHead, ListDataList data){assert(pHead);ListNode* cur = pHead->_next;while(pHead != cur){if(data == cur->_data){return cur;}cur = cur->_next;}return nullptr;}// 双向链表销毁void ListPrint(ListNode* pHead){assert(pHead);ListNode* cur = pHead;while(nullptr != cur){if(cur == pHead){cur->_prev->_next = nullptr;}ListNode* next = cur->_next;cur->_next = cur->_prev = nullptr;free(cur);cur = next;}}
}

顺序表和链表的区别

顺序表和链表的区别
不同点
顺序表
链表
存储空间上
物理上一定连续
逻辑上连续,但物理上不一定连续
随机访问
支持O(1)
不支持:O(N)
任意位置插入 \ 删除元素
可能需要搬移元素,效率低O(N)
只需修改指针指向
插入
动态顺序表,空间不够时需要扩容
没有容量的概念
应用场景
元素高效存储+频繁访问
任意位置插入和删除频繁
缓存利用率

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/118011.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【计算机网络】HTTP

文章目录 1.HTTP概念2. URLurlencode 和 urldecode转义规则 3. HTTP的宏观理解HTTP的请求HTTP的响应 4. 见一见HTTP请求和响应请求报头 1. 模拟一个简单的响应response响应报头 2. 从路径中获取内容ReadFile函数的实现 3.不同资源进行区分反序列化的实现ReadOneLine函数的实现P…

如何将两个pdf合并成一个?pdf合并技巧分享

在日常工作过程当中&#xff0c;我们经常需要处理一些文件&#xff0c;而文件的处理往往是琐碎的&#xff0c;想要提高工作效率&#xff0c;需要选择一些合适的方法&#xff0c;并掌握一定的技巧&#xff0c;那么&#xff0c;如何将两个pdf合并成一个?pdf合并技巧有哪些呢?接…

hadoop学习:mapreduce入门案例四:partitioner 和 combiner

先简单介绍一下partitioner 和 combiner Partitioner类 用于在Map端对key进行分区 默认使用的是HashPartitioner 获取key的哈希值使用key的哈希值对Reduce任务数求模决定每条记录应该送到哪个Reducer处理自定义Partitioner 继承抽象类Partitioner&#xff0c;重写getPartiti…

ELK日志收集系统集群实验(5.5.0版)

目录 前言 一、概述 二、组件介绍 1、elasticsearch 2、logstash 3、kibana 三、架构类型 四、ELK日志收集集群实验 1、实验拓扑 2、在node1和node2节点安装elasticsearch 3、启动elasticsearch服务 4、在node1安装elasticsearch-head插件 5、测试输入 6、node1服…

redis实战-实现优惠券秒杀解决超卖问题

全局唯一ID 唯一ID的必要性 每个店铺都可以发布优惠券&#xff1a; 当用户抢购时&#xff0c;就会生成订单并保存到tb_voucher_order这张表中&#xff0c;而订单表如果使用数据库自增ID就存在一些问题&#xff1a; id的规律性太明显&#xff0c;容易被用户根据id的间隔来猜测…

JavaScript关于函数的小挑战

题目 回到两个体操队&#xff0c;即海豚队和考拉队! 有一个新的体操项目&#xff0c;它的工作方式不同。 每队比赛3次&#xff0c;然后计算3次得分的平均值&#xff08;所以每队有一个平均分&#xff09;。 只有当一个团队的平均分至少是另一个团队的两倍时才会获胜。否则&…

排盘程序算法探寻举例(陆先生八字)

算法实现&#xff1a; 1.庚生未月&#xff0c;燥土不能生金&#xff0c;日支申金为日主墙根&#xff0c;月干辛金比劫透出傍身&#xff0c;月干强。年干甲木自做寅木强根&#xff0c;又得月支乙木中气&#xff0c;甲木强旺有力&#xff0c;时干丙火七杀得未土余气&#xff0c;…

Spring 中存取 Bean 的相关注解

目录 一、五大类注解 1、五大类注解存储Bean对象 1.1Controller(控制器储存) 1.2Service(服务存储) 1.3Repository(仓库存储) 1.4Component(组件存储) 1.5Configuration(配置存储) 2、五大类注解小结 2.1为什么要这么多类注解 2.2 五大类注解之间的关系 二、方法注解 1.方法注…

linux编程第一部分总结

C多线程安全原则 对象析构很复杂&#xff0c;我们采用shared_ptr和weak_ptr来做 enable_shared_from_this<>是用来做回调的&#xff0c;因为多线程中可能对象的生命周期比传出去的this指针短&#xff0c;同时为了不延长对象的生命周期&#xff0c;我们把shared_ptr转成we…

c++ vs2019 cpp20规范的STL库的map与multimap源码分析

map就是一个红黑树。 标准平衡二叉树&#xff0c;要求左右子树的高度差不超过1 。红黑树只要求左右子树的高度差不超过一倍即可。兼顾了树平衡与效率。避免了AVL树的频繁调整树平衡。 b站 的“可雷曼土”大师&#xff0c;讲红黑树的理论讲的很透彻&#xff0c;再结合看代码&…

Linux-安装redis6.2.1及主备复制模式(replication)

Linux-安装redis6.2.1 下载redis6.2.1资源上传至安装目录解压及编译解压修改名称编译 修改配置文件主节点从节点 启动及测试启动主节点从节点 测试 下载redis6.2.1资源 地址》https://redis.io/download/ 上传至安装目录 例&#xff1a;/data/replication/ 解压及编译 解…

二进制安全虚拟机Protostar靶场 安装,基础知识讲解,破解STACK ZERO

简介 pwn是ctf比赛的方向之一&#xff0c;也是门槛最高的&#xff0c;学pwn前需要很多知识&#xff0c;这里建议先去在某宝上买一本汇编语言第四版&#xff0c;看完之后学一下python和c语言&#xff0c;python推荐看油管FreeCodeCamp的教程&#xff0c;c语言也是 pwn题目大部…

Jupyter lab 配置

切换jupyterlab的默认工作目录 在终端中输入以下命令 PS C:\Users\Administrator> jupyter-lab --generate-config Writing default config to: C:\Users\Administrator\.jupyter\jupyter_lab_config.py它就会生成JupyterLab的配置文件&#xff08;如果之前有这个文件的话…

(笔记五)利用opencv进行图像几何转换

参考网站&#xff1a;https://docs.opencv.org/4.1.1/da/d6e/tutorial_py_geometric_transformations.html &#xff08;1&#xff09;读取原始图像和标记图像 import cv2 as cv import numpy as np from matplotlib import pyplot as pltpath r"D:\data\flower.jpg&qu…

【数据结构】 二叉树面试题讲解->叁

文章目录 &#x1f30f;引言&#x1f332;[根据二叉树创建字符串](https://leetcode.cn/problems/construct-string-from-binary-tree/submissions/)&#x1f431;‍&#x1f464;题目描述&#xff1a;&#x1f431;‍&#x1f409;示例&#xff1a;&#x1f4cc;示例一&#x…

Flutter小功能实现-咖啡店

1 导航栏实现 效果图&#xff1a; 1.Package google_nav_bar: ^5.0.6 使用文档&#xff1a; google_nav_bar | Flutter Package 2.Code //MyBottomNavBar class MyBottomNavBar extends StatelessWidget {void Function(int)? onTabChange;MyBottomNavBar({super.key, …

iOS swift5 扫描二维码

文章目录 1.生成二维码图片2.扫描二维码&#xff08;含上下扫描动画&#xff09;2.1 记得在info.plist中添加相机权限描述 1.生成二维码图片 import UIKit import CoreImagefunc generateQRCode(from string: String) -> UIImage? {let data string.data(using: String.En…

若依 vue中el-radio无法默认选中

网上看了很多方法都不管用, 即便是element官方示例方法也不行 解决方法: html <el-form-item label"是否公开" prop"isOpen"><el-radio-group v-model"form.isOpen"><el-radio :label"0">不公开</el-radio>…

跳出Lambda表达式forEach()循环解决思路

背景 在一次需求开发时&#xff0c;发现使用Lambda的forEach()跳不出循环。如下示例代码&#xff0c;想在遍历满足条件时跳出循环。 public static void main(String[] args) {List<Integer> list Arrays.asList(1, 4, 5, 7, 9, 11);list.forEach(e -> {if (e % 2 …

Leetcode Top 100 Liked Questions(序号236~347)

236. Lowest Common Ancestor of a Binary Tree 题意&#xff1a;二叉树&#xff0c;求最近公共祖先&#xff0c;All Node.val are unique. 我的思路 首先把每个节点的深度得到&#xff0c;之后不停向上&#xff0c;直到val相同&#xff0c;存深度就用map存吧 但是它没有向…