您的位置:首页 > 理论基础 > 数据结构算法

java数据结构之线性表

2017-05-08 15:30 337 查看
线性表概述
线性表是最基本、最简单、也是最常用的一种数据结构。在线性表中数据元素之间的关系是线性,数据元素可以看成是排列在一条线上或一个环上。
线性表分为静态线性表和动态线性表,常见的有顺序表(静态的)、单向链表(动态的)和双向链表(动态的)。
线性表的操作主要包括:
(1)计算表的长度n。
(2)线性表是否为空
(3)将元素添加到线性表的末尾
(4)获取第i个元素,0≤i < n。
(5)清除线性表
(6)返回列表中首次出现指定元素的索引,如果列表不包含此元素,则返回 -1。
(7)返回列表中最后一次出现指定元素的索引,如果列表不包含此元素,则返回 -1。
(8)将新元素插入第i个位置,0≤i < n,使原来的第i,i+1,…,n–1个元素变为第i+1,i+2,…,n个元素。
(9)更改第i个元素
(10)删除第i个元素,0≤i < n,使原来的第i+1,i+2,…,n–1个元素变为第i,i+1,…,n–2个元素
由此,对线性表抽象数据类型定义List接口如下:

模拟List接口

package com.example.code;

public interface MyList {
/**
* 将元素添加到线性表的末尾
*/
public void add(Object obj);

/**
* 清除线性表
*/
public void clear();
/**
* 获取i位置的元素
* @param i
* @return
*/
public Object get(int i);
/**
* 返回列表中首次出现指定元素的索引,如果列表不包含此元素,则返回 -1。
* @param obj
* @return
*/
public int indexOf(Object obj);
/**
* 在i后面插入一个元素e
* @param i
* @param obj
*/
public void insert(int i, Object obj);
/**
* 判断线性表是否为空
* @return
*/
public boolean isEmpty();
/**
* 回列表中最后出现指定元素的索引,如果列表不包含此元素,则返回 -1。
* @param obj
* @return
*/
public int lastIndexOf(Object obj);
/**
* 移除列表中指定位置的元素
* @param i
*/
public void remove(int i);
/**
* 移除列表中指定的元素
* @param obj
*/
public void remove(Object obj);
/**
* 用指定元素替换列表中指定位置的元素(可选操作)。
* @param i
* @param obj
*/
public Object set(int i, Object obj);
/**
* 返回线性表的大小
* @return
*/
public int size();
}

模拟ArrayList实现List接口

package com.example.code;

