Java基本功之栈的增删改查

方法一:通过调用Stack这个类来实现

1.了解 栈 是一种只能在一端进行插入或删除操作的线性表  并且是先入后出的(也是后入先出)

2.下面我们先了解一下栈的基本操作:

Stack stack=new Stack();//这是创建一个Stack类对象并赋值给Stack类的stack变量
stack.empty()//是判断栈是否为空,若为空则返回true
System.out.println(stack.empty());
push//是入栈
stack.push("字符串入栈");
peek()//取栈顶值(不出栈)
System.out.println(stack.peek());//输出栈顶的值
pop//出栈
stack.pop();//出栈一个栈顶元素
search()//可以查询元素在栈的位置

3.下面我们来想一下原理:通过调用Stack这个类的push方法往栈中存入一系列数,想要实现增加一个数,就简单的在push一个就可以;若是想在某一特定数的前面加入这个数,首先需要讲特定数之后的先取出,然后在放入增加的数,然后再把取出的数放回。

删、改也都是同样的原理。

4.下面我们用代码实现一下栈中删除某一特定数的方法:

public static void main(String[] args)
	{
		Stack stack=new Stack();//创建一个新的Stack对象,并赋值给Stack类型的stack变量
		System.out.println(stack.empty());//判断新建的stack栈是否为空
		for(int i=0;i<10;i++)//往栈里输入[0,1,2,3,4,5,6,7,8,9]
		{
			stack.push(new Integer(i));
		}
		System.out.println(stack);//输出栈
		del(stack,3);//调用下面del方法
		del(stack,8);
	}
	public static void del(Stack stack,int target)
	{
		int site=stack.search(target);//通过search方法查询目标数,返回的是以1开始的下标数
		Object[] a= new Object[site];//创建一个新数组,长度为栈内要取出数的长度
		for(int i=0;i<site;i++)//从栈取出的赋给数组,数组最后一个数即为要删除的数
		{
			a[i]=stack.pop();
		}
		for(int j=site-2;j>=0;j--)//从数组后倒数第二位开始往栈中存,倒数第一位是要删除的
		{
			stack.push(a[j]);
		}
		System.out.println(stack);
	}	

方法二:也可以通过数组来实现

1.把数组想象成栈,那么就是要在数组尾进行存入和取出的操作,头不动。

2.这里就说一下思路:通过两个数组,一个模拟成栈的形式,一个用来存放取出的数据。再自己定义两个方法,一个往数组存,一个从数组取出。

方法三:通过链表(也就是一个个的结点)的形式实现栈

一、用一个例子来体现链表形式实现栈的模式:

1.首先我们先建立一个单结点

public class MyStack<T> {//<T>代表任意引用类型   泛型//定义一个单结点
	private T data;//定义成私有的 通过get set的取值赋值方法调用 避免被随意更改其中的值
	private MyStack<T> next;
    //调用get\set函数
	public T getData() {
		return data;
	}
	public void setData(T data) {
		this.data = data;
	}
	public MyStack<T> getNext() {
		return next;
	}
	public void setNext(MyStack<T> next) {
		this.next = next;
	}
	@Override
	public String toString() {//不加的话,输出的为地址
		return "MyStack [data=" + data + ", next=" + next + "]";
	}		
}

2.写一个学生类

