1. 数据结构与算法python描述:数组和链表

**

从我自己博客粘贴过来的,这里没图

**
原文地址:https://kongping.net/blog/post/2788/
线性结构
1. 内存连续

2. 下标访问,时间复杂度为O(1)

链式结构
1. 内存不连续,更灵活

线性结构和链式结构比较
空间上:线性表连续,链式结构不连续,灵活度大,但是更消耗资源(因为每一个节点都需要保存节点指针)

时间上:

结构 增
删 查
线性表 O(n) O(n) O(1)
链表 O(1) O(n) O(n)

抽象数据类型ADT
Abstract Data Type:包括数据和方法(操作数据)

用python实现一个Array数组
‘’’
定义一个数组类型
data:
size: 数组最大的长度
_items: 保存数据的容器
method:
add: 增加数据
remove: 删除数组中某一个数
clear: 清空数组
‘’’

class Array(object):

def __init__(self, maxsize=32):
    self.maxsize = maxsize  # 数组的最大长度
    self._items = [None] * maxsize

def __len__(self):
    return len(self._items)

def __getitem__(self, index):
    return self._items[index]

def __setitem__(self, index, value):
    self._items[index] = value

def remove(self, value):
    index = None  # 记录被删元素的下标
    for i in range(len(self)):
        if self._items[i] == value:
            index = i

        if index is not None and i < len(self) - 1:
            self._items[i] = self._items[i+1]

def clear(self):
    for i in range(len(self)):
        self._items[i] = None

def __iter__(self):
    for item in self._items:
        yield item

def test_array():
arr = Array(8)

arr[0] = 1
arr[1] = 2
arr[2] = 3
assert len(arr) == 8
assert arr[0] == 1

arr.clear()
assert arr[0] is None
# assert 0  # 判断以上代码是不是真的执行了

if name == ‘main’:
test_array()
用pytest 执行效果如下:

说明:由于删除数组元素需要维护顺序结构,所以删除的时间复杂度为O(n)

单链表

抽象数据类型:

‘’’
单链表的实现

Data: Node 节点  # 数据由节点组成
    maxsize: 链表的最大长度
    root: 根节点
    tailnode: 尾节点
    length: 链表的长度

method:
    init: 初始化链表
    append: 增加节点
    appendleft: 在链表左侧增加节点
    remove: 删除节点
    popleft: 从左侧删除节点
    clear: 清空链表
    find: 查找元素,返回是第几个元素

‘’’

class Node(object):
def init(self, value=None, next=None):
self.value = value
self.next = next

class LinkedList(object):
def init(self, maxsize=None):
‘’‘初始化链表,如果不指定maxsize则可以无限存储’’’
self.maxsize = maxsize
node = Node()
self.root = node
self.tailnode = None # 保存尾节点
self.length = 0 # 链表的长度

def __len__(self):
    return self.length

def append(self, value):
    if self.maxsize is not None and len(self) > self.maxsize:
        raise Exception('LinkedList is full')

    node = Node(value=value)
    if self.tailnode is None:  # 如果链表为空链表
        self.tailnode = node
        self.root.next = node
    else:
        self.tailnode.next = node
        self.tailnode = node

    self.length += 1

def appendleft(self, value):
    if self.maxsize is not None and len(self) > self.maxsize:
        raise Exception('LinkedList is full')

    node = Node(value=value)
    headnode = self.root.next  # 获取头结点
    if headnode is not None:
        node.next = headnode
        self.root.next = node
    # 如果头结点为空,说明是空链表
    else:
        self.root.next = node
        self.tailnode = node

    self.length += 1

def iter_node(self):
    '''遍历节点'''
    curnode = self.root.next  # 第一个节点为当前节点

    while curnode is not self.tailnode:  # 如果不是尾节点则一直向后遍历
        yield curnode
        curnode = curnode.next

    yield curnode  # 再返回尾节点

