链表和顺序表的一些区别

顺序表与链表是非常基本的数据结构,它们可以被统称为线性表。

线性表(Linear List)是由 n(n≥0)个数据元素(结点)a[0],a[1],a[2]…,a[n-1] 组成的有限序列。

顺序表和链表,是线性表的不同存储结构。它们各自有不同的特点和适用范围。针对它们各自的缺点,也有很多改进的措施。

一、顺序表

顺序表一般表现为数组,使用一组地址连续的存储单元依次存储数据元素,如图 1 所示。它具有如下特点:

  • 长度固定,必须在分配内存之前确定数组的长度。
  • 存储空间连续,即允许元素的随机访问。
  • 存储密度大,内存中存储的全部是数据元素。
  • 要访问特定元素,可以使用索引访问,时间复杂度为 O(1)O(1)
  • 要想在顺序表中插入或删除一个元素,都涉及到之后所有元素的移动,因此时间复杂度为 O(n)O(n)

图 1 顺序表

顺序表最主要的问题就是要求长度是固定的,可以使用倍增-复制的办法来支持动态扩容,将顺序表变成“可变长度”的。

具体做法是初始情况使用一个初始容量(可以指定)的数组,当元素个数超过数组的长度时,就重新申请一个长度为原先二倍的数组,并将旧的数据复制过去,这样就可以有新的空间来存放元素了。这样,列表看起来就是可变长度的。

一个简单的实现如下所示,初始的容量为 4。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <string.h>
struct sqlist {
    int *items, size, capacity;
    sqlist():size(0), capacity(4) {
        // initial capacity = 4
        items = new int[capacity];
    }
    void doubleCapacity() {
        capacity *= 2;
        int* newItems = new int[capacity];
        memcpy(newItems, items, sizeof(int)*size);
        delete[] items;
        items = newItems;
    }
    void add(int value) {
        if (size >= capacity) {
            doubleCapacity();
        }
        items[size++] = value;
    }
};

这个办法不可避免的会浪费一些内存,因为数组的容量总是倍增的。而且每次扩容的时候,都需要将旧的数据全部复制一份,肯定会影响效率。不过实际上,这样做还是直接使用链表的效率要高,具体原因会在下一节进行分析。

二、链表

链表,类似它的名字,表中的每个节点都保存有指向下一个节点的指针,所有节点串成一条链。根据指针的不同,还有单链表、双链表和循环链表的区分,如图 2 所示。

图 2 链表

单链表是只包含指向下一个节点的指针,只能单向遍历。

双链表即包含指向下一个节点的指针,也包含指向前一个节点的指针,因此可以双向遍历。

循环单链表则是将尾节点与首节点链接起来,形成了一个环状结构,在某些情况下会非常有用。

还有循环双链表,与循环单链表类似,这里就不再赘述。

由于链表是使用指针将节点连起来,因此无需使用连续的空间,它具有以下特点:

  • 长度不固定,可以任意增删。
  • 存储空间不连续,数据元素之间使用指针相连,每个数据元素只能访问周围的一个元素(根据单链表还是双链表有所不同)。
  • 存储密度小,因为每个数据元素,都需要额外存储一个指向下一元素的指针(双链表则需要两个指针)。
  • 要访问特定元素,只能从链表头开始,遍历到该元素,时间复杂度为 O(n)O(n)
  • 在特定的数据元素之后插入或删除元素,不涉及到其他元素的移动,因此时间复杂度为 O(1)O(1)。双链表还允许在特定的数据元素之前插入或删除元素。

在上一节说到,利用倍增-复制的办法,同样可以让顺序表长度可变,而且效率比链表还要好,下面就简单的实现一个单链表来验证这一点,至于元素插入的顺序就不要在意了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h>
#include <time.h>
  
struct node {
    int value;
    node *next;
};
struct llist {
    node *head;
    void add(int value) {
        node *newNode = new node();
        newNode->value = value;
        newNode->next = head;
        head = newNode;
    }
};
int main() {
    int size = 100000;
    sqlist list1;
    llist list2;
    long start = clock();
    for (int i = 0;i < size;i++) {
        list1.add(i);
    }
    long end = clock();
    printf("sequence list: %d\n", end - start);
    start = clock();
    for (int i = 0;i < size;i++) {
        list2.add(i);
    }
    end = clock();
    printf("linked list: %d\n", end - start);
    return 0;
}

