4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

スタック

  • Last In, First Outなデータ構造
  • 許される操作はPushPopClearだけ

逆ポーランド記法

逆ポーランド記法(ぎゃくポーランドきほう、英語: Reverse Polish Notation, RPN)は、数式やプログラムの記法の一種。演算子を被演算子の後にすることから、後置記法 (Postfix Notation) とも言う。

スタックを配列で実現する

  • スタックを宣言するときに長さを与える必要がある
package main

import (
	"fmt"
	"os"
)

const LENGTH = 10

type Stack struct {
	arr []int
	sp  int
}

func (s *Stack) Clear() {
	s.sp = -1
}

func (s *Stack) Push(val int) {
	if s.sp >= len(s.arr) {
		fmt.Printf("ERROR: stack overflow\n")
		os.Exit(1)
	}
	s.sp += 1         // スタックポインタを上げてから
	s.arr[s.sp] = val // プッシュ
}

func (s *Stack) Pop() int {
	if s.sp <= -1 {
		fmt.Printf("ERROR: stack underflow\n")
		os.Exit(1)
	}
	ret := s.arr[s.sp] // ポップしてから
	s.sp -= 1          // スタックポインタを下げる
	return ret
}

func NewStack(length int) *Stack {
	if length <= 0 {
		fmt.Println("ERROR: length of array should be more than zero")
		os.Exit(1)
	}
	return &Stack{
		arr: make([]int, length),
		sp: -1,
	}
}

func main() {
	input := make([]int, LENGTH)
	for i, _ := range input {
		input[i] = i
	}
	fmt.Println("Input: ", input)
	s := NewStack(LENGTH)
	for ele := range input {
		s.Push(ele)
	}
	for i := 0; i < LENGTH; i++ {
		fmt.Println("Pop: ", s.Pop())
	}
}

スタックをリストで実現する

  • スタックを宣言するときに長さが不要
package main

import (
	"fmt"
	"os"
)

type Cell struct {
	val int
	prev *Cell
	next *Cell
}

type Stack struct {
	sp *Cell
}

func (s *Stack) Clear() {
	s.sp = nil
}

func (s *Stack) Pop() int {
	if s.sp == nil {
		fmt.Println("ERROR: no value in stack")
		os.Exit(1)
	}
	ret := s.sp.val
	s.sp = s.sp.prev
	return ret
}

func (s *Stack) Push(val int) {
	fmt.Println("PUSH: ", val)
	c := NewCell(val)
	if s.sp == nil {
		s.sp = c
		return
	}
	s.sp.next = c
	c.prev = s.sp
	s.sp = c
}

func NewCell(val int) *Cell {
	return &Cell{val: val, prev: nil, next: nil}
}

func NewStack() *Stack {
	return &Stack{sp: nil}
}

func main() {
	s := NewStack()
	s.Push(3)
	s.Push(4)
	s.Push(5)
	fmt.Println("Pop: ", s.Pop())
	fmt.Println("Pop: ", s.Pop())
	fmt.Println("Pop: ", s.Pop())
}

逆ポーランド記法で書かれた式をスタックを用いて評価する

package main

import (
	"fmt"
	"os"
	"strconv"
	"strings"
)

type Stack struct {
	arr []int
	sp  int
}

func (s *Stack) Clear() {
	s.sp = -1
}

func (s *Stack) Push(val int) {
	if s.sp >= len(s.arr) {
		fmt.Printf("ERROR: stack overflow\n")
		os.Exit(1)
	}
	s.sp += 1         // スタックポインタを上げてから
	s.arr[s.sp] = val // プッシュ
}

func (s *Stack) Pop() int {
	if s.sp <= -1 {
		fmt.Printf("ERROR: stack underflow\n")
		os.Exit(1)
	}
	ret := s.arr[s.sp] // ポップしてから
	s.sp -= 1          // スタックポインタを下げる
	return ret
}

func NewStack(length int) *Stack {
	if length <= 0 {
		fmt.Println("ERROR: length of array should be more than zero")
		os.Exit(1)
	}
	return &Stack{
		arr: make([]int, length),
		sp: -1,
	}
}

func main() {
	target := "2 1 + 3 *"
	input := strings.Split(target, " ")
	s := NewStack(len(input) + 1)
	for _, ele := range input {
		switch ele {
		case "+":
			right := s.Pop()
			left := s.Pop()
			s.Push(left + right)
		case "-":
			right := s.Pop()
			left := s.Pop()
			s.Push(left - right)
		case "*":
			right := s.Pop()
			left := s.Pop()
			s.Push(left * right)
		case "/":
			right := s.Pop()
			left := s.Pop()
			s.Push(left / right)
		default:
			s.Push(atoi(ele))
		}
	}
	fmt.Println(target, " = ", s.Pop())

}

func atoi(a string) int {
	ret, _ := strconv.Atoi(a)
	return ret
}
ops = {
  "+": (lambda a, b: a + b),
  "-": (lambda a, b: a - b),
  "*": (lambda a, b: a * b),
  "/": (lambda a, b: a / b)
}

def eval(expression):
  tokens = expression.split()
  stack = []

  for token in tokens:
    if token in ops:
      arg2 = stack.pop()
      arg1 = stack.pop()
      result = ops[token](arg1, arg2)
      stack.append(result)
    else:
      stack.append(int(token))

  return stack.pop()
  
print(eval("1 2 + "))
print(eval("990 1 2 + *"))
print(eval("1000 990 1 2 + * +"))

暇なときに普通の式を逆ポーランド記法にコンパイルするプログラムを書く。

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?