데이터 구조 - 4 - 스 택
112637 단어 데이터 구조
1. 개념
스 택 과 대기 열 이 유사 합 니 다. 다른 것 은 스 택 이
LIFO
last-in-first-out
의 원칙, 즉 마지막 스 택 에 들 어간 요 소 를 가장 먼저 꺼 내 는 것 입 니 다.오다
2. 상용 방법
【 1 】 배열 창고
class ArrayStack<T> {
private final int length;
private Object[] array;
private int top; //
public ArrayStack(int length) {
this.length = length;
this.array = new Object[this.length];
this.top = -1;
}
public void push(T element) {
if (isFull()) {
return;
}
array[++top] = element;
}
@SuppressWarnings("unchecked")
public T pop() {
if (isEmpty()) {
return null;
}
return (T)array[top--];
}
@SuppressWarnings("unchecked")
public T peek() {
if (isEmpty()) {
return null;
}
return (T)array[top];
}
public boolean isFull() {
return top == length - 1;
}
public boolean isEmpty() {
return top == -1;
}
@Override
public String toString() {
if (isEmpty()) {
return "[]";
}
StringBuilder sBuilder = new StringBuilder("[");
for (int i = top; i > 0; i--) {
sBuilder.append(array[i]).append(',').append(' ');
}
sBuilder.append(array[0]).append(']');
return sBuilder.toString();
}
}
【 2 】 링크 스 택
class LinkedStack<T> {
private final int length;
private Node<T> top;
private int size;
public LinkedStack(int length) {
this.length = length;
this.top = null;
this.size = 0;
}
public void push(T element) {
if (isFull()) {
return;
}
Node<T> add = new Node<T>(element);
add.next = top;
top = add;
this.size++;
}
public T pop() {
if (isEmpty()) {
return null;
}
Node<T> node = this.top;
this.top = node.next;
this.size--;
return node.element;
}
public T peek() {
if (isEmpty()) {
return null;
}
return this.top.element;
}
public boolean isFull() {
return size == length;
}
public boolean isEmpty() {
return this.top == null;
}
private static class Node<T> {
private T element;
private Node<T> next;
public Node(T element) {
this.element = element;
}
@Override
public String toString() {
return (null != element) ? element.toString() : "null";
}
}
@Override
public String toString() {
if (isEmpty()) {
return "[]";
}
StringBuilder sBuilder = new StringBuilder("[");
Node<T> node = this.top;
while (true) {
sBuilder.append(node.element);
if (null == node.next) {
break;
}
node = node.next;
sBuilder.append(',').append(' ');
}
sBuilder.append(']');
return sBuilder.toString();
}
}
4. 응용
【 1 】 접미사 식
접미사 표현 식 은 우리 가 일상적으로 계산 할 때 사용 하 는 표현 식 알고리즘 이다. 예 를 들 어 1 + 2 * (3 / 4.5)
즉 연산 자 는 연산 량 의 중간 에 있다.인간 에 게 는 계산 이 편리 하지만 컴퓨터 로 계산 할 때 는 비교적 번거롭다.
계산 방식:
예시:
import java.util.Stack;
class InfixExpression {
public static double calc(String expression) {
if (null == expression || 0 == expression.length()) {
return 0;
}
// , 、 、
expression = expression.replaceAll("\\s", "");
if (0 == expression.length()) {
return 0;
}
return split(expression);
}
private static double split(String expression) {
Stack<String> digitStack = new Stack<String>();
Stack<String> operatorStack = new Stack<String>();
String digit = "";
for (int i = 0, len = expression.length(); i < len; i++) {
char ch = expression.charAt(i);
if (isOperator(ch)) {
if (!"".equals(digit)) { //
digitStack.push(digit);
digit = "";
}
if (operatorStack.isEmpty()) { //
operatorStack.push(String.valueOf(ch));
} else {
if ('(' == ch) {
operatorStack.push(String.valueOf(ch));
} else if (')' == ch) {
char operator = operatorStack.pop().charAt(0);
while ('(' != operator) {
String digit1 = digitStack.pop();
String digit2 = digitStack.pop();
double calc = calc(digit1, digit2, operator);
digitStack.push(Double.toString(calc));
operator = operatorStack.pop().charAt(0);
}
} else {
char pop = operatorStack.pop().charAt(0);
//
if (getPriority(ch) > getPriority(pop)) {
operatorStack.push(String.valueOf(pop));
} else {
String digit1 = digitStack.pop();
String digit2 = digitStack.pop();
double calc = calc(digit1, digit2, pop);
digitStack.push(Double.toString(calc));
}
operatorStack.push(String.valueOf(ch));
}
}
} else {
digit += ch;
}
}
if (!"".equals(digit)) { //
digitStack.push(digit);
}
return result(digitStack, operatorStack);
}
/**
*
*/
private static boolean isOperator(char ch) {
return '+' == ch || '-' == ch || '*' == ch || '/' == ch || '(' == ch || ')' == ch;
}
private static double calc(String digit1, String digit2, char operator) {
switch (operator) {
case '+':
return Double.valueOf(digit2) + Double.valueOf(digit1);
case '-':
return Double.valueOf(digit2) - Double.valueOf(digit1);
case '*':
return Double.valueOf(digit2) * Double.valueOf(digit1);
case '/':
return Double.valueOf(digit2) / Double.valueOf(digit1);
default:
return 0;
}
}
private static int getPriority(char operator) {
switch (operator) {
case '(':
return 0;
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
default:
throw new IllegalArgumentException(" !");
}
}
private static double result(Stack<String> digitStack, Stack<String> operatorStack) {
while (!operatorStack.isEmpty()) { //
String digit1 = digitStack.pop();
String digit2 = digitStack.pop();
char operator = operatorStack.pop().charAt(0);
double calc = calc(digit1, digit2, operator);
digitStack.push(Double.toString(calc));
}
return Double.valueOf(digitStack.pop()); // :
}
}
[2] 접두사 표현 식 (폴란드 표현 식)
접두사 표현 식 은 연산 자가 연산 량 의 앞 에 있 습 니 다. 예 를 들 어 + 1 * 2 / 3 4.5 입 니 다.
접두사 식 접두사 식:
예시:
import java.util.Stack;
class PrefixExpression {
public static double calc(String expression) {
if (null == expression || 0 == expression.length()) {
return 0;
}
expression = expression.replaceAll("\\s", "");
if (0 == expression.length()) {
return 0;
}
return split(expression);
}
private static double split(String expression) {
Stack<String> digitStack = new Stack<String>();
Stack<String> operatorStack = new Stack<String>();
String digit = "";
for (int i = expression.length() - 1; i >= 0; i--) { //
char ch = expression.charAt(i);
if (isOperator(ch)) {
if (!"".equals(digit)) { //
digitStack.push(digit);
digit = "";
}
if (operatorStack.isEmpty()) { //
operatorStack.push(String.valueOf(ch));
} else {
if (')' == ch) {
operatorStack.push(String.valueOf(ch));
} else if ('(' == ch) {
char operator = operatorStack.pop().charAt(0);
while (')' != operator) {
digitStack.push(String.valueOf(operator));
operator = operatorStack.pop().charAt(0);
}
} else {
char pop = operatorStack.pop().charAt(0);
if (getPriority(ch) >= getPriority(pop)) {
operatorStack.push(String.valueOf(pop));
} else {
digitStack.push(String.valueOf(pop));
}
operatorStack.push(String.valueOf(ch));
}
}
} else {
digit = ch + digit; //
}
}
if (!"".equals(digit)) { //
digitStack.push(digit);
}
while (!operatorStack.isEmpty()) { //
digitStack.push(operatorStack.pop());
}
return result(digitStack);
}
/**
*
*/
private static boolean isOperator(char ch) {
return '+' == ch || '-' == ch || '*' == ch || '/' == ch || '(' == ch || ')' == ch;
}
private static double calc(String digit1, String digit2, char operator) {
switch (operator) {
case '+':
return Double.valueOf(digit1) + Double.valueOf(digit2);
case '-':
return Double.valueOf(digit1) - Double.valueOf(digit2);
case '*':
return Double.valueOf(digit1) * Double.valueOf(digit2);
case '/':
return Double.valueOf(digit1) / Double.valueOf(digit2);
default:
return 0;
}
}
private static int getPriority(char operator) {
switch (operator) {
case ')':
return 0;
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
default:
throw new IllegalArgumentException(" !");
}
}
private static double result(Stack<String> digitStack) {
printNotation(digitStack);
Stack<String> temp = new Stack<String>();
while (!digitStack.isEmpty()) { //
temp.push(digitStack.pop());
}
Stack<String> tempDigitStack = new Stack<String>();
while (!temp.isEmpty()) {
String pop = temp.pop();
char first = pop.charAt(0);
if (isOperator(first)) {
String digit1 = tempDigitStack.pop();
String digit2 = tempDigitStack.pop();
double calc = calc(digit1, digit2, first);
tempDigitStack.push(Double.toString(calc));
} else {
tempDigitStack.push(pop);
}
}
return Double.valueOf(tempDigitStack.pop());
}
private static void printNotation(Stack<String> digitStack) {
for (int i = digitStack.size() - 1; i >= 0; i--) {
System.out.print(digitStack.get(i) + " ");
}
System.out.println();
}
}
【 3 】 접미사 표현 식 (역 폴란드 표현 식)
역 폴란드 식 (reverse Polish notation, RPN) 은 연산 량 을 앞 에 쓰 고 연산 자 를 뒤에 쓴다.
예: 1, 2, 3, 4.5 / * +
접미사 표현 식 역 폴란드 표현 식:
예시:
import java.util.Stack;
class RPN {
public static double calc(String expression) {
if (null == expression || 0 == expression.length()) {
return 0;
}
expression = expression.replaceAll("\\s", "");
if (0 == expression.length()) {
return 0;
}
return split(expression);
}
private static double split(String expression) {
Stack<String> digitStack = new Stack<String>();
Stack<String> operatorStack = new Stack<String>();
String digit = "";
for (int i = 0, len = expression.length(); i < len; i++) {
char ch = expression.charAt(i);
if (isOperator(ch)) {
if (!"".equals(digit)) { //
digitStack.push(digit);
digit = "";
}
if (operatorStack.isEmpty()) { //
operatorStack.push(String.valueOf(ch));
} else {
if ('(' == ch) {
operatorStack.push(String.valueOf(ch));
} else if (')' == ch) {
char operator = operatorStack.pop().charAt(0);
while ('(' != operator) {
digitStack.push(String.valueOf(operator));
operator = operatorStack.pop().charAt(0);
}
} else {
char pop = operatorStack.pop().charAt(0);
if (getPriority(ch) > getPriority(pop)) {
operatorStack.push(String.valueOf(pop));
} else {
digitStack.push(String.valueOf(pop));
}
operatorStack.push(String.valueOf(ch));
}
}
} else {
digit += ch;
}
}
if (!"".equals(digit)) { //
digitStack.push(digit);
}
while (!operatorStack.isEmpty()) { //
digitStack.push(operatorStack.pop());
}
Stack<String> temp = new Stack<String>();
while (!digitStack.isEmpty()) { //
temp.push(digitStack.pop());
}
return result(temp);
}
/**
*
*/
private static boolean isOperator(char ch) {
return '+' == ch || '-' == ch || '*' == ch || '/' == ch || '(' == ch || ')' == ch;
}
private static double calc(String digit1, String digit2, char operator) {
switch (operator) {
case '+':
return Double.valueOf(digit2) + Double.valueOf(digit1);
case '-':
return Double.valueOf(digit2) - Double.valueOf(digit1);
case '*':
return Double.valueOf(digit2) * Double.valueOf(digit1);
case '/':
return Double.valueOf(digit2) / Double.valueOf(digit1);
default:
return 0;
}
}
private static int getPriority(char operator) {
switch (operator) {
case '(':
return 0;
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
default:
throw new IllegalArgumentException(" !");
}
}
private static double result(Stack<String> digitStack) {
printNotation(digitStack);
Stack<String> tempDigitStack = new Stack<String>();
while (!digitStack.isEmpty()) {
String pop = digitStack.pop();
char first = pop.charAt(0);
if (isOperator(first)) {
String digit1 = tempDigitStack.pop();
String digit2 = tempDigitStack.pop();
double calc = calc(digit1, digit2, first);
tempDigitStack.push(Double.toString(calc));
} else {
tempDigitStack.push(pop);
}
}
return Double.valueOf(tempDigitStack.pop());
}
private static void printNotation(Stack<String> digitStack) {
for (int i = digitStack.size() - 1; i >= 0; i--) {
System.out.print(digitStack.get(i) + " ");
}
System.out.println();
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
정수 반전Udemy 에서 공부 한 것을 중얼거린다 Chapter3【Integer Reversal】 (예) 문자열로 숫자를 반전 (toString, split, reverse, join) 인수의 수치 (n)가 0보다 위 또는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.