写一下线性表

news2024/11/15 22:34:40

如果你是c语言, "不会"c++, 那么...

把iostream当成stdio.h
把cout当成printf, 不用管啥类型, 变量名字一给输出完事
把cin>>当成scanf, 变量名字一给输入完事
把endl当成\n, 换行.

哦对了, malloc已经不建议使用了, 现在使用new, 把new当作malloc, 把delete当作free就行

ok, 现在你掌握了c++的基础内容, 现在我们接着往下看...

感觉没啥好写的...背一下时空复杂度, 这两个我直接从gpt复制来的, 看看就行. 

1. 顺序存储结构(数组)

顺序存储结构用一段连续的内存空间依次存放线性表的元素。

  • 特点

    1. 内存位置连续,每个元素的存储位置都可以通过首地址和偏移量计算出来,访问速度快(时间复杂度为 (O(1)))。

    2. 插入和删除操作需要移动大量元素(最坏情况下时间复杂度为 (O(n)))。

    3. 存储空间在定义时需要预先分配,可能存在内存浪费或空间不足问题。

  • 常见操作

    1. 查找第 (i) 个元素:直接通过数组下标访问,时间复杂度为 O(1)。

    2. 插入元素:在指定位置插入新元素,需要将插入位置后的元素依次向后移动一位,时间复杂度为 O(n)。

    3. 删除元素:删除指定位置的元素,需要将删除位置后的元素依次向前移动一位,时间复杂度为 O(n)。

2. 链式存储结构(链表)

链式存储结构使用一组任意的存储单元存储线性表的元素,每个元素由一个数据域和一个指针域组成,指针域指向下一个元素的地址。

  • 特点

    1. 元素的存储位置不连续,通过指针链接各个元素。

    2. 插入和删除操作不需要移动其他元素,只需修改指针指向,时间复杂度为 (O(1))。

    3. 查找某个元素需要从头开始遍历,时间复杂度为 (O(n))。

  • 常见操作

    1. 查找第 (i) 个元素:需要从链表头开始遍历,时间复杂度为 (O(n))。

    2. 插入元素:只需修改插入位置前后的指针关系,时间复杂度为 (O(1))。

    3. 删除元素:只需修改删除位置前后节点的指针关系,时间复杂度为 (O(1))。

然后链表的创建摧毁, 没啥说的...

#include<string>
#include<iostream>
using namespace std;

struct Node
{
	int data;
	Node* next;
};

//print
void Print(Node* head)
{
	Node* current = head;
	while (current!= NULL)
	{
		std::cout << current->data << " ";
		current = current->next;
	}
	std::cout << std::endl;
}

//insert
void Insert(Node** head, int data)
{
	Node* newNode = new Node();
	newNode->data = data;
	newNode->next = *head;
	*head = newNode;
}

// 释放链表的内存
void freeList(struct Node* head) {
	struct Node* current = head;
	struct Node* next;
	while (current != NULL) {
		next = current->next; // 保存下一个节点
		delete current;       // 释放当前节点
		current = next;       // 移动到下一个节点
	}
}



int main()
{
	Node* head = NULL;
	Insert(&head, 1);
	Insert(&head, 2);
	Insert(&head, 3);
	Insert(&head, 4);
	Print(head);

	freeList(head);
	head = NULL;
;
	return 0;
}

对于查找, 删除, 写一下数组, 不难理解

#include<iostream>
using namespace std;

void printArray(int* arr, int size);
void deleteNode(int* arr, int size, int index);
void searchNode(int* arr, int size, int index);
void gotoNode(int* arr, int size, int index);

void test01()
{
	int array[10] = { 7,3,5,5,6,0,8,9,2,1 };
	int size = sizeof(array) / sizeof(array[0]);

	deleteNode(array, size, 3);printArray(array, size);
	searchNode(array, size, 5);
	gotoNode(array, size, 7);
}

//O(n)
void deleteNode(int* arr,int size, int index)
{
	for (auto i = 0; i != size;++i)
	{
		if (arr[i] == index)
		{
			for (auto j = i; j != size - 1; ++j)
			{
				arr[j] = arr[j + 1];
			}
			arr[size - 1] = 0;
		}
	}
}

//O(n)
void searchNode(int* arr, int size, int index)
{
	for (auto i = 0; i != size; ++i)
	{
		if (arr[i] == index)
		{
			cout << "Found at index " << i << endl;
			return;
		}
	}
	cout << "Not found" << endl;
}