public class Student {
//实例域 若用public会破坏封装,谁都可以访问, 用来存放要操作的数据
	private int stuNum;
	private String name;
	private String otherInfo;
//调用get set方法
	public int getStuNum() {
		return stuNum;
	}
	public void setStuNum(int stuNum) {
		this.stuNum = stuNum;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getOtherInfo() {
		return otherInfo;
	}
	public void setOtherInfo(String otherInfo) {
		this.otherInfo = otherInfo;
	}
	@Override
	public String toString() {
		return "Student [stuNum=" + stuNum + ", name=" + name + ", otherInfo=" + otherInfo + "]";
	}		
}

3.通过学生数组,想象每一个都是一个单结点。然后栈,需要有一个固定的头(linkBanji),和一个随着加入数据而移动的指针flag——永远指向最后一个数据(因为栈是后入先出,所以只需要一个指针,指向最后一个数据结点即可)。随着每加入一个数据,新建一个单结点,并通过next连起来,再移动flag指针指向新加入的数据。

public class TestClass {
	public static void main(String[] args)
	{
		String[] studentNames=new String[]//定义数组并赋值
				{
						"xiao1","xiao2","xiao3","xiao4","xiao5","xiao6","xiao7","xiao8"
				};
        MyStack<Student> linkBanji=new MyStack<Student>();//头
        MyStack<Student> flag=linkBanji;//随着移动的一个指针
        //通过循环把数组中的数据放入栈中,每放入一个新的数据就在堆中新建一块区域
        for( int i = 0; i < studentNames.length; i++ )
        {
              Student stu = new Student();
              //给stu赋值
              flag.setData(stu);
              stu.setName( studentNames[i] );
              stu.setStuNum(i);
              stu.setOtherInfo("我序号为" + ( i + 1 ) );
              if(i<studentNames.length-1)//小于的时候证明数组中还有数据没有存放进栈中
                {
                    flag.setNext(new MyStack<Student>());//通过next指向新建的区域
                    flag=flag.getNext;//flag通过next的指向 指向新建的区域
                }              
             
          }
          System.out.println(linkBanji);//输出这个栈的数据
	}
}

图解:更直观理解如何通过单结点形成链表

二、实现链表栈的输出:

先写一个出栈入栈的方法

package test;

import pag.MyStack;

public class StackClass<T> {//<T>是泛型
	  private MyStack<T> que; //栈只要用头标就行

	    public MyStack<T> getQue() {
	        return que;
	    }

	    public void setQue(MyStack<T> que) {
	        this.que = que;
	    }

	    public void add( MyStack<T>  add ){//入栈
	        if( que == null ){//空的时候就直接放入第一个头标处即可
	            que = add;
	        }else{
	            add.setNext(que);//不空时,add放入que的下一个结点(setNext(que)表示que的下一结点)
	            que = add;//挪动头标位置
	        }
	    }

	    public MyStack<T> pop(){//出栈
	    	MyStack<T> result = que;//赋值
	        if( que != null ){
	            que = que.getNext();//不为空,que往后挪动
	        }
	        return result;
	    }
	    public void look(){
	        System.out.println(que.toString());//调用MyStack里的toString()
	    }
}

主函数

public class TestClass {
	public static void main(String[] args)
	{
		String[] studentNames=new String[]//定义数组并赋值
				{
						"xiao1","xiao2","xiao3","xiao4","xiao5","xiao6","xiao7","xiao8"
				};
       StackClass<Student> que=new StackClass<Student>();//建立que变量 头
        //通过循环把数组中的数据放入栈中,每放入一个新的数据就在堆中新建一块区域
        for( int i = 0; i < studentNames.length; i++ )
        {
              MyStack<Student> flag=new MyStack<Student>();
              Student stu = new Student();
              //给stu赋值
              flag.setData(stu);
              stu.setName( studentNames[i] );
              stu.setStuNum(i);
              stu.setOtherInfo("我序号为" + ( i + 1 ) );
              que.add(flag);//讲flag放入que中
              if(i==3)//条件符合时输出,因为这是栈所以刚存进去就输出。(这里跟队列有所区别)
                {
                    MyStack<Student> as=que.pop();//出栈
                    if(as==null){
                        System.out.println("空了");
                        break;
                    }else{System.out.println(as.getData().getName())}
                }              
             
          }
          for(;;){//循环输出栈内数据
               MyStack<Student> as=que.pop();
               if(as==null)
               {
                  System.out.println("空了");
                  break;
               }else{System.out.println(as.getData().getName())}
          }
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值