🌞

Go实现一个支持动态扩容的数组

「 数组 」
一旦分配空间,不可再更改,容量限定,可能存在访问越界风险。


在此实现支持动态扩容的数组,能完成基本的增删改查操作,其数据结构定义及构造函数如下,使用数组 Data 保存数据,用 Size 记录当前已保存的数据的个数:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
type MyArray struct {
	Data []interface{}
	Size int
}

func NewMyArray(size int) *MyArray {
	if size == 0 {
		return nil
	}

	return &MyArray{
		make([]interface{}, size),
		size,
	}
}

📜快速访问

MyArray 内的 Data 本质是一个数组,在插入数据时,要考虑 Data 是否还有多余的空间保存数据,当空间不够时,我们对其进行扩容。扩容时,将容量翻倍,即申请一段新的连续内存,将已有的数据保存到新的内存空间中,时间复杂度为 O(n):

1
2
3
4
5
6
7
func (m *MyArray) resize() {
	newArray := make([]interface{}, 2*m.Size)
	for i := 0; i <= m.Size; i++ {
		newArray[i] = m.Data[i]
	}
	m.Data = newArray
}

Data 的最大容量为 len(Data) ,添加单个或多个数据时,比对 Size 和最大容量得知是否要扩容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
func (m *MyArray) AddItem(item interface{}) {
	if len(m.Data) == m.Size {
		m.resize()
	}
	m.Data[m.Size] = item
	m.Size++
}

func (m *MyArray) AddItems(items ...interface{}) {
	for item := range items {
		m.AddItem(item)
	}
}

删除操作有两种方式,删除具体数据,可能存在多个相同的数据,

1
2
3
4
5
6
7
8
9
// 删
func (m *MyArray) Remove(target interface{}) {
	newArray := make([]interface{}, len(m.Data))
	for i := 0; i < m.Size; i++ {
		if m.Data[i] != target {
			newArray = append(newArray, m.Data[i])
		}
	}
}

以及删除数组指定下标的数据,在删除前,要检查下标是否合法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
func (m *MyArray) RemoveWithIndex(index int) {
	if index < 0 || index > len(m.Data) {
		panic("Illegal index.")
	}
	newArray := make([]interface{}, len(m.Data))
	for i := 0; i < m.Size; i++ {
		if i != index {
			newArray[i] = m.Data[i]
		}
	}
	m.Data = newArray
}

修改一般是对指定下标的数据做修改,类似删除,也需要做下标合法检查:

1
2
3
4
5
6
func (m *MyArray) Set(index int, item interface{}) {
	if index < 0 || index > len(m.Data) {
		panic("Illegal index.")
	}
	m.Data[index] = item
}

查找支持查找单个和查找多个,根据数据内容查找对应的数组下标,并利用这个方法判断数据是否存在于数组中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func (m *MyArray) FindItem(target interface{}) int {
	for i := 0; i < m.Size; i++ {
		if m.Data[i] == target {
			return i
		}
	}
	return -1
}

func (m *MyArray) FindAllItems(target interface{}) (result []int) {
	for i := 0; i < m.Size; i++ {
		if m.Data[i] == target {
			result = append(result, i)
		}
	}
	return
}

func (m *MyArray) Contains(target interface{}) bool {
	if m.FindItem(target) == -1 {
		return false
	}
	return true
}

根据数组下标查找具体的数据,批量查找应以列表的形式返回:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
func (m *MyArray) GetItem(index int) interface{} {
	if index > len(m.Data) || index < 0 {
		return nil
	}
	return m.Data[index]
}

func (m *MyArray) GetItems(indexes ...int) []interface{} {
	result := make([]interface{}, len(indexes))
	for i := range indexes {
		if i >= 0 && i < m.Size {
			result = append(result, m.Data[i])
		}
	}

	return result
}

其他

获取最大容量及当前容量,使用当前容量判断数组是否为空:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func (m *MyArray) GetCapacity() int {
	return len(m.Data)
}

func (m *MyArray) GetSize() int {
	return m.Size
}

func (m *MyArray) IsEmpty() bool {
	return m.Size == 0
}
updatedupdated2020-05-062020-05-06