//O(1)
void gotoNode(int* arr, int size, int index)
{
	if (index < 0 || index >= size)
	{
		cout << "Index out of range" << endl; return;
	}
	else
		cout << "Value at index " << index << " is " << arr[index] << endl;
}

void printArray(int* arr, int size) {
	for (auto i = 0; i != size; ++i)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
}


int main()
{
	test01();
}

查找删除也写一下链表, 也不难

#include<iostream>
using namespace std;

struct Node
{
	Node* next;
	int data;
	Node(int x = 10)
	{
		data = x;
		next = nullptr;
	}
};

//O(1)
void insert_front(Node** head, int x)
{
	Node* newNode = new Node(x);
	if (*head == nullptr)
	{
		*head = newNode;
		newNode->next = nullptr;
	}
	else
	{
		newNode->next = *head;
		*head = newNode;
		(*head)->next = nullptr;
	}
}

//O(n)
void insert_end(Node** head, int x)
{
	Node* NewNode = new Node(x);
	if (*head == nullptr)
		*head = NewNode;//newnode->next=nullptr;那么head指向新节点,next指向nullptr
	else
	{
		Node* iterator = (*head)->next;
		while (iterator->next!= nullptr)
			iterator = iterator->next;
		iterator->next = NewNode;
	}
}
//O(n)
void search(Node** head, int x)
{
	Node* iterator = *head;
	while (iterator!= nullptr)
	{
		if (iterator->data == x)
			cout << "Found" << endl;
		iterator = iterator->next;
	}
	if (iterator == nullptr)
		cout << "Not Found" << endl;
}

//O(n)
void delete_front(Node** head)
{
	if (*head == nullptr)
		cout << "List is empty" << endl;
	else
	{
		Node* temp = *head;
		*head = (*head)->next;
		delete temp;
	}
}
//O(n)
void delete_end(Node** head)
{
	if (*head == nullptr)
		cout << "List is empty" << endl;
	else
	{
		Node* iterator = *head;
		while (iterator->next->next!= nullptr)
			iterator = iterator->next;
		delete iterator->next;
		iterator->next = nullptr;
	}
}
//O(n)  (先查后删,出要是查...)
void delete_node(Node** head, int x)
{
	if (*head == nullptr)
		cout << "List is empty" << endl;
	Node* iterator = *head;
	while (iterator->next != nullptr && iterator->next->data != x)
	{
		iterator = iterator->next;
	}
	if (iterator->next == nullptr)
		cout << "Not Found" << endl;
	else
	{
		Node* temp = iterator->next;
		iterator->next = iterator->next->next;
		delete temp;
	}
}
//查不写了, 和上面那个一样.

//直接删节点
//也是, 先查后删, 主要是查...

后来我发现我们老师讲的就十分幽默...当然也很规范, 使用最好最坏平均分析

 翟旭你期末看到这里怎么不给我点赞啊

我们有单向链表双向链表循环链表, 一个个实现的话...

来吧那就.

单向我不写了, 上面那个就是

循环那个也差不多, 就是尾节点->next指向头节点

算了我直接写一下吧,  边写代码边写注释, 理解起来会很快

#include<iostream>
using namespace std;

//实现循环链表

//我们最好设置一个哨兵头节点

//定义节点结构
struct Node{
    int data;
    Node* next;

    Node(int x=0):data(x),next(NULL){};
};

//定义循环链表类

class CircularLinkedList {
private:
    Node* sentinel;//可以把他看做你熟知的head, 这有很多好处
public:
    //构造函数
    CircularLinkedList()
    {
        sentinel = new Node();
        sentinel->next = sentinel;//#1
    }
    //析构函数
    ~CircularLinkedList()
    {
        Node* current = sentinel->next;
        Node* temp = NULL;
        while (current != sentinel)
        {
            temp = current;
            current = current->next;
            delete temp;
        }
        delete sentinel;
    }
    //插入元素
    void insert(int value)
    {
        Node* new_node = new Node(value);
        new_node->next = sentinel->next;
        sentinel->next = new_node;
    }
    //删除元素
    void remove(int value)
    {
        Node* current = sentinel->next;
        Node* previous = sentinel;
        while (current->data != value)
        {
            previous = current;
            current = current->next;
            if (current == sentinel->next)
                return;
        }
        previous->next = current->next;
        delete current;
    }
    //查找元素
    bool find(int value)
    {
        Node* current = sentinel->next;
        while (current->data != value)
        {
            current = current->next;
            if (current == sentinel->next)
                return false;
        }
        return true;
    }
    //打印链表
    void print()
    {
        Node* current = sentinel->next;
        do {
            cout << current->data << " ";
            current = current->next;
        } while (current != sentinel->next);
    }
};

