链表
在各种编程语言中,数组的使用极为广泛,因为使用数组可以按顺序结构储存打量数据,并且通过数组下标可以极为方便快捷的实现对数组中元素的读取,同时,顺序的存储结构使得内存空间得以最大程度的利用。然而有得必有失,顺序的存储结构使得数组在被定义时即赋予固定的存储空间,并且在存储在后续的操作中无法改变。如此一来便导致不能随意在数组中添加数据元素,并且当数组中存储的元素较少时会造成存储空间的浪费。此外,顺序的存储结构为数组的插入和删除操作带来了不便,每执行一次删除或插入操作都需移大量的数据元素,导致硬件性能的浪费。
而链表的出现,较为恰当的解决了数组中出现的上述问题。链表由数量不限的节点组成,节点在内存空间上的存储位置并非连续存储,而是随机分配位置。对于单链表而言,每个节点中存储的内容包括该节点的数据元素以及指向下一个节点的地址。单链表的节点类的定义如下:
Public class Node{
Private Object element;//存储节点的数据元素
Private Node next;//存储当前节点的下一个节点(即其地址),尾节点的next值为null
Public get方法……
}
单链表的访问:在对单链表进行访问时无法像数组那样通过下标直接访问,每次访问都必须通过头结点,从头结点的数据元素开始访问,并根据头结点中存储的下一节点的地址访问下一节点,依次类推,借助每个节点中存储的下一节点的地址便可实现对在内存空间上分散存储的链表的全部节点实现有序的访问。
(Root)Element,next-> Element,next->……-> Element,next-> Element,next-> Element,null
单链表的添加、插入和删除元素:因为链表节点在内存空间上的散列存储,使得使用者可以在单链表中任意添加、插入或删除元素,同时无需移动其它元素,仅需改变相邻两个节点中地址的指向即可,以单链表的插入操作为例:
//在节点node后插入节点node1
Node temp = node.next;//定义一个临时变量用于存储node节点的下一个节点
node.next = node1;//将node1的地址赋给node.next,即让node.next指向node1
node1.next = temp;// 将插入前node的下一个节点地址赋给node1.next,让node.next指向该节点
//单链表的删除操作相反
双链表:
双链表即单链表的升级版,解决了单链表在访问过程中只能单向进行的缺陷(即只能通过上一个元素访问到其后一个元素,而不能反向进行)。双链表的具体实现方式为相对于单链表在每个节点中额外增加一个Node型变量,用于存储上一个节点的地址,如:
Public class Node{
Private Object element;//存储节点的数据元素
Private Node front;//存储当前节点的上一个节点(即其地址),头点的front值为null
Private Node next;//存储当前节点的下一个节点(即其地址),尾节点的next值为null
Public get方法……
}
循环链表:
解决单链表只能单向访问数据元素的另一个方法就是循环链表。所谓循环链表就是在单链表的基础上,将单链表的头结点和尾节点相连,即将尾节点中的next值存储为头结点,实现对链表的循环访问。