在我的电脑上,链表的耗时大约是顺序表的 4~8 倍。会这样,是因为数组只需要很少的几次大块内存分配,而链表则需要很多次小块内存分配,内存分配操作相对是比较慢的,因而大大拖慢了链表的速度。这也是为什么会出现内存池。

因此,链表并不像理论分析的那样美好,在实际应用中要受很多条件制约,一般情况下还是安心用顺序表的好。

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

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

相关文章

ANCS推送简介

总体原理 ANCS通过蓝牙BLE 4.0实现&#xff0c;仅支持iPhone 4S及以上且系统版本在IOS 7以上的手机&#xff0c;同时在外设端需要支持蓝牙4.0协议。 1、外设端进行广播&#xff0c;手机打开蓝牙&#xff0c;搜索外设&#xff0c;连接外设&#xff0c;之后进行绑定&#xff08;这…

好记性不如烂笔头,记录几个常用的Linux操作

作者&#xff1a;老王Shell公共函数库Linux系统里有一些公共的Shell函数库可供使用&#xff0c;最重要的是/etc/rc.d/init.d/functions&#xff0c;在/etc/init.d目录下有很多脚本都用到了这个函数库&#xff0c;里面提供了很多有用的方法&#xff0c;比如&#xff1a;killproc…

用matlab简单电路模型,基于MATLAB的电路模型仿真应用

基于MATLAB的电路模型仿真应用实验指导书一、实验目的1、掌握采用M文件及SIMULINK对电路进行仿真的方法。2、熟悉POWERSYSTEM BLOCKSET 模块集的调用、设置方法。3&#xff0e;进一步熟悉M脚本文件编写的方法和技巧。二、实验原理1、通过M文件实现电路仿真的一般仿真步骤为&…

春节期间小游戏同时在线人数最高达2800万人/小时

微信官方发布2018年春节期间微信数据报告&#xff1a;除夕至初五&#xff0c;总共有2,297亿条微信消息&#xff0c;28亿条微信朋友圈成功发出&#xff0c;音视频通话总时长175亿乙分钟。其中&#xff0c;90后用广的消息发送量占总量的42.5%&#xff0c;80后用户25.9%&#xff0…

C语言中* 和

&x是对x变量取地址&#xff0c;也就是返回的是x的地址。 int *i;这里面的*说明变量i是一个指针&#xff0c;存的是一个地址。 而 *i整体代表的是一个数值&#xff0c;例如可以int *i 5 这里整体的*i代表的是5&#xff0c;而i代表的是这个值存储的地址

餐馆的故事-浅析职责链模式

我们在餐馆吃饭的时候&#xff0c;一般都是在拿到菜单后&#xff0c;选择喜欢的菜&#xff0c;然后通知服务员。服务员会将我们的定单交给大厨&#xff0c;大厨可能会亲自去做这道菜&#xff0c;也可能安排给小厨来做&#xff0c;总之&#xff0c;我们不用担心他们没有人做菜&a…

JDBC数据对象存储

一&#xff1a;将查询的结果生成对象&#xff0c;储存在数组中。 1 package day31;2 3 import java.sql.Connection;4 import java.sql.PreparedStatement;5 import java.sql.ResultSet;6 import java.sql.SQLException;7 import java.util.ArrayList;8 9 public class java_ob…

个人工作13年的一些人生真实领悟

此文不定期的更新&#xff0c;想起来就写一些&#xff0c;我都忘了我曾经会过什么了。你可能会在许多的文章里看到类似的&#xff0c;但这些是我个人的真实体会。 1 技术服从于业务 此问题以前的一个文章提过&#xff0c;不再多说。 适用于大多数对技术的盲目崇拜者。在绝大…

matlab非齐次方程组的通解,用matlab求非齐次线性方程组的通解?

先向大家介绍一下非齐次线性方程组。所谓非齐次线性方程组就是方程组等号右边的常数项不全为零的线性方程组。全部等于零时&#xff0c;就称为齐次线性方程组。下面我们就讲解一下如何利用matlab快速求非齐次线性方程组的通解。工具/材料matlab电脑操作方法01线性方程组Axb的求…