双向稍微处理一下逻辑就好了

比如删除删除某个节点, 那么就直接考虑前后

我们使用ABC来表示, 删除B

那么BC双向链接断开, AB双向链接断开,有四条指针需要理解, B->next和front<-B都不需要了, B指针先delete然后赋值为nullptr, 然后 B->next和front<-B 都nullptr

A->next和front<-C悬空着, 他们俩正好连在一起

你可以把它想象成一个乐高, 前面和面一个插入一个被插入

再比如插入, 还是ABC距离, 那么AC断开, A->next和front<-C悬空, 接到B上, 然后B一前一后分别插入A和被C插入, ok.

很简单的逻辑. 和单向链表真的很像, 顺便一提, 你可以把单向列表想象成一个平头乐高块, 都见过吧, 顶上是光滑的, 没有头的那种. 

今天儿子驾考过了, 开心

ok.

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TCP四大拥塞控制算法总结

四大算法&#xff1a;1.慢启动&#xff0c;2.拥塞避免&#xff0c;3.拥塞发生&#xff0c;4.快速恢复。 慢启动&#xff1a; 首先连接建好的开始先初始化拥塞窗口cwnd大小为1&#xff0c;表明可以传一个MSS大小的数据。 每当收到一个ACK&#xff0c;cwnd大小加一&#xff0c…

链表(单向不带头非循环)

声明 链表题考的都是单向不带头非循环&#xff0c;所以在本专栏中只介绍这一种结构&#xff0c;实际中链表的结构非常多样&#xff0c;组合起来就有8种链表结构。 链表的实现 创建一个链表 注意&#xff1a;此处简单粗暴创建的链表只是为了初学者好上手。 public class MyS…

FreeRtos同步互斥与通信

前言&#xff1a;本篇笔记参考韦东山老师&#xff0c;视屏教程&#xff0c;连接放在最后。 同步与互斥的基本概念 同步&#xff1a;Task_a执行完成之后Task_b才能执行&#xff0c;让任务按照特定的顺序去执行。 互斥&#xff1a;当Task_a访问临界资源进行执行&#xff0c;Task…

(done) 声音信号处理基础知识(2) (重点知识:pitch)(Sound Waveforms)

来源&#xff1a;https://www.youtube.com/watch?vbnHHVo3j124 复习物理知识&#xff1a; 声音由物体的振动产生 物体振动会导致空气分支振荡 某一处的空气气压变化会创造一个波 声音是机械波 空气的振荡在空间中传递 能量从空间中的一个点到另一个点 机械波需要媒介&#x…

LabVIEW编程能力如何能突飞猛进

要想让LabVIEW编程能力实现突飞猛进&#xff0c;需要采取系统化的学习方法&#xff0c;并结合实际项目进行不断的实践。以下是一些提高LabVIEW编程能力的关键策略&#xff1a; 1. 扎实掌握基础 LabVIEW的编程本质与其他编程语言不同&#xff0c;它是基于图形化的编程方式&…

【Taro】初识 Taro

笔记来源&#xff1a;编程导航。 概述 Taro 官方文档&#xff1a;https://taro-docs.jd.com/docs/ &#xff08;跨端开发框架&#xff09; Taro 官方框架兼容的组件库&#xff1a; taro-ui&#xff1a;https://taro-ui.jd.com/#/ &#xff08;最推荐&#xff0c;兼容性最好&…

第四范式发布AIGS Builder企业级软件重构助手,以生成式AI重构企业软件

产品上新 Product Release 今天&#xff0c;第四范式发布企业级软件重构助手——AIGS Builder&#xff0c;可快速重构软件交互体验。传统的企业软件开发&#xff0c;每次迭代通常要以月计。基于第四范式AIGS Builder大模型&#xff0c;用生成式Agent替代复杂的界面&#xff0c;…

为什么 AVIF 将成为下一代图片格式之王

AVIF的卓越优势 AVIF&#xff08;AV1 Image File Format&#xff09;正在迅速崛起&#xff0c;成为下一代网络图片格式的有力竞争者。作为基于AV1视频编码技术的图像格式&#xff0c;AVIF在多个方面展现出了令人瞩目的性能。 1. 卓越的压缩效率 与JPEG和WebP相比&#xff0c…

