栈的应用
进制转换
例:十进制转十六进制
输入654321,打印输出与其等值的十六进制数。
654321 ÷ 16 = 40895 ~ 1
40895 ÷ 16 = 2555 ~ 15
2555 ÷ 16 = 159 ~ 11
159 ÷ 16 = 9 ~ 15
9 ÷ 16 = 0 ~ 9
9 F B F 1
十六进制转换为十进制
9 F B F 1
1 × 160 + F × 161 + B × 162 + F × 163 + 9 × 164
1 × 160 + 15 × 161 + 11 × 162 + 15 × 163 + 9 × 164
import jdk.internal.dynalink.linker.ConversionComparator;
import java.util.Stack;
public class BinaryConversion {
public static void main(String[] args) {
//进制转化
int num = 654321;
String a = Conversion(num);
System.out.println(a);
String n = "9FBF1";
int p = Con(n);
System.out.println(p);
}
private static int Con(String n) {
// 16--> 10;
Stack <Character>s = new Stack();
int i = 0;
int rs = 0;
while (i < n.length()){
s.push(n.charAt(i));
i++;
}
while(!s.isEmpty()){
for (int j = 0; j < n.length(); j++) {
int p = s.pop();
if(p <=57 &&p >=49){
rs = rs+ (p-48) * mi(16,j);
}else if(p <=70 && p >=65){
rs = rs+ (p-55) * mi(16,j);
}else{
throw new IllegalArgumentException("erro");
}
}
}
return rs;
}
private static int mi(int i, int j) {
int c = 1;
if(i==0){
return 1;
}
for(i =0;i < j;i++){
c = c * 16;
}
return c;
}
private static String Conversion(int num) {
//10 --> 16
StringBuilder sb = new StringBuilder();
Stack<String> s = new Stack();
while (num!=0){
int res = num % 16 ;
if(res < 10 && res >=0){
s.push(res+"");
}else{
s.push((char)(res + 55) +"");
}
num = num/ 16;
}
while (!s.isEmpty()){
sb.append(s.pop());
}
return sb.toString();
}
}
括号匹配
import java.util.Stack;
public class ParenthesesMatching {
//括号匹配
public static void main(String[] args) {
String s1 = "{[<>]()}";
boolean matching = Matching(s1);
System.out.println(matching);
}
private static boolean Matching(String s1) {
Stack<Character> st = new Stack();
for (int i = 0; i < s1.length(); i++) {
//进栈 如果是空 或者 ASCII码的差值不为2或者1;
int res = 0;
if(!st.isEmpty()){
res = s1.charAt(i) - st.peek();
if (res ==1 || res == 2){
st.pop();
}else{
st.push(s1.charAt(i));
}
}else{
st.push(s1.charAt(i));
}
}
return st.isEmpty();
}
}
双端栈
双端栈的定义:
是指将一个线性表的两端当做栈底分别进行入栈和出栈操作
主要利用了栈“栈底位置不变,而栈顶位置动态变化” 的特性。
左栈为空:ltop = -1
左栈元素个数:ltop + 1
右栈为空:rtop = length
右栈元素个数:length – rtop
栈满:ltop + 1 = rtop
双端栈是线性表的一种,更是栈的一个特殊分类,可以用动态数组和栈的思想来实现双端栈
双端栈扩容缩容问题
因为双端栈对两端进行操作,所有不能用ArrayList来实现(ArrayList只能在一端进行操作)用数组来实现左右端 push pop peek 等方法
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
public class ArrayDoubleEndStack<E> implements Iterable<E> {
//属性和行为
//左端栈的栈顶
private int ltop;
//右端栈的栈顶
private int rtop;
//存储元素的容器
private E [] data;
//数组容器的默认容量
private static int Default_CAPACITY=10;
public ArrayDoubleEndStack(){
data = (E[]) new Object[Default_CAPACITY];
ltop = -1;
rtop = data.length;
}
public void pushLeft(E element){
//判断是否满了
if(ltop +1 == rtop){
resize(data.length *2);
}
data[++ltop] = element;
}
public void pushRight(E element){
if(ltop +1 == rtop){
resize(data.length *2);
}
data[--rtop] = element;
}
private void resize(int newLen) {
E[] newData = (E[]) new Object[newLen];
//复制左端栈
for (int i = 0; i <= ltop; i++) {
newData[i] = data[i];
}
//复制右端栈的元素
int index = rtop;
for (int i = newLen - sizeRight();i < newLen;i++){
newData[i] = data[index++];
}
rtop = newLen - sizeRight();
data = newData;
}
public E popLeft(){
if(isLeftEmpty()){
throw new IllegalArgumentException("left is null");
}
E ret = data[ltop--];
if(sizeLeft() +sizeRight() <= data.length/4 && data.length>Default_CAPACITY){
resize(data.length/2);
}
return ret;
}
public E popRight(){
if(isRightEmpty()){
throw new IllegalArgumentException("right is null");
}
E ret = data[rtop++];
if(sizeLeft() +sizeRight() <= data.length/4 && data.length>Default_CAPACITY){
resize(data.length/2);
}
return ret;
}
public E peekLeft(){
if(isLeftEmpty()){
throw new IllegalArgumentException("left is null");
}
return data[ltop];
}
public E peekRight(){
if(isRightEmpty()){
throw new IllegalArgumentException("right is null");
}
return data[rtop];
}
public boolean isLeftEmpty(){
return ltop ==-1;
}
public boolean isRightEmpty(){
return rtop== data.length;
}
private int sizeRight() {
return data.length - rtop;
}
private int sizeLeft() {
return ltop;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
if(isLeftEmpty()&& isRightEmpty()){
sb.append("]");
return sb.toString();
}
//左边
for (int i = 0; i <= ltop; i++) {
sb.append(data[i]);
if(i==ltop && isRightEmpty()){
sb.append("]");
return sb.toString();
}else{
sb.append(",");
}
}
//右边
for (int i = rtop; i < data.length ; i++) {
sb.append(data[i]);
if(i == data.length-1){
sb.append("]");
}else{
sb.append(",");
}
}
return sb.toString();
}
@Override
public Iterator<E> iterator () {
return new ArrayDoubleEndStackStackInerator();
}
class ArrayDoubleEndStackStackInerator implements Iterator<E>{
private ArrayList<E>list1 ;
private Iterator<E>it;
public ArrayDoubleEndStackStackInerator(){
list1 = new ArrayList<>();
for (int i = 0; i < ltop; i++) {
list1.add(data[i]);
}
for (int i = rtop; i < data.length ; i++) {
list1.add(data[i]);
}
it = list1.iterator();
}
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public E next() {
return it.next();
}
}
}
用ArrayList实现队列
定义:
1.队列只是允许在一端进行插入操作,而在另一端进行删除操作的线性表
2.队首:允许删除的一端。
3.队尾:插入的一端
4.不含任何数据元素的队列称为空队列
5.队列本身就是一个线性表,其数据元素具有线性关系,只不过他是一种特殊的线性表
6.队列的插入叫做入队
7.队列的删除叫做出队
import p1.接口.Queue;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Objects;
public class ArrayQueue<E> implements Queue<E> {
//底层用ArrayList
private ArrayList<E> list ;
public ArrayQueue(){
list = new ArrayList<>();
}
@Override
public void offer(E element) {
//入队
list.add(list.size(), element);
}
@Override
public E poll() {
return list.remove(0);
}
@Override
public E peek() {
return list.get(0);
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void clear() {
list.clear();
}
@Override
public int size() {
return list.size();
}
@Override
public Iterator<E> iterator() {
return list.iterator();
}
@Override
public String toString() {
return list.toString();
}
@Override
public boolean equals(Object o) {
if(o==null){
return false;
}
if(this ==o){
return true;
}
if(o instanceof ArrayQueue){
ArrayQueue other = (ArrayQueue) o;
return list.equals(other.list);
}
return false;
}
}
用栈实现队列
用两个栈来实现队列的功能
stack A主要存储元素
stackB 临时存储元素
import p1.接口.Queue;
import java.util.Iterator;
import java.util.Stack;
public class StackToQueue {
//栈实现队列
public static void main(String[] args) {
QueueImplByStack <Integer> queue = new QueueImplByStack<>();
for(int i =1;i <=5;i++){
queue.offer(i);
}
System.out.println(queue);
System.out.println(queue.poll());
System.out.println(queue);
}
}
class QueueImplByStack<E> implements Queue<E>{
private Stack<E> stackA;
private Stack<E> stackB;
public QueueImplByStack(){
stackA = new Stack<>();
stackB = new Stack<>();
}
@Override
public void offer(E element) {
stackA.push(element);
}
@Override
public E poll() {
if(isEmpty()){
throw new IllegalArgumentException("queue is null");
}
while (stackA.size()!=1){
stackB.push(stackA.pop());
}
E ret = stackA.pop();
while (!stackB.isEmpty()){
stackA.push(stackB.pop());
}
return ret;
}
@Override
public E peek() {
if(isEmpty()){
throw new IllegalArgumentException("queue is null");
}
while (stackA.size()!=1){
stackB.push(stackA.pop());
}
E ret = stackA.peek();
while (!stackB.isEmpty()){
stackA.push(stackB.pop());
}
return ret;
}
@Override
public boolean isEmpty() {
return stackA.isEmpty();
}
@Override
public void clear() {
stackA.clear();
stackB.clear();
}
@Override
public int size() {
return stackA.size();
}
@Override
public Iterator<E> iterator() {
return stackA.iterator();
}
@Override
public String toString() {
return stackA.toString();
}
}