Linux 终端仿真程序Putty

PuTTY是一个Telnet、SSH、rlogin、纯TCP以及串行接口连接软件。较早的版本仅支持Windows平台&#xff0c;现在的版本中开始支持各类Unix平台。 用linux作为桌面系统&#xff0c;身为工程师很多时候需要通过Telnet、SSH协议进行远程管理&#xff0c;通过串口进行设备配置。Putty…

Mysql 数据库水平分表 存储过程

数据库存储量达到一定程度的时候&#xff0c;就需要进行分表以减轻检索的消耗。 常用的分表方式包括水平和垂直分表。本次进行的是按照uid进行水平分表。 ##分表思路&#xff1a; 水平分表平均的将数据按照特定方式分配到多个表中。理论上每个表的访问频次和数据量都是同一水平…

中国架构师,名符其实有多少?

先说一下读后感&#xff1a;我前段时间去过几个公司面试架构师&#xff0c;要求还是蛮高的&#xff0c;要熟悉大数据量处理&#xff0c;要熟悉高并发&#xff0c;要熟悉XX体系架构&#xff0c;要能在关键技术上实现突破。总之&#xff0c;架构错了&#xff0c;就啥都错了。呵呵…

粗识静态链表

为了弥补链表在内存分配上的不足&#xff0c;出现了静态链表这么一个折中的办法。静态链表比较类似于内存池&#xff0c;它会预先分配一个足够长的数组&#xff0c;之后链表节点都会保存在这个数组里&#xff0c;这样就不需要频繁的进行内存分配了。 当然&#xff0c;这个方法的…

php用date语句获取时间,关于php date()函数获取时间的设置和使用方法

date()函数是PHP自带的时间函数&#xff0c;可以获取当前服务器的时间echo date(Y-m-d H:i:s); //输出:2020-05-18 11:02:35date()函数中可以使用的字母含义&#xff1a;a-"am"(上午)或者"pm"(下午)A-"AM"或者"PM"Y-年&#xff0c;显示…

Django_form补充

问题1: 注册页面输入为空&#xff0c;报错&#xff1a;keyError&#xff1a;找不到passworddef clean(self): print("---",self.cleaned_data) # if self.cleaned_data["password"]self.cleaned_data["repeat_password"]: …

WF4.0:NativeActivity中的错误处理

备注&#xff1a;这篇文章的使用环境是.NET framework 4.0 RC 1 在WF4中创建native活动时&#xff0c;NativeActivity是非常强大的。其众多的功能之一是围绕错误处理。 调度子活动的时的基本错误处理。 当NativeActivity执行的时候&#xff0c;它是通过一个NativeActivityConte…

程序员提高建议之踏踏实实“扎马步”

踏踏实实“扎马步” 今天无意中看了“校长”的“程序员&司机”&#xff0c;其中谈到了关于程序员速成的问题。其实速成班毕业的“系统杀手”早已在遍布大江南北&#xff0c;只是在互联网时代&#xff0c;互联网的应用型软件生命周期越来越短&#xff0c;业务驱动主导…

c语言scanf返回值

1. scanf 函数是有返回值的&#xff0c;它的返回值可以分成三种情况1) 正整数&#xff0c;表示正确输入参数的个数。例如执行 scanf("%d %d", &a, &b);如果用户输入"3 4"&#xff0c;可以正确输入&#xff0c;返回2&#xff08;正确输入了两个变量…

gpgga格式读取MATLAB,GPS编码格式及读取.doc

GPS接收机只要处于工作状态就会源源不断地把接收并计算出的GPS导航定位信息通过串口传送到计算机中。前面的代码只负责从串口接收数据并将其放置于缓存&#xff0c;在没有进一步处理之前缓存中是一长串字节流&#xff0c;这些信息在没有经过分类提取之前是无法加以利用的。因此…

Cadence 电源完整性仿真实践(二)

转载于:http://blog.csdn.net/wu20093346/article/details/38050917 通过以上步骤对每个平面进行了单节点分析并观测了响应曲线&#xff0c;接下来将观测平面对的目标阻抗是否满足要求&#xff0c;通过选择电容器的方法来减小含有电容器阻抗响应曲线中的反谐振波峰。在SigWave窗…