算法学习(一) 从定容栈到动态栈到链栈

写在前面

栈是算法学习的第一个知识,在这里开启了算法学习的道路。通过栈的学习,巩固了泛型,接口等概念。下面就开始实现吧!!

(一)栈的API以及用例

要想深入了解一个内容,首先从使用它开始。
栈的API中包括了入栈,出栈,判断为空和输出栈的大小操作。
由于我们需要栈内可以接受任意的数据类型,java中的泛型正是、解决这一问题的方法。

import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;
import java.util.Stack;

public class StackUsage {
    public static void main(String[] args) {
        Stack<Integer> s = new Stack<Integer>();
        while (!StdIn.isEmpty()) {
            s.push(StdIn.readInt());
        }
        //这里使用foreach语句并不能翻转
        //使用foreach输出时候是按照数组从索引0开始的方式遍历的!!
        //即:从栈底到栈顶;刚好和弹栈的方式相反!!!  所以反转实现用pop语句
        for(int i:s){
        StdOut.print(i+",");
        }
        /**
        int N = s.size();
        int[] a = new int[N];
        for (int i = 0; i < N; i++) {
            a[i] = s.pop();
        }
        for (int i = 0; i < N; i++) {
            StdOut.print(a[i] + ",");
        }
         **/
    }
}

上述代码中,实现了输入一串整数序列,将其反转的操作
注意:这里使用foreach语句来进行反转是有问题的,所以可以使用pop操作来进行反转

(二)定容栈

在这里我使用数组来进行数据的存储。而数组的大小是设定之初就设置好的。

2、1固定类型的定容栈

这里实现了一个String类型的定容栈

//用数组来实现栈 动态调整数组大小
public class FixedCapacityStackOfStrings{
    //设计一个定容栈
    private String []a;
    private int N;
    //构造方法 初始化一个数组
    public FixedCapacityStackOfStrings(int cap){
        a=new String[cap];
    }
    public boolean isEmpty(){
        return N==0;
    }
    public int size(){
        return N;
    }
    public void push(String item){
        a[N++]=item;
    }
    public String pop(){
        return a[--N];
    }

}

2、1使用泛型实现任意参数类型的定容栈

使用泛型实现

//用数组来实现栈 动态调整数组大小
public class FixedCapacityStackOfItem<Item> {
    private Item a[];
    private int N;
    public FixedCapacityStackOfItem(int cap){
        //创建泛型数组是不允许的,采用类型转换
        a=(Item[])new  Object[cap];
    }
    public boolean isEmpty(){
        return N==0;
    }
    public int size(){
        return N;
    }
    public void push(Item item){
        a[N++]=item;
    }
    public Item pop(){
        return a[--N];
    }
}

注意:创建泛型数组是不允许的,采用类型转换

(三)动态栈

3、1如何调整数组大小?

在定容栈中,我们需要在入栈和出栈操作之前,先检查栈中是否满或空。而这挺烦的。如何去除这些操作呢?
在这里定义一个resize的方法,将大小N《=Max的栈移动到一个新的大小为Max的数组中。

    private void resize(int max) {
        Item[]temp=(Item[]) new Object[max];
        for(int i=0;i<N;i++){
            temp[i]=a[i];
        }
        a=temp;
        
    }

在push操作中,我们会先检查栈的大小N和数组大小a.length是否相等来检查数组是否能够容纳新元素
注意栈的大小是《=数组长度的

public void push(Item item){
        if(N==a.leghth)
            resize(a.length*2);
    }

同理对于pop操作

public Item pop(){
        if(N>0&&N==a.length/4)
            resize(a.length/4);
        return a[--N];
    }

3、2迭代的实现

集合类数据类型的基本操作之一就是能够使用foreach语句通过迭代遍历并处理集合中的每个元素。

3、2、1可迭代的集合数据类型中,我们需要实现什么?

1、首先使一个类可迭代,需要在其申明中加入Implements Iterable 《Item》

  public interface Iterable<Item>{
        Iterator<Item> iterator();
    }

2、集合数据类型必须实现一个iterator方法并返回一个iterator对象

public Iterator<Item> iterator(){
        return new ReverseArrayIterator();
    }

3、iterator中需要包含两个方法hasNext和next

public interface Iterator<Item>{
        boolean hasNext();
        Item next();
        void remove();
    }

3、2、2实现可迭代的动态栈

import java.util.Iterator;

//用数组来实现栈 动态调整数组大小
import java.util.Iterator;

//用数组来实现栈 动态调整数组大小

public class StackRealize<Item> implements Iterable<Item> {
    private Item a[]=(Item[])new Object[1];
    private int N=0;
    public boolean isEmpty(){
        return N==0;
    }
    public int size(){
        return N;
    }
    private void resize(int max) {
        Item[]temp=(Item[]) new Object[max];
        for(int i=0;i<N;i++){
            temp[i]=a[i];
        }
        a=temp;

    }
    public void push(Item item){
        if(N==a.length)
            resize(a.length*2);
        a[N++]=item;
    }
    public Item pop(){
        Item item=a[--N];
        //避免游离
        a[N]=null;
        if(N>0&&N==a.length/4)
            resize(a.length/4);
        return item;
    }

    public Iterator<Item> iterator(){
        return new ReverseArrayIterator();
    }
    public class ReverseArrayIterator implements Iterator<Item>{
        private int i=N;
        public boolean hasNext(){
            return i>0;
        }
        public Item next(){
            return a[--i];
        }
        public void remove(){

        }
    }
}




(四)链栈的实现

通过使用链表,这里实现向栈顶添加元素(这里的栈顶是头指针的指向)。

import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;

import java.util.Iterator;

//实现链栈
public class LineStack<Item> implements Iterable<Item> {
    private class Node {
        Item item;
        Node next;
    }

    private Node head;
    private int N;

    public boolean isEmpty() {
        return head==null;
    }

    public void push(Item item) {
        Node x = head;
        head = new Node();
        head.item = item;
        head.next = x;
        N++;
    }

    public Item pop() {
        Item item = head.item;
        head = head.next;
        N--;
        return item;
    }

    public int size() {
        return N;
    }



    public Iterator iterator(){
        return new ListIterator();
    }
    public class ListIterator implements Iterator<Item> {
        private Node current = head;

        public boolean hasNext() {
            return current != null;
        }

        public void remove() {
        }

        public Item next() {
            Item item = current.item;
            current = current.next;
            return item;
        }
    }
    public static void main(String[] args){
        LineStack<Integer> s=new LineStack<Integer>();
        while(!StdIn.isEmpty()){
            Integer item=StdIn.readInt();
            if(!item.equals(5))
                s.push(item);
            else if(!s.isEmpty())
                StdOut.print(s.pop());
        }StdOut.print(s.size());
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值