0.简介
本文提供了无序数组以及一些实验性质的处理,共三种并附有ts代码。主要目的是为了提高列表删除和查找的效率。
1.前言(无关内容可跳过)
练手时的一些相关记录,主要是效率呀,效率呀,希望能够提高运行效率
2.无序列表(加快增删处理)
对于正常列表来说,它是有序的,有利于遍历的,不利于删除元素和插入元素,这种操作会带来额外的数据拷贝处理(基于链表的列表除外)。但有些时候列表元素的排列循序对我们来说没那重要,比如计算所有学生的分数,这个学生数组的顺序并不会对我们的需求有影响,所以我们可以忽略列表的顺序来加快插入和删除处理。
(1)插入因为没有列表没有顺序,所以与增加相同,可以直接加在列表尾部,没有数据复制移动问题
(2)直接删除前面的元素时,后面的元素需要往前复制,以补上删除的空缺。但如果列表是无序的,那我们可以先将删除的位置和队尾元素做一个互换,然后再删除队尾元素,来避免数据复制等问题。
/** 一个无序的数组,提供较为快速的删除和插入处理 */
export class UnorderedArray<T> {
/** Group成员,不应该对此直接进行修改*/
public readonly Members: Array<T> = new Array<T>()
public Add(item: T) {
this.Members.push(item)
}
public Remove(item: T) {
let index = this.Members.indexOf(item)
if (index < this.Members.length - 1) {
this.Members[index] = this.Members[this.Members.length - 1]
}
this.Members.pop()
}
}
3.无序列表+缓存(推迟增删处理)
有时我们在遍历数组时可能会对数组进行增加或者删除,但是会影响后续遍历处理,比如数组越界,如果遍历中删除是非必须的,那么将要操作的数据保存起来,延迟到遍历后操作。比如游戏在某一帧中,删除一个特效对象,这个特效对象不是立刻就要删除的,结束后再删对玩家来说都没感觉,这个时候就可以先缓存一下,然后推迟到遍历结束。所以写出了这个
/**
* 一个无序的数组,提供较为额外删除和插入处理。
* 当Lock开启时将会保存插入和删除的数据到缓存数组中,等到lock解除时再处理,会先执行添加再删除
* */
export class CacheArray<T> {
private lock: boolean = false
/** Group成员,不应该对此直接进行修改*/
public readonly Members: Array<T> = new Array<T>()
/** 等待添加的缓存,不应该对此直接进行修改*/
public readonly AddCache: Array<T> = new Array<T>()
/** 等待删除的缓存,不应该对此直接进行修改*/
public readonly RemoveCache: Array<T> = new Array<T>()
public GetLock(): boolean {
return this.lock
}
public SetLock(lock: boolean) {
this.lock = lock
if (!this.lock) {
// add
if (this.AddCache.length > 0) {
this.Members.push(...this.AddCache)
this.AddCache.length = 0
}
//remove
if (this.RemoveCache.length > 0) {
let removeLength = this.RemoveCache.length
for (let i = 0; i < removeLength; i++) {
let index = this.Members.indexOf(this.RemoveCache[i])
if (index >= 0) {
if (index < this.Members.length - 1) {
this.Members[index] = this.Members[this.Members.length - 1]
}
this.Members.pop()
}
}
}
}
}
public Add(item: T) {
if (this.lock) {
this.AddCache.push(item)
} else {
this.Members.push(item)
}
}
public Remove(item: T) {
if (this.lock) {
this.RemoveCache.push(item)
} else {
let index = this.Members.indexOf(item)
if (index >= 0) {
if (index < this.Members.length - 1) {
this.Members[index] = this.Members[this.Members.length - 1]
}
this.Members.pop()
}
}
}
}
4.无序列表+字典(加快查找和删除速度)
一方面希望数据能够方便遍历,也希望能够快速查找。不知道Map(map,dictionary)已经有了这个功能或者Map本身就遍历很快捷,又或者有没有其他的数据结构符合这个要求?我寻思着要不结合一下列表和字典两种数据结构,牺牲些内存空间来换取运行效率,可以先试试所以便有了下面的代码:
export interface IFastArrayItem {
Uid: number
}
/** 一个无序的数组,提供一种有利于插入删除查找遍历的结构。内存开销会增加*/
export class FastArray<T extends IFastArrayItem> {
/** Group成员,不应该对此直接进行修改*/
public readonly Members: Array<T> = new Array<T>()
/** Group成员索引map,不应该对此直接进行修改*/
private readonly MembersIndexMap: Map<number, number> = new Map<number, number>()
public Has(item: T): boolean {
return this.MembersIndexMap.has(item.Uid)
}
public Get(Uid: number): T | undefined {
let index = this.MembersIndexMap.get(Uid)
if (index == undefined) {
return undefined
} else {
return this.Members[index]
}
}
public Add(item: T) {
this.MembersIndexMap.set(item.Uid, this.Members.length)
this.Members.push(item)
}
public Remove(item: T) {
if (this.MembersIndexMap.has(item.Uid)) {
let index = this.MembersIndexMap.get(item.Uid) as number
if (index < this.Members.length - 1) {
this.Members[index] = this.Members[this.Members.length - 1]
}
this.Members.pop()
}
}
}
5.结尾(结束啦感谢观看)
(1)注意,仅供实践参考,在实际项目使用需谨慎。这种基础结构,写出错或者有效率问题,对开发影响很大。
(2)其中2和3都是我个人练手时使用的一个额外处理,合理性和效率性都有待大家一起讨论。
(3)代码中成员是暴露的,带来的问题是可能会在外面错误删除或更改,这并不符合基础理念,但为了提供遍历方便,因为目前我需求是加快速度,所以成员没有对外隐藏。可能做一些迭代器之类的可能会好一些,目前不是很了解。