def remove(self, value):
    '''删除节点'''
    prenode = self.root  # 记录当前节点的前一个节点
    curnode = self.root.next  # 当前节点

    while curnode.next is not None:
        if curnode.next is None:  # 如果是最后一个节点被删除,需要把尾节点往前指
            self.tailnode = prenode

        if curnode.value == value:  # 遍历到了该节点
            prenode.next = curnode.next
            del curnode
            self.length -= 1
            return

        # 否则继续遍历
        prenode = curnode
        curnode =curnode.next

def popleft(self):
    '''删除头结点'''
    headnode = self.root.next

    if headnode is None:  # 如果头结点为空说明链表为空
        raise Exception('pop in empty linkedlist')

    self.root.next = headnode.next
    del headnode
    self.length -= 1
    return headnode.value

def clear(self):
    for node in self.iter_node():  # 遍历删除节点
        del node

    self.tailnode = None
    self.root.next = None
    self.length = 0

def __iter__(self):
    for node in self.iter_node():
        if node is not None:
            yield node.value

def find(self, value):
    index = 0
    for node in self.iter_node():
        if node.value == value:
            return index

        index += 1
    return -1

def test_linked_list():
ll = LinkedList()

ll.append(1)
ll.append(2)
ll.append(3)
assert list(ll) == [1, 2, 3]

ll.appendleft(-1)
assert list(ll) == [-1, 1, 2, 3]

ll.remove(2)
assert list(ll) == [-1, 1, 3]

v = ll.popleft()
assert v == -1

assert ll.find(1) == 0

ll.clear()
assert list(ll) == []

说明:由于每次查找,删除都需要遍历,所以单链表的删除和查找的时间复杂度都为O(1)

     而且只能单向遍历,所以引入的双向链表

循环双端链表

循环双端链表:

每一个节点包含三个域,从上到下分别指向前一个节点,节点的值,指向下一个节点,而根节点的前一个节点为尾节点,尾节点的下一个节点为根节点,构成闭环。

抽象数据类型 :

‘’’
循环双端链表

‘’’

class Node(object):
‘’‘定义节点类型’’’
def init(self, prev=None, value=None, next=None):
self.prev, self.value, self.next = prev, value, next

class CircleDoubleLinkedList(object):
def init(self, maxsize=None):
self.maxsize = maxsize
self.length = 0
node = Node()
self.root = node
self.root.prev, self.root.next = node, node # 根节点指向自己,形成闭环

def __len__(self):
    return self.length

def tailnode(self):
    return self.root.prev  # 根节点的前一个节点

def headnode(self):
    return self.root.next  # 根节点的后一个节点

def append(self, value):
    if self.maxsize is not None and len(self) >= self.maxsize:
        raise Exception('链表满了')

    node = Node(value=value)
    node.prev = self.tailnode()
    self.tailnode().next = node
    self.root.prev = node
    node.next = self.root

    self.length += 1

def appendleft(self, value):
    if self.maxsize is not None and len(self) >= self.maxsize:
        raise Exception('链表满了')

    node = Node(value=value)
    headnode = self.headnode()
    headnode.prev = node
    node.next = headnode
    self.root.next = node
    node.prev = self.root

    self.length += 1

def remove(self, node):  # 传入节点  O(1)
    prevnode = node.prev
    nextnode = node.next

    prevnode.next = node.next
    nextnode.prev = node.prev

    del node
    self.length -= 1

def iter_node(self):
    curnode = self.headnode()

    while curnode is not self.root:
        yield curnode
        curnode = curnode.next

def __iter__(self):
    for node in self.iter_node():
        yield node.value

def iter_node_reverse(self):
    curnode = self.tailnode()

    while curnode.prev is not self.root:
        yield curnode

def test_circle_double_linked_list():
cdll = CircleDoubleLinkedList()
cdll.append(1)
cdll.append(2)
cdll.append(3)
cdll.append(4)

assert list(cdll) == [1, 2, 3, 4]

cdll.appendleft(0)
assert  list(cdll) == [0, 1, 2, 3, 4]

代码:https://github.com/yiouejv/python_data_stract_algorithm/tree/master/linklist

猜你喜欢

转载自blog.csdn.net/qq767852841/article/details/95640204