[数据结构]无序列表快速增删查改和延迟删除

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)代码中成员是暴露的,带来的问题是可能会在外面错误删除或更改,这并不符合基础理念,但为了提供遍历方便,因为目前我需求是加快速度,所以成员没有对外隐藏。可能做一些迭代器之类的可能会好一些,目前不是很了解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值