线性表指的事n个类型相同数据元素的有限序列,通常记作(A0,A1,…..Ai…..An-1)。在数据元素的有限集中,除第一个元素无直接前驱,最后一个元素无直接后续以外,每个数组元素有且仅有一个直接前驱元素和直接后继元素。
1.抽象数据类型
ADT List{
}
2.List接口
public interface List {
//返回线性表大小
public int getSize();
//线性表为空返回true,否则返回false
public boolean isEmpty();
//是否包含e
public boolean contains(Object e);
//e的位置
public int indexOf(Object e);
//e插入到i的位置
public void insert(int i, Object e) throws OutBoundaryException;
//e插到obj前
public boolean insertBefore(Object obj,Object e);
//e插到obj后
public boolean insertAfter(Object obj,Object e);
//删除序号i的元素并返回值
public Object remove(int i) throws OutBoundaryException;
//删除第一个与e相同的元素
public boolean remove(Object e);
//替换i位置的元素为e,并返回原值
public Object replace(int i,Object e) throws OutBoundaryException;
//返回i位置元素
public Object get(int i) throws OutBoundaryException;
}
/**
* 异常类
*
*/
class OutBoundaryException extends RuntimeException{
public OutBoundaryException(String err){
super(err);
}
}
/**
* 比较策略接口
*
*/
interface Strategy{
//判断两元素数据是否相等
public boolean equal(Object obj1,Object obj2);
/*
* 比较两个数据元素大小
* obj1 < obj2 返回-1
* obj1 = obj2 返回0
* obj1 > obj2 返回1
*/
public int compare(Object obj1,Object obj2);
}
/**
* 默认比较策略
*
*/
class DefaultStrategy implements Strategy{
@Override
public boolean equal(Object obj1, Object obj2) {
// TODO Auto-generated method stub
return false;
}
@Override
public int compare(Object obj1, Object obj2) {
// TODO Auto-generated method stub
return 0;
}
}
3.线性表顺序存储结构与实现
/**
* 线性表的数组实现
*
*/
public class ListArray implements List {
private final int LEN = 8;//数组默认大小
private Strategy strategy;//数据元素比较策略
private int size;//线性表中数据元素个数
private Object[] elements;//数据元素数组
//构造方法
public ListArray(){
this(new DefaultStrategy());
}
public ListArray(Strategy strategy){
this.strategy = strategy;
size = 0;
elements = new Object[LEN];
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public boolean contains(Object e) {
for(int i=0;i<size;i++){
if(strategy.equal(e, elements[i])){
return true;
}
}
return false;
}
@Override
public int indexOf(Object e) {
for(int i=0;i<size;i++){
if(strategy.equal(e, elements[i])){
return i;
}
}
return -1;
}
@Override
public void insert(int i, Object e) throws OutBoundaryException {
if(i<0 || i>size){
throw new OutBoundaryException("错误,指定的插入序号越界。");
}
if(size >= elements.length){
expandSpace();
}
//后方位置向后移动
for(int j=size;j>i;j--){
elements[j] = elements[j-1];
}
elements[i] = e;
size++;
return;
}
//扩容数组
private void expandSpace(){
Object[] a = new Object[elements.length*2];
for(int i=0;i<elements.length;i++){
a[i] = elements[i];
}
elements = a;
}
@Override
public boolean insertBefore(Object obj, Object e) {
int i = indexOf(obj);
if(i<0){
return false;
}
insert(i,e);
return true;
}
@Override
public boolean insertAfter(Object obj, Object e) {
int i = indexOf(obj);
if(i<0){
return false;
}
insert(i+1,e);
return true;
}
@Override
public Object remove(int i) throws OutBoundaryException {
if(i<0 || i>size){
throw new OutBoundaryException("错误,指定的插入序号越界。");
}
Object obj = elements[i];
//后方数据向前移动
for(int j=i;j<size-1;j++){
elements[j] = elements[j+1];
}
elements[--size] = null;
return obj;
}
@Override
public boolean remove(Object e) {
int i = indexOf(e);
if(i<0){
return false;
}
remove(i);
return true;
}
@Override
public Object replace(int i, Object e) throws OutBoundaryException {
if(i<0 || i>size){
throw new OutBoundaryException("错误,指定的插入序号越界。");
}
Object obj = elements[i];
elements[i] = e;
return obj;
}
@Override
public Object get(int i) throws OutBoundaryException {
if(i<0 || i>size){
throw new OutBoundaryException("错误,指定的插入序号越界。");
}
return elements[i];
}
}
4.线性表的链式存储与实现
4.1 单链表
/**
* 单链表结点定义
*
*/
public class SLNode implements Node{
private Object element;
private SLNode next;
//构造器
public SLNode() {
this(null,null);
}
public SLNode(Object element, SLNode next) {
this.element = element;
this.next = next;
}
//get/set方法
public SLNode getNext() {
return next;
}
public void setNext(SLNode next) {
this.next = next;
}
@Override
public Object getData() {
return element;
}
@Override
public void setData(Object obj) {
element = obj;
}
}
/**
* 结点接口
*
*/
interface Node{
//获取结点数据域
public Object getData();
//设置结点数据域
public void setData(Object obj);
}
4.2 双向链表
/**
* 双向链表结点定义
*
*/
public class DLNode implements Node {
private Object element;
private DLNode pre;
private DLNode next;
public DLNode() {
this(null,null,null);
}
public DLNode(Object element, DLNode pre, DLNode next) {
this.element = element;
this.pre = pre;
this.next = next;
}
public DLNode getPre() {
return pre;
}
public void setPre(DLNode pre) {
this.pre = pre;
}
public DLNode getNext() {
return next;
}
public void setNext(DLNode next) {
this.next = next;
}
@Override
public Object getData() {
return element;
}
@Override
public void setData(Object obj) {
element = obj;
}
}
4.3 线性表的单链表实现
/**
* 线性表的单链表实现
*
*/
public class ListSLinked implements List {
private Strategy strategy;//数据元素比较策略
private SLNode head;//单链表首结点引用
private int size;//表中数据元素个数
public ListSLinked() {
this(new DefaultStrategy());
}
public ListSLinked(Strategy strategy) {
this.strategy = strategy;
head = new SLNode();
size = 0;
}
//获取前驱结点
private SLNode getPreNode(Object e){
SLNode p = head;
while(p.getNext() != null){
if(strategy.equal(p.getNext().getData(), e)){
return p;
}else{
p = p.getNext();
}
}
return null;
}
//获取序号i[0,size)的前驱结点
private SLNode getPreNode(int i){
SLNode p = head;
for(;i>0;i--){
p = p.getNext();
}
return p;
}
//获取序号i[0,size)的结点
private SLNode getNode(int i){
SLNode p = head.getNext();
for(;i>0;i--){
p = p.getNext();
}
return p;
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public boolean contains(Object e) {
SLNode p = head.getNext();
while(p != null){
if(strategy.equal(p.getData(), e)){
return true;
}
}
return false;
}
@Override
public int indexOf(Object e) {
SLNode p = head.getNext();
int index = 0;
while(p != null){
if(strategy.equal(p.getData(), e)){
return index;
}else{
index++;
p=p.getNext();
}
}
return -1;
}
@Override
public void insert(int i, Object e) throws OutBoundaryException {
if(i<0 || i>size){
throw new OutBoundaryException("错误,指定的插入序号越界。");
}
SLNode p = getPreNode(i);
SLNode q = new SLNode(e,p.getNext());
p.setNext(q);
size++;
return;
}
@Override
public boolean insertBefore(Object obj, Object e) {
SLNode p = getPreNode(obj);
if(p!=null){
SLNode q = new SLNode(e,p.getNext());
p.setNext(q);
size++;
return true;
}
return false;
}
@Override
public boolean insertAfter(Object obj, Object e) {
SLNode p = head.getNext();
while(p!=null){
if(strategy.equal(p.getData(), obj)){
SLNode q = new SLNode(e,p.getNext());
p.setNext(q);
size++;
return true;
}
}
return false;
}
@Override
public Object remove(int i) throws OutBoundaryException {
if(i<0 || i>size){
throw new OutBoundaryException("错误,指定的插入序号越界。");
}
SLNode p = this.getPreNode(i);
Object obj = p.getNext().getData();
p.setNext(p.getNext().getNext());
size--;
return obj;
}
@Override
public boolean remove(Object e) {
SLNode p = this.getPreNode(e);
if(p != null){
p.setNext(p.getNext().getNext());
size--;
return true;
}
return false;
}
@Override
public Object replace(int i, Object e) throws OutBoundaryException {
if(i<0 || i>size){
throw new OutBoundaryException("错误,指定的插入序号越界。");
}
SLNode p = getNode(i);
Object obj = p.getData();
p.setData(e);
return obj;
}
@Override
public Object get(int i) throws OutBoundaryException {
if(i<0 || i>size){
throw new OutBoundaryException("错误,指定的插入序号越界。");
}
SLNode p = getNode(i);
return p.getData();
}
}
以上都是针对线性表中的数据元素及其序号来操作实现的,下面基于结点操作。
5.链接表
/**
* 链接表接口
*
*/
public interface LinkedList {
//返回线性表大小
public int getSize();
//线性表为空返回true,否则返回false
public boolean isEmpty();
//返回第一个结点
public Node first() throws OutBoundaryException;
//返回最后一个结点
public Node last() throws OutBoundaryException;
//返回p之后结点
public Node getNext(Node p) throws InvalidNodeException,OutBoundaryException;
//返回p之前结点
public Node getPre(Node p) throws InvalidNodeException,OutBoundaryException;
//e作为第一个元素插入,并返回所在结点
public Node insertFirst(Object e);
//e作为最后一个元素插入,并返回所在结点
public Node insertLast(Object e);
//e插入p后位置,返回e所在结点
public Node insertAfter(Node p,Object e) throws InvalidNodeException;
//e插入p前位置,返回e所在结点
public Node insertBefore(Node p,Object e) throws InvalidNodeException;
//删除给定位置的元素并返回值
public Object remove(Node p) throws InvalidNodeException;
//删除第一个元素,并返回值
public Object removeFirst() throws OutBoundaryException;
//删除最后一个元素,并返回值
public Object removeLast() throws OutBoundaryException;
//替换给定位置的元素为e,并返回原值
public Object replace(Node p,Object e) throws InvalidNodeException;
//元素迭代器
public Iterator elements();
}
/**
* InvalidNodeException异常类
*
*/
class InvalidNodeException extends RuntimeException{
public InvalidNodeException(String err){
super(err);
}
}
/**
* 基于双向链表实现的链接表
*
*/
public class LinkedListDLNode implements LinkedList {
private int size;
private DLNode head;//头结点,哑元结点
private DLNode tail;//尾结点,哑元结点
public LinkedListDLNode() {
size = 0;
head = new DLNode();
tail = new DLNode();
head.setNext(tail);
tail.setPre(head);
}
//判断结点p是否合法,如合法转换为DLNode
protected DLNode checkPosition(Node p) throws InvalidNodeException {
if(p == null){
throw new InvalidNodeException("错误,p为空");
}
if(p == head){
throw new InvalidNodeException("错误,p为头结点,非法");
}
if(p == tail){
throw new InvalidNodeException("错误,p为尾结点,非法");
}
DLNode node = (DLNode) p;
return node;
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public Node first() throws OutBoundaryException {
if(isEmpty()){
throw new OutBoundaryException("错误,链接表为空");
}
return head.getNext();
}
@Override
public Node last() throws OutBoundaryException {
if(isEmpty()){
throw new OutBoundaryException("错误,链接表为空");
}
return tail.getPre();
}
@Override
public Node getNext(Node p) throws InvalidNodeException,
OutBoundaryException {
DLNode node = checkPosition(p);
node = node.getNext();
if(node == tail){
throw new OutBoundaryException("错误,已经是链接表尾端");
}
return node;
}
@Override
public Node getPre(Node p) throws InvalidNodeException,
OutBoundaryException {
DLNode node = checkPosition(p);
node = node.getPre();
if(node == head){
throw new OutBoundaryException("错误,已经是链接表首端");
}
return node;
}
@Override
public Node insertFirst(Object e) {
DLNode node = new DLNode(e,head,head.getNext());
head.getNext().setPre(node);
head.setNext(node);
size++;
return node;
}
@Override
public Node insertLast(Object e) {
DLNode node = new DLNode(e,tail.getPre(),tail);
tail.getPre().setNext(node);
tail.setPre(node);
size++;
return node;
}
@Override
public Node insertAfter(Node p, Object e) throws InvalidNodeException {
DLNode node = checkPosition(p);
DLNode newNode = new DLNode(e,node,node.getNext());
node.getNext().setPre(newNode);
node.setNext(newNode);
size++;
return newNode;
}
@Override
public Node insertBefore(Node p, Object e) throws InvalidNodeException {
DLNode node = checkPosition(p);
DLNode newNode = new DLNode(e,node.getPre(),node);
node.getPre().setNext(newNode);
node.setPre(newNode);
size++;
return newNode;
}
@Override
public Object remove(Node p) throws InvalidNodeException {
DLNode node = checkPosition(p);
Object obj = node.getData();
node.getPre().setNext(node.getNext());
node.getNext().setPre(node.getPre());
size--;
return obj;
}
@Override
public Object removeFirst() throws OutBoundaryException {
return remove(head.getNext());
}
@Override
public Object removeLast() throws OutBoundaryException {
return remove(tail.getPre());
}
@Override
public Object replace(Node p, Object e) throws InvalidNodeException {
DLNode node = checkPosition(p);
Object obj = node.getData();
node.setData(e);
return obj;
}
@Override
public Iterator elements() {
return new LinkedListIterator(this);
}
}
6.迭代器
/**
* 迭代器接口
*
*/
public interface Iterator {
//移动到第一个元素
public void first();
//移动到下一个元素
public void next();
//检查迭代器中是否还有剩余的元素
public boolean isDone();
//返回当前元素
public Object currentItem();
}
class LinkedListIterator implements Iterator{
private LinkedList list;//链接表
private Node current;//当前结点
public LinkedListIterator(LinkedList list) {
this.list = list;
if(list.isEmpty()){
current = null;
}else{
current = list.first();
}
}
@Override
public void first() {
if(list.isEmpty()){
current = null;
}else{
current = list.first();
}
}
@Override
public void next() throws OutBoundaryException{
if(isDone()){
throw new OutBoundaryException("错误,已经没有元素");
}
if(current == list.last()){
current = null;
}else{
current = list.getNext(current);
}
}
@Override
public boolean isDone() {
return current == null;
}
@Override
public Object currentItem() throws OutBoundaryException{
if(isDone()){
throw new OutBoundaryException("错误,已经没有元素");
}
return current.getData();
}
}