为了账号安全,请及时绑定邮箱和手机立即绑定

go语言数据结构之栈的实现 栈

标签:
Go 数据结构

stack.go

package data_struct

import (
    "fmt"
    "log"
)

//数据结构 栈  先进后出,像电梯

type Stack struct {
    size int64 //容量
    top  int64 //栈顶
    data []interface{}
}

func MakeStack(size int64) Stack {
    q := Stack{}
    q.size = size
    q.data = make([]interface{}, size)
    return q
}

//入栈,栈顶升高
func (t *Stack) Push(element interface{}) bool {
    if t.IsFull() {
        log.Printf("栈已满,无法完成入栈")
        return false
    }
    t.data[t.top] = element
    t.top++
    return true
}

//出栈,栈顶下降
func (t *Stack) Pop() (r interface{}, err error) {
    if t.IsEmpty() {
        err = fmt.Errorf("栈已满,无法完成入栈")
        log.Println("栈已满,无法完成入栈")
        return
    }
    t.top--
    r = t.data[t.top]
    return
}

//栈长度, 已有容量的长度
func (t *Stack) StackLength() int64 {
    return t.top
}

//清空, 不需要清空值 ,再入栈,覆盖即可
func (t *Stack) Clear() {
    t.top = 0
}

//判空
func (t *Stack) IsEmpty() bool {
    return t.top == 0
}

//判满
func (t *Stack) IsFull() bool {
    return t.top == t.size
}

//遍历
func (t *Stack) Traverse(fn func(node interface{}), isTop2Bottom bool) {
    if isTop2Bottom {
        var i int64 = 0
        for ; i < t.top; i++ {
            fn(t.data[i])
        }
    } else {
        for i := t.top - 1; i >= 0; i-- {
            fn(t.data[i])
        }
    }

}

stack_test.go

package data_struct

import (
    "fmt"
    "testing"
)

func TestNewStack(t *testing.T) {
    s := int64(4)
    q := MakeStack(s)
    if q.size != s {
        t.Error("初始长度%d与创建的栈长度%d不一致", s, q.size)
    }
    if q.top != 0 {
        t.Error("栈顶值不正确,衩始化时,栈顶应为0,实际为%d", q.top)
    }
    if !q.IsEmpty() {
        t.Error("栈应为空,实际为非空")
    }
    if q.IsFull() {
        t.Error("新创建的栈,不应为满")
    }
    if q.StackLength() != 0 {
        t.Error("初始长度应为0,但现在是%d", q.StackLength())
    }
}
func TestStack_Push(t *testing.T) {
    s := int64(4)
    q := MakeStack(s)
    q.Push(10)
    if q.StackLength() != 1 {
        t.Error("长度应为1,但现在是%d", q.StackLength())
    }
    q.Push(12)
    q.Push(14)
    q.Push(16)
    v := q.Push(18)
    if v == true {
        t.Error("满的栈不能再加入,应返回假")
    }
    if q.StackLength() != s {
        t.Error("长度应为%s,但现在是%d", s, q.StackLength())
    }
    q.Clear()
    if q.StackLength() != 0 {
        t.Error("长度应为0,但现在是%d", q.StackLength())
    }
}
func TestStack_Pop(t *testing.T) {
    s := int64(4)
    q := MakeStack(s)
    q.Push(10)
    q.Push(12)
    q.Push(14)
    q.Push(16)
    v, err := q.Pop()
    if err != nil {
        t.Errorf("执行Stack_Pop报错, %s", err)
    }
    if v != 16 {
        t.Errorf("此时栈顶应为16, 但取到的值为%d", v)
    }
    v, err = q.Pop()
    if v != 14 {
        t.Errorf("此时栈顶应为14, 但取到的值为%d", v)
    }
    if q.StackLength() != s-2 {
        t.Errorf("长度应为%d,但现在是%d", s-2, q.StackLength())
    }
}

//测试遍历
func ExampleStack_Traverse() {
    s := int64(4)
    q := MakeStack(s)
    q.Push(10)
    q.Push(12)
    q.Push(14)
    q.Push(16)
    q.Traverse(func(node interface{}) {
        fmt.Println(node)
    }, false)

    q.Pop()
    q.Traverse(func(node interface{}) {
        fmt.Println(node)
    }, true)
    //output:
    //16
    //14
    //12
    //10
    //10
    //12
    //14
}

func ExampleStackDemo1() {

    //栈应用一,十进制转换
    /**
    *   短除法进制转换规则
        N = (N div d)  * d + N mod d    (div ,除, Mod ,求余)
        十进制转8进制
        N       N div 8     N mod 8
        1348    168         4
        168     21          0
        21      2           5
        2       0           2

        N       N div 16    N mod 16
        1348    84          4
        84      5           4
        5       0           5
    *
    **/
    const BINARY int = 2
    const OCTONARY int = 8
    const HEXADECIMAL int = 16

    var fn_c = func(n int, target int) {
        var stack = MakeStack(40)
        for {
            if n == 0 {
                break
            }
            stack.Push(n % target)
            n = n / target
        }
        stack.Traverse(func(node interface{}) {
            fmt.Print(node)
        }, false)
    }

    fn_c(1348, OCTONARY)
    fmt.Println()
    fn_c(1348, HEXADECIMAL)
    fmt.Println()
    fn_c(1348, BINARY)

    //output:
    // 2504
    // 544
    // 10101000100
}
点击查看更多内容
3人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消