这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战
数据结构
数据结构是计算机储存组织数据的方式,数据结构大体分成三大类型:线性结构,树形结构和图形结构,当然我们从最简单的线性结构来说。
线性结构的数据结构通常指的是n个相同类型元素的有限序列,N>=0。
线性结构数据通常也叫线性表。我们最常见的数组就是线性结构的,一般线性表中的数据类型应该是相同的,并且个数是有限的。线性表存储在计算机的储存中是连续的,所以内存地址也是连续的,所以在定义一个数组的时候数据是无法动态修改容量,如果储存方式不是连续的那么这种数据结构就是链表,链表我们放在后面再说吧。
在学习golang的过程中说了一下Golang的切片扩容: Go语言切片(8)
学习golang中我才认真了解到堆和栈这个概念,对于更底层的与堆栈相关性更高的底层语言C和C++没有认真去了解过。Golang切片底层是一个数组,数组是一个值类型的变量,切片是一个引用类型的变量。值类型的变量的值一般储存在栈中,引用类型是一种更复杂的存储结构,引用类型储存的值是一个内存地址,这个地址储存最终的值,引用类型的变量一般在堆上分配,通过GC(垃圾回收机制)回收,要学习后面的知识先复习一下基础。
栈
栈是一种先进后出的数据结构,使用数组实现的栈叫做顺序栈。栈只能在一端进行删除和增加的操作,经常听说的说的两个词语:入栈(也叫压栈,push)和出栈(也叫退栈,pop)就是在栈这个数据结构里面进行增加元素和删除元素的操作,在只能操作删除和增加的一端叫做栈顶,不能操作的一端叫做栈底,这样理解的话栈底就是最先入栈的元素,栈顶就是最后入栈的元素。最先入栈的元素是最后出栈的元素,所以叫先进后出。堆的知识相对于栈来说较为复杂,我们放在后面说。
Golang来实现一个栈的方法
栈的常用方法就是入栈和出栈,获取栈的元素个数,获取栈顶元素,顺便巩固一下Golang的知识.
首先使用Golang的结构体(struct)制定一个栈的抽象结构。包含了一个切片,切片中元素的个数.因为Golang中数组是不能进行扩容的,而切片是可以的,切片底层是一个数组,所以采用切片:
package main
import (
"errors"
"fmt"
)
type myStack struct {
sliceData []string //定义一个切片。切片元素类型为string
sliceLen int //栈中元素的个数
}
func makeStack() *myStack {
return &myStack{sliceData: make([]string, 0)} //返回一个结构体指针 ,让下面栈方法去操作指针类型(底层类型)而不是值类型
}
//返回栈的大小
func (s *myStack) size() int {
return s.sliceLen
}
//元素入栈
func (s *myStack) push(insertData string) {
s.sliceData = append(s.sliceData, insertData)
s.sliceLen = s.sliceLen + 1
}
//元素出栈并返回删除的元素
func (s *myStack) pop() interface{} {
if s.sliceLen > 0 {
s.sliceLen-- //栈长度减一
index := s.sliceData[s.sliceLen] //获取栈顶的元素
s.sliceData = s.sliceData[:s.sliceLen] //重新剪切切片。接去掉最后一个元素
return index //返回删除的元素
}
return errors.New("栈没有元素了")
}
//返回栈顶的元素
func (s *myStack) top() interface{} {
if s.isEmpty() { //栈为空就报错
return nil
}
return s.sliceData[s.sliceLen-1] // 切片的最后一个元素
}
//判断切片长度是否为空
func (p *myStack) isEmpty() bool {
return p.sliceLen == 0
}
func main() {
var stack = makeStack()
stack.push("hello")
fmt.Printf("数组长度:%d \n", stack.size())
stack.push("world")
fmt.Printf("数组长度:%d \n", stack.size())
stack.pop()
fmt.Printf("数组长度:%d \n", stack.size())
stack.push("我是土圭垚墝")
fmt.Printf("切片的栈顶是:%s \n", stack.top())
for i, j := range stack.sliceData {
fmt.Printf("切片第%d个内容是%s\n", i, j)
}
fmt.Printf("切片的长度是:%d \n", stack.sliceLen)
}
输出内容:
数组长度:1
数组长度:2
数组长度:1
切片的栈顶是:我是土圭垚墝
切片第0个内容是hello
切片第1个内容是我是土圭垚墝
切片的长度是:2
总结
这篇就简单认识了一下栈的各种操作方法,对数据结构有了初步了解,Goalng代码都很简单,没有学习Golang应该也可以看得懂。