zoukankan      html  css  js  c++  java
  • Go_栈

    1. 栈的介绍

    2. 栈的应用

    3. 栈入门

    package main
    
    import (
    	"fmt"
    	"errors"
    )
    
    //使用数组来模拟一个栈的使用
    type Stack struct {
    	MaxTop int    // 表示我们栈最大可以存放数个数
    	Top    int    // 表示栈顶, 因为栈顶固定,因此我们直接使用Top
    	arr    [5]int // 数组模拟栈
    }
    
    //入栈
    func (this *Stack) Push(val int) (err error) {
    
    	//先判断栈是否满了
    	if this.Top == this.MaxTop-1 {
    		fmt.Println("stack full")
    		return errors.New("stack full")
    	}
    	this.Top++
    	//放入数据
    	this.arr[this.Top] = val
    	return
    }
    
    //出栈
    func (this *Stack) Pop() (val int, err error) {
    	//判断栈是否空
    	if this.Top == -1 {
    		fmt.Println("stack empty!")
    		return 0, errors.New("stack empty")
    	}
    
    	//先取值,再 this.Top--
    	val = this.arr[this.Top]
    	this.Top--
    	return val, nil
    
    }
    
    //遍历栈,注意需要从栈顶开始遍历
    func (this *Stack) List() {
    	//先判断栈是否为空
    	if this.Top == -1 {
    		fmt.Println("stack empty")
    		return
    	}
    	fmt.Println("栈的情况如下:")
    	for i := this.Top; i >= 0; i-- {
    		fmt.Printf("arr[%d]=%d
    ", i, this.arr[i])
    	}
    
    }
    
    func main() {
    
    	stack := &Stack{
    		MaxTop: 5,  // 表示最多存放5个数到栈中
    		Top:    -1, // 当栈顶为-1,表示栈为空
    	}
    
    	//入栈
    	stack.Push(1)
    	stack.Push(2)
    	stack.Push(3)
    	stack.Push(4)
    	stack.Push(5)
    
    	//显示
    	stack.List()
    	val, _ := stack.Pop()
    	fmt.Println("出栈val=", val) // 5
    	//显示
    	stack.List() //
    
    	fmt.Println()
    	val, _ = stack.Pop()
    	val, _ = stack.Pop()
    	val, _ = stack.Pop()
    	val, _ = stack.Pop()
    	val, _ = stack.Pop()       // 出错
    	fmt.Println("出栈val=", val) // 5
    	//显示
    	stack.List() //
    }
    

    4. 栈的计算表达式

    package main
    import (
    	"fmt"
    	"errors"
    	"strconv"
    )
    
    //使用数组来模拟一个栈的使用
    type Stack struct {
    	MaxTop int  // 表示我们栈最大可以存放数个数
    	Top int // 表示栈顶, 因为栈顶固定,因此我们直接使用Top
    	arr [20]int // 数组模拟栈
    }
    //入栈
    func (this *Stack) Push(val int) (err error) {
    
    	//先判断栈是否满了
    	if this.Top == this.MaxTop - 1 {
    		fmt.Println("stack full")
    		return errors.New("stack full")
    	}
    	this.Top++ 
    	//放入数据
    	this.arr[this.Top] = val
    	return 
    }
    
    //出栈
    func (this *Stack) Pop() (val int, err error) {
    	//判断栈是否空
    	if this.Top == -1 {
    		fmt.Println("stack empty!")
    		return 0, errors.New("stack empty")
    	} 
    
    	//先取值,再 this.Top--
    	val =  this.arr[this.Top]
    	this.Top--
    	return val, nil
    
    }
    //遍历栈,注意需要从栈顶开始遍历
    func (this *Stack) List() {
    	//先判断栈是否为空
    	if this.Top == -1 {
    		fmt.Println("stack empty")
    		return 
    	}
    	fmt.Println("栈的情况如下:")
    	for i := this.Top; i >= 0; i-- {
    		fmt.Printf("arr[%d]=%d
    ", i, this.arr[i])
    	}
    
    }
    //判断一个字符是不是一个运算符[+, - , * , /]
    func (this *Stack) IsOper(val int) bool {
    
    	if val == 42 || val == 43 || val == 45 || val == 47 {
    		return true
    	} else {
    		return false
    	}
    }
    
    //运算的方法
    func (this *Stack) Cal(num1 int, num2 int, oper int) int{
    	res := 0
    	switch oper {
    		case 42 :
    			res = num2 * num1
    		case 43 :
    			res = num2 + num1
    		case 45 :
    			res = num2 - num1
    		case 47 :
    			res = num2 / num1
    		default :
    			fmt.Println("运算符错误.")
    	}
    	return res
    }
    
    //编写一个方法,返回某个运算符的优先级[程序员定义]
    //[* / => 1 + - => 0]
    func (this *Stack) Priority(oper int) int {
    	res := 0
    	if oper == 42 || oper == 47 {
    		res = 1
    	} else if oper == 43 || oper == 45 {
    		res = 0
    	} 
    	return res
    } 
    
    func main() {
    
    	//数栈
    	numStack := &Stack{
    		MaxTop : 20,
    		Top : -1,
    	}
    	//符号栈
    	operStack := &Stack{
    		MaxTop : 20,
    		Top : -1,
    	}
    
    	exp := "30+30*6-4-6"
    	//定义一个index ,帮助扫描exp
    	index := 0
    	//为了配合运算,我们定义需要的变量
    	num1 := 0
    	num2 := 0
    	oper := 0
    	result := 0
    	keepNum := "" 
    
    	for {
    		//这里我们需要增加一个逻辑,
    		//处理多位数的问题
    		ch := exp[index:index+1] // 字符串.
    		//ch ==>"+" ===> 43
    		temp := int([]byte(ch)[0]) // 就是字符对应的ASCiI码
    		if operStack.IsOper(temp) { // 说明是符号
    
    			//如果operStack  是一个空栈, 直接入栈
    			if operStack.Top == -1 { //空栈
    				operStack.Push(temp)
    			}else {
    				//如果发现opertStack栈顶的运算符的优先级大于等于当前准备入栈的运算符的优先级
    				//,就从符号栈pop出,并从数栈也pop 两个数,进行运算,运算后的结果再重新入栈
    				//到数栈, 当前符号再入符号栈
    				if operStack.Priority(operStack.arr[operStack.Top]) >= 
    					operStack.Priority(temp) {
    						num1, _ = numStack.Pop()
    						num2, _ = numStack.Pop()
    						oper, _ = operStack.Pop()
    						result = operStack.Cal(num1,num2, oper)
    						//将计算结果重新入数栈
    						numStack.Push(result)
    						//当前的符号压入符号栈
    						operStack.Push(temp)
    
    				}else {
    					operStack.Push(temp)
    				}
    
    			}
    
    
    		} else { //说明是数
    			
    			//处理多位数的思路
    			//1.定义一个变量 keepNum string, 做拼接
    			keepNum += ch 
    			//2.每次要向index的后面字符测试一下,看看是不是运算符,然后处理
    			//如果已经到表达最后,直接将 keepNum
    			if index == len(exp) - 1 { 
    				val, _ := strconv.ParseInt(keepNum, 10, 64)
    				numStack.Push(int(val))
    			} else {
    				//向index 后面测试看看是不是运算符 [index]
    				if operStack.IsOper(int([]byte(exp[index+1:index+2])[0])) {
    					val, _ := strconv.ParseInt(keepNum, 10, 64)
    					numStack.Push(int(val))
    					keepNum = ""
    				}
    			}
    		}
    
    		//继续扫描
    		//先判断index是否已经扫描到计算表达式的最后
    		if index + 1 == len(exp) {
    			break
    		}
    		index++
    
    	}
    
    	//如果扫描表达式 完毕,依次从符号栈取出符号,然后从数栈取出两个数,
    	//运算后的结果,入数栈,直到符号栈为空
    	for {
    		if operStack.Top == -1 {
    			break //退出条件
    		}
    		num1, _ = numStack.Pop()
    		num2, _ = numStack.Pop()
    		oper, _ = operStack.Pop()
    		result = operStack.Cal(num1,num2, oper)
    		//将计算结果重新入数栈
    		numStack.Push(result)
    		
    	}
    
    	//如果我们的算法没有问题,表达式也是正确的,则结果就是numStack最后数
    	res, _ := numStack.Pop()
    	fmt.Printf("表达式%s = %v", exp, res)
    }
    

      

  • 相关阅读:
    可视化工具之 IGV 使用方法
    SAM格式 及 比对工具之 samtools 使用方法
    比对工具之 BWA 使用方法
    项目一:使用二代测序数据进行基因组组装(局部组装)
    Linux 打包和压缩 方法详解
    Oracle 11G R2 RAC中的scan ip 的用途和基本原理【转】
    ORACLE表空间查询和管理【转】
    MySQL分布式集群之MyCAT(三)rule的分析【转】
    MySQL分布式集群之MyCAT(二)【转】
    linux快速复制大量小文件方法 nc+tar【转】
  • 原文地址:https://www.cnblogs.com/yzg-14/p/12239526.html
Copyright © 2011-2022 走看看