public class MyArrayList implements MyList {
private Object[] array;
private int size;

/**
* 自定义容量
* @param initialCapacity
*/
public MyArrayList(int initialCapacity){
if(initialCapacity<0){
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
array = new Object[initialCapacity];
}

//默认容量为10
public MyArrayList(){
this(10);
}

@Override
public int size() {
return size;
}

@Override
public boolean isEmpty() {
return size==0;
}

/**
* 数组下标检查
* @param index
*/
private void rangeCheck(int index){
if(index<0||index>=size){
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
}

/**
* 添加一个元素
* @param obj
*
* System提供了一个静态方法arraycopy(),我们可以使用它来实现数组之间的复制。其函数原型是:
* public static void arraycopy(Object src,int srcPos, Object dest, int destPos, int length)
* src:源数组;srcPos:源数组要复制的起始位置;dest:目的数组;destPos:目的数组放置的起始位置;length:复制的长度。
*/
@Override
public void add(Object obj) {
//数组扩容和数据的拷贝,重新new一个数组
if(size==array.length){
Object[] newArray = new Object[size*2+1];
System.arraycopy(array, 0, newArray, 0, array.length);
array = newArray;
}
array[size++] = obj;
}

@Override
public void clear() {
for (int i = 0; i < size; i++)
array[i] = null;
size = 0;

}
/**
* 通过索引获取元素
*/
@Override
public Object get(int i) {
rangeCheck(i);
return array[i];
}

@Override
public int indexOf(Object obj) {
if (obj==null) {
for (int i = 0; i < size; i++)
if (array[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (obj.equals(array[i]))
return i;
}
return -1;
}
/**
* 数组扩容
*/
private void ensureCapacity(){
//数组扩容和数据的拷贝
if(size==array.length){
Object[] newArray = new Object[size*2+1];
System.arraycopy(array, 0, newArray, 0, array.length);
array = newArray;
}
}
/**
* 将元素插入对应的位置
*/
@Override
public void insert(int i, Object obj) {
rangeCheck(i);
ensureCapacity(); //数组扩容
System.arraycopy(array, i, array, i+1, size-i);
array[i] = obj;
size++;
}
/**
* 回列表中最后出现指定元素的索引,如果列表不包含此元素,则返回 -1。
*/
@Override
public int lastIndexOf(Object obj) {
if (obj==null) {
for (int i=size-1; i>=0; i--)
if (array[i]==null)
return i;
} else {
for (int i=size-1; i>=0; i--)
if (obj.equals(array[i]))
return i;
}
return -1;
}

/**
* 通过索引删除元素
*/
@Override
public void remove(int i){
rangeCheck(i);

int numMoved = size - i - 1;
if (numMoved > 0){
System.arraycopy(array, i+1, array, i,numMoved);
}
array[--size] = null;
}
/**
* 删除对应的元素(利用equal判断元素是否一致)
* @param obj
*/
@Override
public void remove(Object obj) {
for(int i=0;i<size;i++){
//注意:底层调用的equals方法而不是==
if(get(i).equals(obj)){
remove(i);
}
}
}
/**
* 设置索引对应的元素
*/
@Override
public Object set(int i, Object obj) {
rangeCheck(i);
Object oldValue = array[i];
array[i] = obj;
return oldValue;

}

public static void main(String[] args) {
MyArrayList list = new MyArrayList();
list.add("333");
list.add("444");
list.add("5");
list.add("344433");
list.add("333");
list.add("333");
list.remove("444");
list.insert(2, "a");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println(list.size);
System.out.println(list.indexOf("5"));
}

}

模拟单项循环链表LinkList实现List接口

package com.example.code;
/**
* 带头结点的链式链表,下标从0开始;
*
*/
public class MyLinkList implements MyList{
Node head; //头结点
int size; //链表的大小
public MyLinkList() {
head = new Node();
size = 0;
}
public MyLinkList(Object[] datas) {
int n = datas.length;
head = new Node();
Node p = head;
for(int i=0; i<n; i++) {
p.next = new Node(datas[i]);
p = p.next;
}
size = n;
}
@Override
public void add(Object e) {
Node p;
if(0 == size) {
p = head;
} else {
p = index(size-1);
}
p.next = new Node(e);
size ++;
}

@Override
public void clear() {
head.next = null;
size = 0;
}

@Override
public Object get(int i) {
Node p = index(i);
return p.data;
}

private Node index(int i) {
Node p = null;
if(i>=0 && i<size){
p = head;
for(int j=0; j<=i; j++) {
p = p.next;
}
}
return p;
}

@Override
public int indexOf(Object e) {
Node p = head.next;
int i = 0;
while(!p.data.equals(e)) {
p = p.next;
i++;
}
if(i<size)
return i;
else
return -1;
}

@Override
public void insert(int i, Object e) {
Node p = index(i);
Node p2 = new Node(e);
p2.next = p.next;
p.next = p2;
size ++;
}

@Override
public boolean isEmpty() {
if(size ==0)
return true;
else
return false;
}

@Override
public int lastIndexOf(Object e) {
int i = size-1;
while(!get(i).equals(e)) {
i--;
}
if(i>=0)
return i;
else
return -1;
}

@Override
public void remove(int i) {
if(i>=0 && i<size) {
Node p = null;
if(i == 0)
p = head;
else {
p = index(i-1);
}
p.next = index(i).next;
}
size --;
}

@Override
public Object set(int i, Object e) {
Node p = index(i);
p.data = e;
return p;
}

@Override
public int size() {
return size;
}
@Override
public void remove(Object obj) {
// TODO Auto-generated method stub

}
}
/**
* 链表的结点
*
*/
class Node{
Object data; //数据元素
Node next; //后驱结点
public Node() {
this(null);
}
public Node(Object data) {
this.data = data;
this.next = null;
}
}

模拟双向循环链表LinkList实现List接口

package com.example.code;

public class MyDoubleLinkList implements MyList{

DlNode head; //头结点
int size; //链表的大小
public MyDoubleLinkList() {
head = new DlNode();
head.prior = head;
head.next = head;
size = 0;
}
public MyDoubleLinkList(Object[] datas) {
int n = datas.length;
head = new DlNode();
DlNode p = head;
DlNode p2 = null;
for(int i=0; i<n; i++) {
p2 = new DlNode(datas[i]);
p.next = p2;
p2.prior = p;
p = p.next;
}
p2.next = head;
head.prior = p2;
size = n;
}
@Override
public void add(Object e) {
DlNode p, p2;
if(0 == size) {
p = head;
} else {
p = index(size-1);
}
p2 = new DlNode(e);
p.next = p2;
p2.prior = p;
p2.next = head;
head.prior = p2;
size ++;
}

@Override
public void clear() {
head.prior = head;
head.next = head;
size = 0;
}

@Override
public Object get(int i) {
DlNode p = index(i);
return p.data;
}

private DlNode index(int i) {
DlNode p = null;
if(i>=0 && i<size){
p = head;
for(int j=0; j<=i; j++) {
p = p.next;
}
}
return p;
}

@Override
public int indexOf(Object e) {
DlNode p = head.next;
int i = 0;
while(!p.data.equals(e)) {
p = p.next;
i++;
}
if(i<size)
return i;
else
return -1;
}

@Override
public void insert(int i, Object e) {
DlNode p = index(i);
DlNode p2 = new DlNode(e);
p2.next = p.next;
p2.prior = p;
p.next = p2;
size ++;
}

@Override
public boolean isEmpty() {
if(size ==0)
return true;
else
return false;
}

@Override
public int lastIndexOf(Object e) {
DlNode p = head.prior;
int i = size-1;
while(!p.data.equals(e)) {
p = p.prior;
i--;
}
if(i>=0)
return i;
else
return -1;
}

@Override
public void remove(int i) {
if(i>=0 && i<size) {
DlNode p = null;
if(i == 0)
p = head;
else {
p = index(i-1);
}
DlNode p2 = index(i).next;
p.next = p2.next;
p2.next.prior = p;
}
size --;
}

@Override
public Object set(int i, Object e) {
DlNode p = index(i);
p.data = e;
return p;
}

@Override
public int size() {
return size;
}
@Override
public void remove(Object obj) {
// TODO Auto-generated method stub

}

}
/**
* 链表的结点
*
*/
class DlNode{
Object data;
DlNode prior, next;
public DlNode() {
this(null);
}
public DlNode(Object data) {
this.data = data; //数据元素
this.prior = null; //前驱结点
this.next = null; //后驱结点
}
}

转载:http://blog.csdn.net/luoweifu/article/details/8505178
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: