1.使用java中的数组
动态数组
public class Array<E> {
private E[] data;
private int size;
public Array(int capacity) {
data = (E[])new Object[capacity];
size = 0;
}
public Array() {
this(10);
}
public int getSize() {
return size;
}
public int getCapacity() {
return data.length;
}
public boolean isEmpty() {
return size == 0;
}
public void addLast(E e) {
add(size,e);
}
public void addFirst(E e) {
add(0,e);
}
public void add(int index, E e) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("");
}
if (size == data.length) {
resize(2*data.length);
}
//从后向前挪
for (int i = size - 1; i >= index; i--) {
data[i + 1] = data[i];
}
data[index]=e;
size++;
}
E get(int index){
if(index<0||index>=size){
throw new IllegalArgumentException("");
}
return data[index];
}
void set (int index,E e){
if(index<0||index>=size){
throw new IllegalArgumentException("");
}
data[index]=e;
}
//查找数组中是否存在元素e
public boolean contains(E e){
for (int i=0;i<size;i++){
if(data[i].equals(e)){
return true;
}
}
return false;
}
public int find(E e){
for (int i=0;i<size;i++){
if(data[i].equals(e)){
return i;
}
}
return -1;
}
//删除
public E remove(int index){
if(index<0||index>=size){
throw new IllegalArgumentException("");
}
//将待删除元素存起来 用于返回
E ret =data[index];
//删除就是后面的直接覆盖
for (int i=index+1;i<size;i++){
data[i-1]=data[i];
}
size--;
data[size]=null;//自动回收
//动态减小数组
if(size==data.length/4&& data.length/2!=0){
resize(data.length/2);
}
return ret;
}
public E removeFist(){
return remove(0);
}
public E removeLast(){
return remove(size-1);
}
public void removeElement(E e){
int index=find(e);
if (index!=-1)
remove(index);
}
@Override
public String toString(){
StringBuilder res=new StringBuilder();
res.append(String.("Array: size=%d,capacity=%d\n",size,data.length));
res.append('[');
for (int i=0;i<size;i++){
res.append(data[i]);
if (i!=size-1)
res.append(",");
}
res.append("]");
return res.toString();
}
private void resize(int newCapacity){
E[] newData=(E[]) new Object[newCapacity];
for (int i=0;i<size;i++){
newData[i]=data[i];
}
data=newData;
}
}2.栈和栈的应用:撤销操作和系统栈
1.栈也是一种线性结构。
2.相比数组,栈对应的操作是数组的子集。
3.只能从一端添加元素,也只能从一端取出元素。
4.这一端称为栈顶。
A程序执行到A2这个位置去执行B程序,在B2这里执行c程序,c程序执行完成,去找应该执行的位置,就是B2.
package stack;
import array.Array;
public class ArrayStack<E> implements Stack<E> {
//成员变量
Array<E> array;
//构造函数
public ArrayStack(int capacity) {
array = new Array<E>(capacity);
}
public ArrayStack() {
array = new Array<E>();
}
@Override
public int getSize() {
return array.getSize();
}
@Override
public boolean isEmpty() {
return array.isEmpty();
}
public int getCapacity() {
return array.getCapacity();
}
@Override
public void push(E e) {
array.addLast(e);
}
@Override
public E pop() {
return array.removeLast();
}
@Override
public E peek() {
return array.getLast();
}
@Override
public String toString() {
StringBuffer res=new StringBuffer();
res.append("Stack: ");
res.append("[");
for (int i=0;i<array.getSize();i++){
res.append(array.get(i));
if (i!=array.getSize()-1){
res.append(",");
}
}
res.append("] top");
return res.toString();
}
}栈的一个应用:括号匹配
首先我们声明一个stack 我们遍历字符,将左侧的括号以此压如栈中,开始遍历到右侧括号就和栈顶匹配,匹配成功就出栈,都遍历完了,栈是空的,当前这些括号是合法的。
反例:当遍历到右侧大括号时,与栈顶的中括号匹配失败了,
import java.util.Stack;
public class Solution {
public boolean isValid(String s) {
Stack<Character> stack=new Stack<Character>();
for (int i=0;i<s.length();i++){
char c=s.charAt(i);
if (c=='('||c=='['||c=='{'){
stack.push(c);
}else {
if (stack.isEmpty()){
return false;
}
char topChar=stack.pop();
if(c==')'&& topChar!='('){
return false;
}
if (c==']'&& topChar!='['){
return false;
}
if (c=='}'&& topChar!='{'){
return false;
}
}
}
return stack.isEmpty();
}
}3数组队列
队列也是一种线性结构
相比数组,队列对应的操作是数组的子集
只能从一端(队尾)添加元素,也只能从另一端(队首)取出元素。
package queue;
import array.Array;
public class ArrayQueue<E> implements Queue<E> {
private Array<E> array;
//构造函数
public ArrayQueue(int capacity){
array=new Array<E>(capacity);
}
public ArrayQueue(){
array=new Array<E>();
}
@Override
public int getSize() {
return array.getSize();
}
@Override
public boolean isEmpty() {
return array.isEmpty();
}
public int getCapacity(){
return array.getCapacity();
}
@Override
public void enqueue(E e) {
array.addLast(e);
}
@Override
public E dequeue() {
return array.removeFist();
}
@Override
public E getFront() {
return array.getFirst();
}
@Override
public String toString() {
StringBuilder res=new StringBuilder();
res.append("Queue: ");
res.append("front [");
for (int i=0;i<array.getSize();i++){
res.append(array.get(i));
if (i!=array.getSize()-1)
res.append(",");
}
res.append("] tail");
return res.toString();
}
public static void main(String[] args) {
ArrayQueue<Integer> queue=new ArrayQueue<Integer>();
for (int i=0;i<10;i++){
queue.enqueue(i);
System..println(queue);
if (i%3==2){
queue.dequeue();
System..println(queue);
}
}
}
}4 循环队列
用数组实现对列,在出队时取走头部位置,后面的数据响应的需要往前移,所以时间复杂度是O(N)级别的,如果这些元素不移动位置,时间复杂度就会降到0(1)级别的。所以我们记录下队首和队尾的位置,就可以了。
循环对列需要两个指针,一个tail 每入队就++,取数据 front就++,为什么加循环对列:
当我们加到第7个元素时,tail+1对capacity取余 就是 0,前提是数组没有满,如果满了 就扩容。
package queue;
public class LoopQueue<E> implements Queue<E> {
private E[] data;
private int front,tail;
private int size;
public LoopQueue(int capacity){
data=(E[])new Object[capacity+1];
front=0;
tail=0;
size=0;
}
public LoopQueue(){
this(10);
}
public int getCapacity(){
return data.length-1;
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return front==tail;
}
@Override
public void enqueue(E e) {
//入队,先检查对列是否满了
if((tail+1)%data.length==front){//满了需要扩容
resize(getCapacity()*2);
}
data[tail]=e;
tail=(tail+1)%data.length;
size++;
}
private void resize(int newCapacity){
E[] newData=(E[])new Object[newCapacity+1];//先开空间
//将原来的数据都放入新空间中
for (int i=0;i<size;i++){
newData[i]=data[(i+front)%data.length];
}
data=newData;
front=0;
tail=size;
}
@Override
public E dequeue() {
//出队,先判断对列是否为空
if (isEmpty()){
throw new IllegalArgumentException("error");
}
E ret=data[front];
data[front]=null;
front=(front+1)%data.length;
size--;
//缩容
if(size==getCapacity()/4 && getCapacity()/2 !=0)
resize(getCapacity()/2);
return ret;
}
@Override
public E getFront() {
if(isEmpty()){
throw new IllegalArgumentException("error");
}
return data[front];
}
@Override
public String toString() {
StringBuilder res=new StringBuilder();
res.append(String.("Queue: size=%d,capacity=%d\n",size,getCapacity()));
res.append(" front [");
for (int i=front;i!=tail;i=(i+1)%data.length){
res.append(data[i]);
if ((i+1)%data.length!=tail)
res.append(",");
}
res.append("] tail ");
return res.toString();
}
}5 什么是链表
package linkedList;
public class LinedList<E> {
//内部类
private class Node{
public E e;
public Node next;
//构造方法
public Node(E e,Node next){
this.e=e;
this.next=next;
}
public Node(E e){
this(e,null);
}
//无参构造器
public Node(){
this(null,null);
}
@Override
public String toString() {
return e.toString();
}
}
}带有尾针的链表:使用链表实现队列
package queue;
public class LinkedListQueue<E> implements Queue<E> {
private class Node {
public E e;
public Node next;
//构造方法
public Node(E e, Node next) {
this.e = e;
this.next = next;
}
public Node(E e) {
this(e, null);
}
//无参构造器
public Node() {
this(null, null);
}
@Override
public String toString() {
return e.toString();
}
}
private Node head,tail;
private int size;
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public void enqueue(E e) {
if(tail==null){
tail=new Node(e);
head=tail;
}else {
tail.next=new Node(e);
tail=tail.next;
//头结点不要动
}
size ++;
}
@Override
public E dequeue() {//出队
if(isEmpty()){
throw new IllegalArgumentException("error");
}
Node retNode=head;//出队元素的节点应该是头节点
head=head.next;
retNode.next=null;
if (head ==null){
tail=null;
}
size--;
return retNode.e;
}
@Override
public E getFront() {
if(isEmpty()){
throw new IllegalArgumentException("error");
}
return head.e;
}
@Override
public String toString() {
StringBuffer res=new StringBuffer();
res.append("Queue :front");
Node cur=head;
while (cur!=null){
res.append(cur+"->");
cur=cur.next;
}
res.append("null tail");
return res.toString();
}
public static void main(String[] args) {
LinkedListQueue<Integer> queue=new LinkedListQueue<Integer>();
for (int i=0;i<10;i++){
queue.enqueue(i);
System..println(queue);
if (i%3==2){
queue.dequeue();
System..println(queue);
}
}
}
}6 递归基础与递归的宏观语意
链表的天然递归结构性质
树结构
具体树结构 请看树结构浅析