01.3棧

棧(stack)

  • 基本介紹

    棧又名堆棧,它是一種運算受限的線性表。其限制是僅允許在表的一段進行插入和刪除運算。這一端被稱為棧頂,相對的,把另一端稱為棧底。向一個棧插入新元素又稱作進棧、入棧或壓棧,它是把新元素放到棧頂元素的上面,使之成為新的棧頂元素;從一個棧刪除元素又稱作出棧或退棧,它是把棧頂元素刪除掉,使其相鄰元素稱為新的棧頂元素。

  • 應用場景

    • 子程序的調用:在跳向子程序前,會將下個指令的地址存到堆棧中,直到子程序執行完後再將地址取出,以回到原來的程序中。
    • 處理遞歸調用:和子程序的調用類似,只是除了儲存下一個指令的地址外,也將參數、區域變量等數據存入堆棧中。
    • 表達式的轉換與求值
    • 二叉樹的遍歷
    • 圖形的深度優先搜索法
  • 數組模擬

    //數組模擬棧
    type Stack struct {
    	MaxTop int //最大可存放的個數
    	Top int //表示棧頂
    	arr [5]int //模擬棧
    }
    //入棧
    func (this *Stack)Push(val int) (err error) {
    	//判斷棧是否滿了
    	if this.Top == this.MaxTop - 1 {
    		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 {
    		return -1,errors.New("stack empty")
    	}
    	val = this.arr[this.Top]
    	this.Top--
    	return
    }
    //遍歷
    func (this *Stack) List() {
    	//棧是否為空
    	if this.Top == -1 {
    		fmt.Println("stack empty")
    		return
    	}
    	fmt.Println("list:")
    	for i := this.Top; i>= 0 ; i-- {
    		fmt.Printf("arr[%d] = %d\n",i,this.arr[i])
    	}
    }
    func main() {
    	a := &Stack{
    		MaxTop: 5,
    		Top:-1,
    	}
    	a.List()
    	fmt.Println(a.Pop())
    	a.Push(10)
    	a.List()
    	fmt.Println(a.Push(11))
    	fmt.Println(a.Push(12))
    	fmt.Println(a.Push(13))
    	fmt.Println(a.Push(14))
    	fmt.Println(a.Push(15))
    	a.List()
    	fmt.Println(a.Pop())
    	a.List()
    }
    
  • 棧實現加減乘除

    //由於計算一般是從前往後算,如果使用棧的後進先出的特性,
    //必須調轉表達式,如2*3-3/2-1寫成1-3/2-2*3
    //也可以自己寫函數完成字符串反轉,再入棧,這樣就可以按順序計算了
    //數組模擬棧
    type Stack struct {
    	MaxTop int //最大可存放的個數
    	Top int //表示棧頂
    	arr [20]int //模擬棧
    }
    //入棧
    func (this *Stack)Push(val int) (err error) {
    	//判斷棧是否滿了
    	if this.Top == this.MaxTop - 1 {
    		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 {
    		return -1,errors.New("stack empty")
    	}
    	val = this.arr[this.Top]
    	this.Top--
    	return
    }
    //遍歷
    func (this *Stack) List() {
    	//棧是否為空
    	if this.Top == -1 {
    		fmt.Println("stack empty")
    		return
    	}
    	fmt.Println("list:")
    	for i := this.Top; i>= 0 ; i-- {
    		fmt.Printf("arr[%d] = %d\n",i,this.arr[i])
    	}
    }
    //判斷一個字符串是不是運算符
    //42 = * ;43 = + ;45 = - ; 47 = /
    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, num2 int, oper int) int {
    	res := 0
    	switch oper {
    	case 42:
    		res = num2*num1
    	case 43:
    		res = num2+num1
    	case 45:
    		res = num1-num2
    	case 47:
    		res = num2/num1
    	default:
    		fmt.Println("運算符錯誤")
    	}
    	return res
    }
    //返回運算符的優先級
    func (this *Stack) Priority(oper int) int {
    	res := 0
    	if oper == 42 || oper == 47 {
    		res = 1
    	}
    	if oper == 43 || oper == 45 {
    		res = 0
    	}
    	return res
    }
    func main() {
    	//數棧
    	numStack := &Stack{
    		MaxTop: 20,
    		Top:-1,
    	}
    	//符號棧
    	operStack := &Stack{
    		MaxTop:20,
    		Top:-1,
    	}
    	for {
    		var exp string
    		fmt.Println("請輸入表達式:")
    		fmt.Scanln(&exp)
    		index := 0
    		num1 := 0
    		num2 := 0
    		oper := 0
    		result := 0
    		keepNum := ""
    		//掃描字符串
    		for {
    			//取出字符串中的各個字符
    			ch := exp[index:index+1]
    			//轉換成int做判斷
    			chint := int([]byte(ch)[0])
    			if operStack.IsOper(chint) {
    				//如果是空棧就直接入棧
    				if operStack.Top == -1 {
    					operStack.Push(chint)
    				}else {
    					//如果發現棧頂的運算符的優先級大於等於當前準備入棧的
    					//優先級,就從符號棧pop出,並從數棧也pop兩個數,進行
    					//運算,運算後的結果再重新入棧到數棧,當前符號在入符
    					// 號棧
    					if operStack.Priority(operStack.arr[operStack.Top])>
    						operStack.Priority(chint){
    						num1,_ = numStack.Pop()
    						num2,_ = numStack.Pop()
    						oper,_ = operStack.Pop()
    						result = operStack.Cal(num1,num2,oper)
    						numStack.Push(result)
    						operStack.Push(chint)
    					}else {
    						operStack.Push(chint)
    					}
    				}
    			}else {
    				//定義一個變量keepNum string,用於拼接
    				keepNum += ch
    				//如果到底了,就將數字壓入數棧
    				if index == len(exp)-1 {
    					val,_ := strconv.ParseInt(keepNum,10,64)
    					numStack.Push(int(val))
    
    				}else {
    					//如果是符號就壓入數棧
    					if operStack.IsOper(int([]byte(exp[index+1:index+2])[0])) {
    						val,_ := strconv.ParseInt(keepNum,10,64)
    						numStack.Push(int(val))
    						keepNum = ""
    					}
    				}
    			}
    			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)
    			fmt.Printf("%d %c %d = %d",num1,oper,num2,result)
    			fmt.Println()
    			numStack.Push(result)
    		}
    		//將結果出棧
    		res,_ := numStack.Pop()
    		fmt.Printf("表達式結果為:%d",res)
    		fmt.Println()
    	}
    }
    
鏈接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值