第一章:表、栈和队列
时间复杂度
描述的代码的执行效率,表示为O(n)的函数。
线性结构和非线性结构
线性结构
1.数据元素之间存在一对一的关系
2.数据有两种存储结构:顺序存储结构(顺序表)和链式存储结构(链表)。
3.线性结构:数组、队列、链表和栈
** 非线性结构**
非线性结构:数据元素之间不一定是一对一的线性关系;二维数组,多维数组,广义表,树结构,图结构
List接口、ArrayList类和LinkedList类
关系图:
interface Collection implements Iterator
interface List implements Collection
class ArrayLsitList implements List
class LinkedList implements List
ArrayList的是用可增长数组实现的,优点在于对get和set的调用花费常数时间,缺点是对于插入和删除元素代价昂贵,因为数组元素的存储结构是连续的,且相对位置和数组下标相对应。插入和删除元素都需要把特定位置之后的元素向前或者向后挪移。
LinkedList是双向链表,优点在于:假设变动项的位置是已知的,插入和删除开销很小;但是其没有下标索引,所以get的调用比较费时间。
MyArrayList
ArrayList是数组结构进行操作数据,里面包含一个容器容量的概念。下面看实现代码!
ArrayList包含对数据的基本操作:清空元素,删除元素,查看容器是否为空,添加元素,迭代器等等。各种操作是基于数组结构进行操作的。
import java.util.Iterator;
/* size()
* add()
* remove()
* capacity()
*/
public class MyArrayList<AnyType> implements Iterator {
//默认容器长度
private static final int DEFAULT_CAPACITY=10;
//数组长度
private int thesize;
//定义数组
private AnyType[] element;
public MyArrayList() {
doclear();
}
//判断是否为空
public boolean isEmpty() {
return thesize==0;
}
//清空容器
public void doclear() {
thesize=0;ensureCapacity(DEFAULT_CAPACITY);
}
//返回数组长度
public int size() {
return thesize;
}
//获取指定位置上的元素
public AnyType get(int index) {
if(index<0||index>size()) {
throw new ArrayIndexOutOfBoundsException();
}
return element[index];
}
//把index位置上值替换掉,并且返回被替换掉的值
public AnyType set(int index,AnyType val) {
if(index<0||index>size()) {
throw new ArrayIndexOutOfBoundsException();
}
AnyType oldelement=element[index];
element[index]=val;
return oldelement;
}
//修改容器的承载能力
@SuppressWarnings("unchecked")
public void ensureCapacity(int capacity) {
if(thesize<capacity)
return;
AnyType[] oldelement=element;
element=(AnyType[]) new Object[capacity];
for(int i=0;i<thesize;i++) {
element[i]=oldelement[i];
}
}
//添加元素
public boolean add(AnyType val) {
add(size(),val);
return true;
}
//在index位置添加元素
private void add(int index, AnyType val) {
if(index<0||index>thesize) {
throw new ArrayIndexOutOfBoundsException();
}
if(element.length==size()) {
ensureCapacity(thesize*2+1);
}
for(int i=thesize;i>index;i--) {
element[i]=element[i-1];
}
element[index]=val;
thesize++;
}
//移除index位置上的元素,并返回被移除的值
public AnyType remove(int index) {
if(index<0||index>size()) {
throw new ArrayIndexOutOfBoundsException();
}
AnyType removeelement=element[index];
for(int i=index;i<thesize-1;i++) {
element[i]=element[i++];
}
thesize--;
return removeelement;
}
public java.util.Iterator<AnyType> iterator(){
return this.new ArrayListIterator();//这里面省略了一个this
}
private class ArrayListIterator implements java.util.Iterator<AnyType>{
private int current=0;
@Override
public boolean hasNext() {
if(current<size()) {
return true;
}
return false;
}
@Override
public AnyType next() {
// TODO Auto-generated method stub
if(!hasNext()) {
throw new java.util.NoSuchElementException();
}
return element[current++];
}
public void remove() {
MyArrayList.this.remove(--current);
}
}
@Override
public boolean hasNext() {
// TODO Auto-generated method stub
return false;
}
@Override
public Object next() {
// TODO Auto-generated method stub
return null;
}
}
MyLInkedList
LinkedList是双链表。
/*
* 和单边二叉树有点像
*/
public class MyLinkedList<AnyType> implements Iterator<AnyType> {
private Node<AnyType> beginMarker;
private Node<AnyType> endMarker;
private int modCount=0;
private int theSize;
//初始化
public MyLinkedList() {
doclear();
}
private void doclear() {
beginMarker=new Node<AnyType>(null,null,null);
endMarker=new Node<AnyType>(null,beginMarker,null);
beginMarker.next=endMarker;
modCount++;
theSize=0;
}
//重新初始化文件
public void clear() {
doclear();
}
public void addBefore(Node<AnyType> p,AnyType x) {
//这就创建一个新的节点
Node<AnyType> newnode=new Node<AnyType>(x,p.prev,p);
p.prev.next=newnode;
p.prev=newnode;
theSize++;
modCount++;
}
public int size() {
return theSize;
}
public boolean add(AnyType x) {
add(size(),x);
return true;
}
private void add(int index, AnyType x) {
// TODO Auto-generated method stub
addBefore(getNode(index,0,size()),x);
}
public AnyType remove(int index) {
return remove(getNode(index));
}
public AnyType get(int index) {
return getNode(index).data;
}
//删除节点,并返回删除节点的值
public AnyType remove(Node<AnyType> node) {
node.next.prev=node.prev;
node.prev.next=node.next;
theSize--;
modCount++;
return node.data;
}
private Node<AnyType> getNode(int index) {
return getNode(index,0,size()-1);
}
public Node<AnyType> getNode(int index,int lower,int upper) {
Node<AnyType> p;
if(index<lower||index>upper) {
throw new IndexOutOfBoundsException();
}
if(index<size()/2) {
p=beginMarker.next;
for(int i=0;i<index;i++) {
p=p.next;
}
}else {
p=endMarker;
for(int i=size();i>index;i--) {
p=p.prev;
}
}
return p;
}
public java.util.Iterator<AnyType> iterator(){
return new LinkedListIterator();
}
private class LinkedListIterator implements java.util.Iterator<AnyType>{
private Node<AnyType> currentnode=beginMarker.next;
private int modcount=modCount;
private boolean okToRemove=false;
@Override
public boolean hasNext() {
return currentnode!=endMarker;
}
@Override
public AnyType next() {
if(modCount!=modcount) {
throw new java.util.ConcurrentModificationException();
}
if(!hasNext()) {
throw new java.util.NoSuchElementException();
}
AnyType item=currentnode.data;
currentnode=currentnode.next;
okToRemove=true;
return item;
}
public void remove() {
if(modCount!=modcount) {
throw new java.util.ConcurrentModificationException();
}
if(!okToRemove) {
throw new IllegalStateException();
}
MyLinkedList.this.remove(currentnode.prev);
modcount++;
okToRemove=false;
}
}
@Override
public boolean hasNext() {
// TODO Auto-generated method stub
return false;
}
@Override
public AnyType next() {
// TODO Auto-generated method stub
return null;
}
//每一个节点的信息
private static class Node<AnyType>{
public Node(AnyType d,Node<AnyType> p,Node<AnyType> n) {
data=d;
prev=p;
next=n;
}
private AnyType data;
public Node<AnyType> prev;
public Node<AnyType> next;
}
}
栈ADT
class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
class Stack extends Vector
栈又叫做LIFO(后进先出)表。
栈模型: 栈就像一个子弹夹,只有一个口用来插入和输出,并且遵循先进后出的原则。表的末端叫做栈顶。相关操作有:进栈(push)和出栈(pop)。
栈的单链表结构实现 把我给写吐了,我好菜
package link;
import java.util.Iterator;
import java.util.Stack;
public class MyStack<AnyType> {
//单链表结构实现
private int size;
private Node<AnyType> endNode;
private Node<AnyType> topnode;
public MyStack() {
doclear();
this.endNode=new Node<AnyType>(null,null);
this.size=0;
}
public void doclear() {
// TODO Auto-generated method stub
endNode=null;
size=0;
}
public int size() {
return size;
}
public Node<AnyType> push(AnyType val) {
Node<AnyType> newnode=new Node<AnyType>(val,null);
getnode(size()).pre=newnode;
size++;
return null;
}
//返回最上面的节点
public Node getnode(int index) {
Node<AnyType> p=endNode;
for(int i=0;i<index;i++) {
p=p.pre;
}
return p;
}
//出栈并删除
public Object pop() {
if(size==0) {
return null;
}
Node node=getnode(size()-1);
AnyType val=(AnyType) node.pre.item;
node.pre=null;
size-=1;
return val;
}
public static void main(String[] args) {
MyStack<Integer> m=new MyStack<>();
for(int i=0;i<10;i++) {
m.push(i);
}
for(int i=0;i<5;i++) {
System.out.println(m.pop()+" "+m.size());
}
}
class Node<AnyType>{
private AnyType item;
public Node pre;
public Node(AnyType item,Node<AnyType> n){
this.item=item;
this.pre=n;
}
}
}
代码总结:
利用单向链表去实现栈的数据结构。
首先分析这个MyStack这个类里面应该有什么:节点(表示元素和其他节点的地址),记录总的数据;对数据进行的操作应该有:插入,获取栈顶元素并同时删除栈顶元素,获取表大小
节点该怎么表示呢:节点不是数据结构就行了,它应该是一个箱子(类的比喻),对于MyStack来讲,是对箱子进行操作。箱子这个类有自己的内容,装的是一个元素和一个地址。
上面可以看出:Java是一门面向对象的语言,同时还包含了封装的特点!好好体会!每一个类有自己要做的事情,每一个方法也有自己要做的事情。
栈的数组实现