Java教程

数据结构与算法-------数组与链表

本文主要是介绍数据结构与算法-------数组与链表,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

想给老衲说:数组和链表放在一起研究,能对比两种数据结构的优点与不足!

Array数组

        数组不陌生吧!数组一般来说都是内存里连续的一段存储区域。          

         最左边这幅图,0~8表示的是数组的下标,咱们可以通过数组下标随机访问这个数组中任意一个元素!右边这里面8位的一串数字这里是内存地址(这里只是示例,真正的可能还会涉及到虚拟内存,寻址算法)!

Array->查找(search) 时间复杂度是O(1)

        右边这幅图指的意思是,Memory Controller(内存管理器)可以通过内存管理器实现对任何下标位置的数组元素进行访问。因此访问任何一个数组元素的时间复杂度是O(1),因为他通过内存管理器通过一次操作就可以拿到元素的值。

Array->插入(insert)  时间复杂度是O(N)

        数组是内存里一段连续的存储区域!

如下图,要把D插入到下标为3的位置处,需要分别挪动E,F,G元素,然后把D插入进去!也就是时间复杂度的话并不是O(1)的。是挪动要插入位置后面的全部元素,因此是O(n)的时间复杂度。

                           

 这里在深入一下

        1.最好插入情况下,刚好插在最屁股后面,时间复杂度是O(1)

        2.最坏插入情况下,刚好插在最前面,就需要挪动数组里面所有的元素,时间复杂度是O(n)

那么平均下来,插在最中间,时间复杂度为O(n/2),时间复杂度为O(n)的!(声明一下,虽然时间复杂度是O(N/2),在表示法里,一般n旁边的乘积是阿拉伯值的话就可以忽略的!

Array->删除(delete)时间复杂度是O(N)

        数组的删除跟上面的插入,是一样的情况,删除同样也需要挪动元素,以保证他们的顺序存储! 平均值也是O(N/2) ,最后时间复杂度也是O(N)

                          

List 链表--->主要介绍两种链表:单链表和双链表

        一般来说用于两种使用场景:

  1.改善插入和删除操作,你想改善插入和删除,并且这两种操作用的较频繁,不想浪费时间

        因为跟数组对比的话:链表的插入和删除都是O(1)的,数组的话是O(N).这也就是链表的优势!

  2. 不知道有多少个元素存在 ,来一个元素咱就往后面插一个

        相比较于数组,数组刚开始就得知道元素的大小,针对于这种情况下不适用!

Linked List 单链表

        

单链表:从图中可以看出是由一个一个的结点通过next指针串起来,形成一个表,这就是单链表!

链表单个结点一般结构为:数据域和指针域

数据域:图中用value来表示,可以存放任何类型的数据(线程池、内存池结构实现方式)

指针域:不知道老衲对指针是否了解,如果不了解在数据结构中寸步难行的!

简单介绍一下指针: 

        老衲你知道变量是什么吗?数据是什么?看最下面那张图

        其实在数据是什么那篇博客中提到了,变量是存储数据的容器。但是没说仔细了。

int a = 5;
int b = 2;
int c = 0;

变量就是图中a,b,c,它存储的数据就分别是5,2,0。变量是用来存放东西的,那么肯定能存放地址,专门存放两一个变量的地址,这个变量就叫指针变量!

struct List{
    int data; //数据域
    List* next; //指针域
}Node;

那么,上图中指针域,List* 表示变量的类型,是链表结点的类型,因此啊,next就是一个用来存放链表结点的指针变量。怎么存?

现在有结点  a,b

  a.next = &b;   //这就表示结点a有个指针变量存放了一个结点的地址,这个节点地址是b

List链表------>插入  时间复杂度O(1)

        要插入新的结点,需要两步:因为是2步,所以时间复杂度是O(1),如果是100步他也是O(1),因为1,2,3,4~100这是常数,O(1)表示常数时间复杂度

  1. 把新结点new node 的next里面存进NODE下一个节点的地址
  2. 把结点NODE的next存进去new node结点地址

 

 List链表-------->删除 时间复杂度O(1)

        删除操作的话,也是分为两步:

  1. 先把NODE的next存放Target node的next指向的那个地址
  2. 然后在Target NODE的指向null,这就完成了

注意的是,释放后的target node结点要释放

 双链表--->Double linked List

        双链表只是比单链表再多了一个指针域

 单个结点的表现形式为:

struct List{
    int data;    //数据域
    List* next;   //下一个节点的指针域
    List* prev;   //前一个节点的指针域
};

总结:

        数组和链表的话各有优缺点,可以因为具体使用到的场景,来挑选不同的数据结构!

数组:查找O(1)比链表快,但是插入和删除都是O(N)的,就比链表慢很多了

链表:查找O(n)他需要从头挨个遍历,才能找到,不能通过下标来查询。

        双向链表的改善了单链表的查找效率,因为他它具有遍历前面结点和后面结点的能力,可以使用二分查找等方式!

结束语:老衲,你理解了吗?注意多联系链表的插入节点和删除操作,就2步不可逆的!

这篇关于数据结构与算法-------数组与链表的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!