python数据结构:以链表为底层原理重新实现字典dict
Posted 九死九歌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python数据结构:以链表为底层原理重新实现字典dict相关的知识,希望对你有一定的参考价值。
(PS:本人主要研究方向是java,python代码写的烂请见谅,大佬轻喷)
一、概述:
首先我们只知道,python中有几个已经实现好的数据结构,底层为链表linkList的列表list、底层为哈希表hashTable的集合set和字典dict。
这确实为我们在程序开发的过程中提供了不少的便利、但也存在一定的弊端。
以dict举个例子:
在java中有一种与dict相似的结构叫做Map,java中同一个容器可以用不同的底层来实现,Map也是如此,像下面这样:
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
public class Main {
public static void main(String[] args) {
Map<Integer, String> m1 = new HashMap<>();
Map<Integer, String> m2 = new TreeMap<>();
Map<Integer, String> m3 = new LinkedHashMap<>();
}
}
无论m1、m2还是m3,他们都可以像python中的dict那样实现键值对应,不一样的在于,pythondict的底层无论如何都只能是哈希表,但是在上面这个例子中,m1底层为哈希表、m2底层为树,m3底层为链表。
为了克服python的这一短处,我们可以尝试自己构建一个类,名为myDict,具有dict的大部分操作,插入删除值排序键排序等等。
由于myDict的底层是链表,所以它可以比dict更加高效的进行字典拼接,排序等操作,唯一一点不足就是·查找元素的效率比dict要底。
废话不多说,我们开始上代码:
二、代码实现
1.首先写好构造器、成员变量是两个链表,分别代表键和值,并且利用isinstance函数保证构造器函数只能传参None、myDict、dict和字符串
class myDict:
def __init__(self, dct=None):
self.__keys = []
self.__values = []
if dct is None:
return
elif isinstance(dct, myDict):
self.__keys = dct.keys()
self.__values = dct.values()
elif isinstance(dct, dict):
for k in dct.keys():
self.__keys.append(k)
for v in dct.values():
self.__values.append(v)
elif isinstance(dct, str):
if dct[0] != "{" or dct[len(dct) - 1] != "}":
raise TypeError
dct = dct[1:len(dct) - 1]
lst = dct.split(", ")
enties = [[], []]
for entry in lst:
ety = entry.split(":")
for i in range(2):
try:
enties[i].append(int(ety[i]))
continue
except ValueError:
pass
try:
enties[i].append(float(ety[i]))
continue
except ValueError:
pass
try:
enties[i].append(complex(ety[i]))
continue
except ValueError:
pass
if ety[i] == "True" or ety[i] == "False":
enties[i].append(ety[i] == "True")
continue
try:
enties[i].append(eval(ety[i]))
continue
except BaseException:
pass
if ety[i][0] != "'" or ety[i][len(ety[i])] != "'":
raise TypeError
enties[i].append(ety[i])
self.__keys = enties[0]
self.__values = enties[1]
self.__balance()
else:
raise TypeError
2.写两个成员函数用于返回键、值、项目列表。其作用相当于dict中的同名函数:
def keys(self):
return self.__keys
def values(self):
return self.__values
def items(self):
lst = []
for i in range(0, len(self)):
lst.append((self.__keys[i], self.__values[i]))
return lst
3.由于要保证键不可重复,所以我们要写一个私有函数进行去重:
def __balance(self):
newKeys = list(set(self.__keys))
newValues = []
for k in newKeys:
newValues.append(self.get(k))
self.__keys = newKeys
self.__values = newValues
4.编写最基础的增删改查四件套、以及排序切片操作:
def append(self, k, v):
if k not in self.__keys:
self.__keys.append(k)
self.__values.append(v)
else:
index = self.__keys.index(k)
self.__values[index] = v
def insert(self, k, v, index):
if k in self.__keys:
return
else:
self.__keys.insert(index, k)
self.__values.insert(index, v)
def extend(self, dct):
self.__keys.extend(dct.keys())
self.__values.extend(dct.values())
self.__balance()
def get(self, k):
if k not in self.__keys:
return None
return self.__values[self.__keys.index(k)]
def deleteByIndex(self, index):
self.__keys.pop(index)
self.__values.pop(index)
def deleteByKey(self, k):
if k not in self.__keys:
raise Exception
self.deleteByIndex(self.__keys.index(k))
def deleteByValue(self, v):
if v not in self.__values:
raise Exception
self.deleteByIndex(self.__values.index(v))
def sortedByKeys(self):
l = len(self.__keys)
for i in range(0, l):
for j in range(i + 1, l):
flag = True
if self.__keys[i] > self.__keys[j]:
flag = False
keyTmp = self.__keys[i]
self.__keys[i] = self.__keys[j]
self.__keys[j] = keyTmp
valueTmp = self.__values[i]
self.__values[i] = self.__values[j]
self.__values[j] = valueTmp
if flag:
break
def sortedByValues(self):
l = len(self.__values)
for i in range(0, l):
for j in range(i + 1, l):
flag = True
if self.__values[i] > self.__values[j]:
flag = False
keyTmp = self.__keys[i]
self.__keys[i] = self.__keys[j]
self.__keys[j] = keyTmp
valueTmp = self.__values[i]
self.__values[i] = self.__values[j]
self.__values[j] = valueTmp
if flag:
break
def slice(self, begin=0, end=None):
if end is None:
end = len(self)
self.__keys = self.__keys[begin:end]
self.__values = self.__values[begin:end]
5.最后一步了,编写特殊函数:
def __len__(self):
if len(self.__keys) != len(self.__values):
raise Exception
else:
return len(self.__keys)
def __str__(self):
lst = []
for i in range(len(self)):
s = ""
if isinstance(self.__keys[i], str):
s += "\\'" + self.__keys[i] + "\\'"
else:
s += str(self.__keys[i])
s += ":"
if isinstance(self.__values[i], str):
s += "\\'" + self.__values[i] + "\\'"
else:
s += str(self.__values[i])
lst.append(s)
return "{" + ", ".join(lst) + "}"
6.最后我们把这个文件命名为dict.py并在main.py中测试一番:
from dict import myDict
'''构造器函数可以为空,可以为一个字典,可以为字符串'''
d = myDict()
print(d)
d = myDict({1: True, 2: "hello", "shi": 10})
print(d)
d = myDict("{2:3.6, True:3+j, 'abc':'cba'}")
print(d)
print()
'''可以返回值列表,键列表,元素列表'''
print(d.keys())
print(d.values())
print(d.items())
print()
'''因为重写了__len__和__str__方法,所以可以直接用print输出,也可以使用len函数测量长度,又因为有参数为字符串的构造器,所以可以由用户输入获取字典'''
print("d的长度是", len(d), ", d的内容是", d)
try:
print(myDict(input()))
except:
print("输入有误!")
'''myDict不同于dict,其底层实现是链表,而不是哈希表,因此可以实现更高效的插入,删除,切片,排序等操作'''
'''这是链表相较于哈希表的优点,当然也是myDict相较于dict的优点'''
d = myDict({1: 3, 0: 9, 2: 7, 3: 5})
d.append(4, 6)
d.insert(4, 8, 3)
d.extend(myDict({2: 9, 3: 8}))
print(d)
d.append("abc", "bca")
d.sortedByKeys()
print(d)
d.sortedByValues()
print(d)
d.deleteByIndex(1)
d.deleteByValue(3)
d.deleteByKey(2)
print(d)
d.slice(2, 4)
print(d)
这样一个虽然有一(hao)些(duo)bug,但是基本上功(te)能(bie)完(la)善(ji)的链表式的字典就构建好了。
以上是关于python数据结构:以链表为底层原理重新实现字典dict的主要内容,如果未能解决你的问题,请参考以下文章