线性表、顺序表、广义表、链表......的关系、一招搞定N维数组的定义

前言

一直以来对各种数据结构的名称分的不是很清,今天刚醒就收到了学校寄来的教材,里面正好有一本数据结构,因此正好借此机会一次弄清这些概念的关系。在之前学java的时候我回想的我学过的各种语言,发现无论在学哪种语言的时候,对于n维数组是模模糊糊的,那时总结了一些不错东西,但是篇幅太小不易成文也就一直没写,今天理概念的时候正好想起,于是就一起写了。
文章分为两个部分,从标题易知:第一部分:数据结构的概念之间的联系。第二部分:N维数组
文章主要依据是数据结构的书,也就是下面的这本。学校发的教材

概念之间的关系

首先我大概罗列一下五花八门的概念:线性结构、线性表 、顺序表 、有序表 、顺序有序表、栈 、顺序栈、队列、循环队列、串、字符串 、数组 、一维数组 、N维数组 、字符数组 、指针数组、广义表、列表、非线性结构、树、图、链表 、 链式有序表、链栈、链队。
然后,直接上我总结的吧。

  • 线性结构
    • 线性表 (排序后:有序表)
      • 队列
    • 数组
    • 广义表(列表)
  • 非线性结构

不同存储结构下一些逻辑结构的不同叫法

结构顺序链式
线性表顺序表链表
有序表顺序有序表链式有序表
顺序栈链栈
队列循环队列链队

总结一下:

  • 其实会把各个名称搞混的最大原因是我们把不同结构混为一谈了,逻辑结构和存储结构是不能混为一谈的。
  • 存储结构也称为物理结构,我们常说数组(一维)是“逻辑相邻物理也相邻”的,也就是说,顺序结构的逻辑结构在内存上是连续的,地址是连续的,而链式的则是随机的。
  • 循环队列 因 防止发生假溢出而把顺序表设计成循环结构 而得名
  • 栈和队列是顺序表的阉割版,在功能上是线性表的子集(FIFO、FILO)
  • 数组和广义表都是线性表的推广
  • 一维数组可以看成是一个线性表,二维数组可以看成数据元素是线性表的线性表,通常用顺序结构来实现。
  • 数组和线性表都有随机存取能力,两个比较难区分,书中描述的我觉得也有些矛盾“其(数组)特点是结构中的元素本身可以是具有某种结构的数据”、“由于线性表的长度可变,c语言中可用动态分配的一维数组来描述”、“n个数据特性相同的元素构成的有限序列称为线性表”(所以数组的推广的啥?)(不过这无伤大雅,我就不纠结下去了)
  • 广义表(也称列表)则是摆脱数组和线性表的局限------广义表的数据元素可以是不一样的。通常用链式结构来实现。
  • 串,即字符串,顺序存储结构时,根据数组是否动态分配可分为堆式顺序存储结构和定长顺序存储结构。

树和图之类的概念很好区分我就不说了。

搞定N维数组

总所周知,数组有三步:声明,初始化,赋值。
其实只要搞清楚这三步的what、why、how处理N维数组就能得心应手了。下面我以java为例说明。
这世上任何一个程序员都无非在做两件事:实现需求、编译通过。如何实现需求是算法问题、是经验问题,而如何通过编译是语法记忆问题,要想快速而不易忘的记忆语法则需要充分的理解。这世上最懂语言的不是某某大牛,而是编译器。因此我们现在从编译器的角度来看,为什么要这三步?这三步分别是什么作用?
声明和赋值大家都懂不多说,变量声明和函数声明一样,不需要定义什么,作用就是让编译器知道你有这个变量。
问题最严重的是初始化,刚学编程的时候听过不少人说过“第一次赋值时初始化,后续的赋值是赋值 ”。这句话对于基本数据类型来说是这样的,最常见的就是 int i=0;但是对于数组这种复合数据类型来说则不是这样了。基本数据类型的初始化和赋值能混为一谈的原因是基本数据类型的存储空间是固定的,所以初始化这一步可有可无,意思就引申为第一次赋值了。对于数组来说,他的存储空间是位置的,编译器需要初始化这一步去确定分配多少空间。

数组的定义其实和赋值没有多大关系,初始化可以完成赋值工作,也可以不赋值,关键是分配空间。在定义数组的时候声明和初始化可以分开来,也可以一起进行。话不多说直接看码

int[] a;//声明
a=new int[2];//初始化
a[0]= 2;//赋值

上面代码数组声明和初始化是分开的,并且初始化的时候没有赋值。第二行中使用了new来进行初始化,在c++,new就是对c语言中的malloc封装,在java应该也差不多。malloc主要用来分配空间,由此可以看出初始化最重要的是让编译器知道要分配多少空间而不是赋值

int[][] b= {{4,3},{1,2}};//声明+初始化  自动计算大小
int[] c = new int[] {8,2,1,0,3};//声明+初始化  自动计算大小
int[][] d = new int[2][2];//初始化有三种方法,第一种只能和声明一起
//没有前面int[][]单独来看b= {{4,3},{1,2}};是一个赋值语句而不是初始化语句,赋值语句不能使用数组常量
int[][] e = new int[10][];//二维数组本质就是一维数组!
e[0]=new int[3];
e[1]=new int[] {1,2};
e[2]=new int[] {1,2,2,3,4,5,6,7,7,4};
e[2][2]=10;//赋值

这一段代码声明初始化一起执行,你会疑惑这不是赋值吗?不是的,必须注意的是数组赋值只能是一个个元素进行。这里用到的花括号那一坨东西叫做数组常量,只有初始化的时候可以使用(不信我们下面试一下),其实我认为这叫做数组字面量更合适,因为这和c语言的字面量差不多意思,c语言支持复合类型的字面量(当然常量和字面量会经常被搞混,如字符串常量)
值得一提的是,上面二维数组初始化的时候只给了第一个参数编译也能通过,这更加体现了二维数组实质就是就是元素为一维数组的一维数组,第一个参数是必须填的,第二个参数可填可不填,因为没人规定你必须在一维数组里面存放的一维数组必须是等长的。(其实根本原因就像我上面提到的,初始化的目的是为了知道存储空间大小,你的数组无论多长,数组指针的大小都是固定的,二维数组只管他多长,存多少个指针就行了,至于他的指针指向什么他不关心,只要你在用之前初始化那个指针就行了)

int[] f;
f= {1,2,3,4};//Array constant can only be used in initializers

你看,如果你像上面那样写eclipse会飘红提示你,数组常量只能被用于初始化!

好了,你弄清了数据结构的各种概念和java的N维数组了吗。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值