-
稀疏数组
稀疏数组应用场景:
当数组size很大而空间利用率很低时,应使用稀疏数组来存储
下面的实现的稀疏数组0行0列都没用来存储数据,留做存储row_size等其他数据用,一个稀疏数组由多个行链表组成,一个行链表由多个节点构成
Python 实现如下:
# 节点类
class ArrayEntry:
def __init__(self, columnNumber=0, nextEntry=None, entry=0):
# 所处的列数
self.columnNumber = columnNumber
# 下一个节点
self.nextEntry = nextEntry
# 数据域
self.entry = entry
# 行链表类
class ArrayRow:
def __init__(self, rowNumber=0, rowSentinel=ArrayEntry(), nextRow=None):
# 稀疏数组所处的行
self.rowNumber = rowNumber
# 下一行
self.nextRow = nextRow
# 当前行的哨兵、头指针
self.rowSentinel = rowSentinel
self.columnSize = 0
# 稀疏数组类
class SparseArray:
def __init__(self, sentinel=ArrayRow(), rowSize=0, columnSize=0):
# sentinel row的头指针
self.sentinel = sentinel
# 稀疏数组的行
self.rowSize = rowSize
# 稀疏数组的列
self.columnSize = columnSize
定义操作:
- 寻找前一行
# 寻找rowNum前一行,返回rowNum前一行
def findRowBefore(self, rowNum) -> ArrayRow:
array_row = self.sentinel
while array_row.nextRow and array_row.nextRow.rowNumber < rowNum:
array_row = array_row.nextRow
return array_row
2.寻找某一行某个节点的前驱节点
# 寻找row的columnNum列的前一列
def findColumnBefore(self, row, columnNum) -> ArrayEntry or str:
if row is None:
return "row 不能为空"
row_sentinel = row.rowSentinel
while row_sentinel.nextEntry and row_sentinel.nextEntry.columnNumber < columnNum:
row_sentinel = row_sentinel.nextEntry
return row_sentinel
3.获取值
# 获取(rowNum,columnNum)值
def getEntry(self, rowNum, columnNum) -> int or str:
row = self.findRowBefore(rowNum)
if row.nextRow is None or row.nextRow.rowNumber > rowNum:
return "没找到行" + str(rowNum)
row_sentinel = self.findColumnBefore(row, columnNum)
if row_sentinel.nextEntry is None or row_sentinel.nextEntry.columnNumber > columnNum:
return "没找到列" + str(columnNum)
return row_sentinel.nextEntry.entry
4.设置值
# 设置entry,若未找到行,则新建行,未找到列则,新建列
def setEntry(self, rowNum, columnNum, entry) -> bool:
# 找到行
row = self.findRowBefore(rowNum)
if row.nextRow is None or row.nextRow.rowNumber > rowNum:
new_row = ArrayRow(row.rowNumber + 1)
new_row.nextRow = row.nextRow
row.nextRow = new_row
row = row.nextRow
# 找到列
row_sentinel = self.findColumnBefore(row, columnNum)
if type(row_sentinel) == str:
return False
elif row_sentinel.nextEntry is None or row_sentinel.nextEntry.columnNumber > columnNum:
new_column = ArrayEntry(columnNumber=row_sentinel.columnNumber + 1, entry=entry)
new_column.nextEntry = row_sentinel.nextEntry
row_sentinel.nextEntry = new_column
else:
row_sentinel.nextEntry.entry = entry
return True
5.删除节点
def deleteEntry(self, rowNum, columnNum):
# 找到行
row = self.findRowBefore(rowNum)
if row.nextRow is None or row.nextRow.rowNumber > rowNum:
return False
# 找到列
row_sentinel = self.findColumnBefore(row.nextRow, columnNum)
if type(row_sentinel) == str:
return False
elif row_sentinel.nextEntry is None or row_sentinel.nextEntry.columnNumber > columnNum:
return False
else:
delete = row_sentinel.nextEntry
after_delete = row_sentinel.nextEntry.nextEntry
row_sentinel.nextEntry = after_delete
# 如果 列被删除后,该行已没有列,删除该行
if after_delete is None and row_sentinel.columnNumber == 0:
row.nextRow = None
del delete
gc.collect()
return True
6.矩阵加法
稀疏矩阵加法(伪代码):
遍历两个矩阵行,
while arr1 and arr2:
if arr1.rowNum>arr2.rowNum : add arr2 to result,arr2=arr2.nextRow
elif arr1.rowNum<arr2.rowNum : add arr1 to result,arr1 = arr1.nextRow
else add arr1[rowNum] + arr2[rowNum] to result,arr1 = arr1.nextRow,arr2=arr2.nextRow
add arr1 remaining to result
add arr2 remaining to result
7.矩阵乘法
稀疏矩阵乘法:
对与矩阵arr1*arr2,由与 要遍历arr2的每一列,而列不能迭代,
我们可以将arr2转置,转制后的矩阵arr2的一行就是转置之前的一列,
若entry默认值为零,类似加法,乘法可计算如下:
遍历arr1,与arr2的转置,
若对于arr1.rowNum != arr2转置.rowNum,点(arr1.rowNum,arr2转置.rowNum)为0
若对于arr1.rowNum == arr2转置.rowNum,则点(arr1.rowNum,arr2转置.rowNum)为对应项乘积之和
-
三角矩阵
应用场景:面对size庞大的数组,且当数组具有很好的对称性时,可以使用三角矩阵,如无向图的邻接矩阵等。
特点:一维矩阵表示二维矩阵,[i,j] === ((i-1)**2+i-1)/2 +j(数组下表从1开始),[i,j] === (i**2+i)/2 +j(数组下表从0开始)
Python实现:
import time
from pymysql import Date
"""
应用场景:数组对称
"""
class TriangleArray:
def __init__(self):
self.data = []
self.size = 0
def get(self, row, column):
index = int((row ** 2 + row) / 2 + column)
if index <= self.size - 1:
return self.data[index]
else:
return None
def append_(self, value):
self.data.append(value)
self.size += 1
def set(self, row, column, value):
index = int((row ** 2 + row) / 2 + column)
if index <= self.size - 1:
self.data[index] = value
return True
else:
return False
if __name__ == "__main__":
tri = TriangleArray()
tri.append_(1)
tri.append_("rlyslata")
tri.append_("CSDN")
tri.append_("新肺炎冠状病毒")
tri.append_(str(time.localtime()))
print(tri.get(0, 0))
print(tri.get(1, 0))
print(tri.get(1, 1))
print(tri.get(2, 0))
print(tri.get(2, 1))
PS:代码clone地址:git@github.com:Rlyslata/DataStauct-And-Algorithm.git
路径:关于链表的算法/SparseArray 关于链表的算法/TriangleArray