torch模型量化方法总结

0.概述 模型训练完成后的参数为float或double类型&#xff0c;而装机&#xff08;比如车载&#xff09;后推理预测时&#xff0c;通常都会预先定点&#xff08;量化&#xff09;为int类型参数&#xff0c;相应的推理的精度会有少量下降&#xff0c;但不构成明显性能下降&#…

CO-锁存器(Latch)

1.描述 锁存器(Latch)&#xff0c;是数字电路中的一种具有记忆功能的逻辑元件&#xff0c;是一种对脉冲电平敏感的存储单元电路&#xff0c;可以在特定输入脉冲电平作用下改变状态&#xff0c;利用电平控制数据的输入&#xff0c;包括不带使能控制的锁存器和带使能控制的锁存器…

sql执行流程经典案例分析

现在有联合索引(a,b),select* form tb where b xx group by a执行流程是什么样子的? CREATE TABLE IF NOT EXISTS test(id INT(10) NOT NULL AUTO_INCREMENT COMMENT主键,a INT(10) NULL,b INT(10) NULL,PRIMARY KEY(id),INDEX idx_a_b(a,b))ENGINE INNODB;INSERT INTO test…

【Unity-UGUI组件拓展】| Image 组件拓展,支持FIlled和Slice功能并存

🎬【Unity-UGUI组件拓展】| Image 组件拓展,支持FIlled和Slice功能并存一、组件介绍二、组件拓展方法三、完整代码💯总结🎬 博客主页:https://xiaoy.blog.csdn.net 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉 🎄 学习专栏推荐:Unity系统学习专栏 🌲 游戏…

Linux:login shell和non-login shell以及其配置文件

相关阅读 Linuxhttps://blog.csdn.net/weixin_45791458/category_12234591.html?spm1001.2014.3001.5482 shell是Linux与外界交互的程序&#xff0c;登录shell有两种方式&#xff0c;login shell与non-login shell&#xff0c;它们的区别是读取的配置文件不同&#xff0c;本…

TypeScript入门 (三)数据类型

引言 大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年9月学习赛的TypeScript学习总结文档。本文旨在全面介绍 TypeScript 中的各种数据类型&#xff0c;帮助读者深入理解每种数据类型的用法、内置属性…

LabVIEW提高开发效率技巧----自动化测试和持续集成

在大型项目中&#xff0c;自动化测试和持续集成是提高开发效率和代码质量的关键手段。通过这些技术&#xff0c;开发者能够在开发的早期阶段快速发现问题&#xff0c;减少后期调试的工作量&#xff0c;并且能够确保代码的稳定性和可维护性。以下是这两个概念如何在LabVIEW开发中…

Docker Networking Tutorial (Bridge - None - Host - IPvlan - Macvlan )

In this article, We will talk about the network of docker. Therere have five types of docker network. 一、Bridge The default network of docker network type. You can use : docker network ls docker network create --driver bridge my_bridge_network ##The CID…

什么是 GPT?通过图形化的方式来理解 Transformer 架构

Predict, sample, repeat 预测、取样、重复 GPT 是 Generative Pre-trained Transformer 的缩写。首个单词较为直接&#xff0c;它们是用来生成新文本的机器人。“Pre-trained” 指的是模型经历了从大量数据中学习的过程&#xff0c;这个词暗示了该模型还有进一步在特定任务中…

移动技术开发:ListView水果列表

1 实验名称 ListView水果列表 2 实验目的 掌握自定义ListView控件的实现方法 3 实验源代码 布局文件代码&#xff1a; activity_main.xml: <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.androi…

Java 中Lock接口锁的使用

一. Lock接口下的实现类 在Java中&#xff0c;Lock 接口是 java.util.concurrent.locks 包中的一部分&#xff0c;它提供了比 synchronized 更丰富的锁操作。Lock 接口的实现类包括 ReentrantLock&#xff08;可重入锁&#xff09;、ReadWriteLock&#xff08;读写锁&#xff…

从零开始学习TinyWebServer

写在前面 项目参考&#xff1a;https://github.com/qinguoyi/TinyWebServer 写作框架/图参考&#xff1a;https://blog.csdn.net/qq_52313711/article/details/136356042?spm1001.2014.3001.5502 原本计划是&#xff0c;先将项目代码大概看一遍&#xff0c;然后再着手实现一下…