1.线性表:
数据结构的四种逻辑结构:集合、线性、树形、网状
linearity = {D,R}
D ={a1,a2,a3,a4} R = {<a1,a2>,<a2,a3>,<a3,a4>}
a1元素称为第一个元素,其他的元素都有一个直接前驱,a4元素称为最后一个元素,其他的元素都有一个直接后继
1.1 线性表的抽象数据类型
ADT List{
数据对象:D ={ai 属于某个数据类型, i=0,1,2,3...}
D = {a0,a1,a2,a3,a4...an},所有元素都是相同的数据类型
数据关系:R={<ai,ai+1>}
数据操作:getSize():返回线性表中元素的个数
isEmpty():判断线性表是否为空,线性为空返回true,否则返回false
insert(i,e):在线性表的i索引值位置插入元素e
contains(e):在线性表中判断是否存在元素e,存在返回true,
indexOf(e):返回元素e在线性表中的索引值,如果不存在元素e返回-1
remove(e):删除线性表中第一个与e相同的元素,删除成功返回删除的元素
remove(i):删除线性表中指定索引值的元素,返回删除的元素
replace(i,e):把线性表中索引值为i的元素替换为元素e
get(i):返回线性表中索引值为i的元素
insertBefore(p,e):在线性表中元素p的前面插入元素e
insertAfter(p,e):在线性表中元素p的后面插入元素e
}List;
抽象数据类型可以对应一个JAVA类,数据对象与元素之间的关系可以通过成员变量来存储或者表示,数据操作可以通过一组方法来实现
1.2 List接口
使用Java中的接口来表示ADT中的数据操作,数据对象与元素之间的关系,可以通过成员变量来存储和表示,数据操作可以通过一组方法来实现
1.3线性表的顺序存储与实现
线性表的顺序存储就是使用一组地址连续的存储空间来依次存储线性表中元素, 以数据元素在计算机内存的地址相邻性表示数据元素之间的关系
插入元素:
public class MyArrayList implements MyList{
private Object [] elements;
private static final int DEAFULY_CAPACITY = 16; //数组默认初始容量
private int size; //保存数据元素的个数
//构造方法
public MyArrayList(){
elements = new Object[initialCapacity];
}
public MyArrayList(int initialCapacity){
elements = new Object[initialCapacity];
}
//返回元素的个数
public int getSize(){
return size;
}
public boolean isEmpty(){
return size==0;
}
public void insert(int i,Object e){
//在线性表i的位置插入元素e
//判断索引值i是否越界
if(i<0 || i>size){
throw new IndexOutOfBoundsException(s)
}
//如果数组已满,对数组扩容
if(size >= elements.length){
expandSpace();
}
//从i开始,把元素依次后移
for(int j = size; j >I;j--){
elements[j] = elements[j-1];
}
//把元素e存储到i位置
elements[i] = e;
//元素的个数增加1
size++;
}
//数组扩容
private void expandSpace(){ //定义一个更大的数组,把原来数据内容复制到新的数组中,让原来数组名指向新的数组
Object[] newelements = new Object【elements。length*2】;
for(int I = 0; I<elements.length;i++){
newelements[I] = elements[I];
}
删除元素:
public Object remove(int i){
if(I<0 ||I>=size){
throw new IndexOutOfBoundsException(I+"越界“);
}
Object old = elements[I];
for(int j =I; j<size-1;j++){
elements[j] = elements[j+1];
}
elements[size-1] = null;
size--;
return null;
}
顺序存储的特点:优点:顺序存储是使用数组实现的,数组可以通过索引值快速访问每个元素
缺点:在插入或者删除元素时,需要移动大量元素,当线性表长度变换较大时,很难确定空间容量、
适合存储插入/删除操作比较少,主要是查询的元素
1.3线性表的链式存储与实现
1.单向链表:单链表,每个存储单元至少有两个存储域,一个用来存储数据,一个域保存下个存储单元的引用。
各个存储单元的地址可以是不连续的
2.通过单向链表实现线性表
public class MySingleLink implements MyList{
private Node head; // 头节点
private int size; //保存元素的个数
//返回元素的个数
public int getSize(){
return size;
}
//判断线性表是否为空
public boolean isEmpty(){
return size == 0;
}
//在线性表中插入元素
public void insert(int I,Object e){
//判断是否越界
if(I < 0 || I >size){
throw new IndexOutOfException(I+"越界");
}
//创建节点
Node newNode = new Node(e,null);
//头节点为null的情况,链表不存在,刚刚添加的节点就是头节点
if(head == null){
head = newNode;
}else{
//在0位置插入节点
if(I ==0){
newNode.next = head; //修改新节点的next域指向原来的头节点
head = newNode; //刚插入的节点就是新的头节点
}else{
//插入节点,先找到i-1这个节点
Node pNode = head;
for(int x = 1;x<I;x++){
pNode = pNode.next;
}
//注意,先修改新节点的next指针域,再修改i-1节点的指针域
newNode.next = pNode.next;
pNode.next = newNode;
}
size++;
}
//在0的位置插入节点
//插入节点
//元素个数加0
2.判断线性表中是否包含指定元素
public boolean contains(Object e){
return indexOf(e) >= 0;
}
//返回元素e在线性表中第一次出现的索引值
public int indexOf(Object e){ // 链表没有索引值
int I = 0; //保存元素e的索引值
Node pNode = head;
while( pNode != null){
if(e == null & pNode.data ==null){
return I;
}else if (e!=null && e.equals(pNOde.data)){
return I;
}
I++;
pNode = pNode.next;
}
return -1;
}
4.从线性表中删除指定索引的元素
public Object remove(int i){
//判断是否越界
if(I < 0 || I>=size){
throw new IndexOutOfBoundsException(I + "越界");
}
Node pNOde = head;
//删除头节点
if(I == 0){
head = head.next;
size--;
return pNode.data; //返回删除头节点的数据
}
//找到i-1节点
for(int x=1;x<I;x++){
pNode = pNode.next;
}
Object old = pNode.next.data; //保存删除节点的数据
pNode.next = pNode.next.next; //修改I-1节点的next指针域,让他指向I+1
size--;
return null;
5.把线性表中i索引值的元素替换为e
public Object replace(int I,Object e){
//判断是否越界
checkIndex(i);
//找到i节点
Node pNode = getNode(i);
Object old = pNode.data; //保存原来的数据
pNode.data = e; //替换
return old;
}
//返回线性表中i索引值的元素
public Object get(int i){
checkIndex(i);
Node pNode = getNode(i);
return pNOde.data;
}
//检查索引值是否越界
private void checkIndex(int i){
if(I<0 || I >=size){
throw new IndexOutOfBoundsException(I + "越界“);
}
//定义一个方法,返回i索引值的元素
private Node getNode(int I){
if(I < 0 || I >= size){
return null;
}
if(I == 0){
return head;
}
Node pNode = head;
for(int x = 1; x <= I ;x++){
pNode = pNode.next;
}
return pNode;
}