Python-数据结构与算法

1.数组列表

内存连续 下标访问

  • 列表为线性结构 内存是连续的,通过下标访问
  • 链表是链式结构,内存不是连续的,需要用指针节点访问其地址

method:

  1. class Array(object)
    构造一个空列表

  2. init(self,size=32)
    初始化列表变量

  3. getitem(self,index)
    获取列表值的下标

  4. setitem(self,index,value)
    构造列表元素
    获取列表下标值与值对应

  5. len(self)
    获取列表的长度

  6. clear(self,value = None)
    清空列表,将None值赋予每一个列表的值

  7. iter(self)
    遍历列表返回列表值zzz

实例代码块

#在一个函数中,程序执行到yield语句的时候,
# 程序暂停,返回yield后面表达式的值,在下一次调用的时候,
# 从yield语句暂停的地方继续执行,如此循环,直到函数执行完

# -*- coding:utf-8 -*-

#数组 列表  的数据结构

class Array(object):
    def __init__(self,size=32):
        self._size = size
        #初始化一个_items列表,长度为size,列表值全部为None
        self._items = [None] * size

    def __getitem__(self,index):
        #获取列表值的下标
        return self._items[index]

    #处理列表值的方法
    def __setitem__(self,index,value):
        #数组列表下标值与值对应
        self._items[index] = value

    def __len__(self):
        #len方法返回数组的长度值
        return self._size

    #clear方法用于清除数组,默认形参value为None
    def clear(self,value = None):
        #遍历数组将所有值都赋予None
        for i in range(len(self._items)):
            self._items[i] = value

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

#单测
def test_array():
    size = 30
    a = Array(size)
    a[0] = 1
    #assert单测 a[0]是否为1   如果结果非真则引发一个错误
    assert a[0] == 1

    a.clear()
    assert a[0] is None

2.单链表

初始化链表root(根节点)->Tail(尾节点)
if root.next is None(则该链表为空)

if root.next is not None:
    (入口)root->Head->节点1->节点2->...->Tail

节点Node-->value/next (数据域/指针域)


单链表 -->
            1.data -->
                    1.root节点
                    2.length长度

            2.method -->
                    1. class Node(object)
                                    构造节点的模块

                    2. class LinkedList(object)
                                    构造链表的模块

                    3. __init__(self,maxsize=None)
                                    初始化变量的函数

                    4. __len__(self)
                                    返回链表长度函数

                    5. append(self,value)
                                    在链表尾部添加新节点

                    6. appendleft(self,value)
                                    在链表头部添加新节点

                    7. iter_node(self)
                                    遍历链表节点方法

                    8. __iter__(self)
                                    遍历链表节点值方法

                    9. remove(self,value)
                                    删除节点函数

                    10. find(self,value)
                                    查找节点函数

                    11. popleft(self)
                                    从链表头部删除节点

                    12. clear(self)
                                    清空链表方法

实例代码块

# -*- coding:utf-8 -*-

#初始化一个节点 模块
class Node(object):
    def __init__(self,value=None,next=None):
        self.value,self.next = value,next

#创建链表 模块
class LinkedList(object):
    #初始化maxsize=None 将此链表最大容量默认为无穷大
    def __init__(self,maxsize=None):
        self.maxsize = maxsize
        #初始化一个根节点
        self.root = Node()
        #初始化链表长度为0
        self.length = 0
        #初始化尾节点为None
        self.tailnode = None

    #定义函数返回链表长度
    def __len__(self):
        return self.length

    """
        value为形参,函数实现在链表末尾插入一个节点,
        (如果tailnode为None)root->node(插入node)
        (如果tailnode不为None)root->tailnode->node(插入node)
    """
    def append(self,value):
        if self.maxsize is not None and len(self) > self.maxsize:
            #抛出异常
            raise Exception('Full')
        #构造一个新的节点
        node = Node(value)
        #取值tailnode
        tailnode = self.tailnode
        if tailnode is None:
            self.root.next = node
        else:
            tailnode.next = node
        #更新tailnode,将插入的node标记为最后一个节点
        self.tailnode = node
        self.length += 1

    """
        在链表头部插入节点:
                root->node(插入的新节点)->headnode
                root->next = node
                node->next = headnode
    """
    def appendleft(self,value):
        headnode = self.root.next
        node = Node(value)
        self.root.next = node
        node.next = headnode
        self.length += 1

    """
        遍历首节点到尾节点:
                    当curnode.next = tailnode时跳出循环,
                    此时yield curnode就是单独返回尾节点
    """
    def iter_node(self):
        curnode = self.root.next
        while curnode is not self.tailnode:
            yield curnode
            curnode = curnode.next
        yield curnode

    #遍历链表节点值
    def __iter__(self):
        for node in self.iter_node():
            yield node.value

    """
        删除节点操作:
            原理:找到要删除的节点,将其前面一个节点的下一个节点指向删除节点的下一个节点
            prevnode.next = node(预备删除节点).next
            操作:
                定义curnode为根节点下一个节点
                遍历链表查找指定要删除的节点,找到后
                将其前一个节点的指针指向其后一个节点的地址
    """
    def remove(self,value):     #O(n)
        prevnode = self.root
        curnode = self.root.next
        while curnode.next is not None:
            if curnode.value == value:
                prevnode.next = curnode.next
                del curnode
                self.length -= 1
                return

    """
        查找节点操作:
                定义一个变量初始化为0,遍历链表
                找到指定节点后返回变量值,表明这是第几个节点
                如果未找到则返回-1         
    """
    def find(self,value):   #O(n)
        index = 0
        for node in self.iter_node():
            if node.value == value:
                return index
            index += 1
        return -1


    """
        从链表头部删除节点:
                    root->节点1->节点2->...->尾节点
                    1.headnode = root.next
                    2.root.next = headnode.next
                    3.获取headnode的值
                    4.del headnode
    """
    def popleft(self):      #O(n)
        if self.root.next is None:
            raise Exception('pop from empty LinkedList')
        headnode = self.root.next
        self.root.next = headnode.next
        self.length -= 1
        #获取头节点的值
        value = headnode.value
        del headnode
        return value

    #清空链表:遍历链表将其所有节点赋值为None,将其长度赋值为0
    def clear(self):
        for node in self.iter_node():
            del node
        self.root.next = None
        self.length = 0


#单测
def test_linked_list():
    #创建一个链表的实例ll
    ll = LinkedList()

    ll.append(0)
    ll.append(1)
    ll.append(2)

    #断言 判断assert后面的表达式是否相等,相等则返回真,否则返回错误信息
    assert len(ll) == 3
    assert ll.find(2) == 2
    assert ll.find(3) == -1

    ll.remove(0)
    assert len(ll) == 2
    assert ll.find(0) == -1

    assert list(ll) == [1,2]

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

    headvalue = ll.popleft()
    assert headvalue == 0
    assert len(ll) == 2
    assert list(ll) == [1,2]

    ll.clear()
    assert len(ll) == 0

3.双端链表

root/prev/next -> Head/prev/next -> node2/prev/next -> node3/prev/next -> Tail/prev/next

循环遍历:
root.prev = Tail.next

data域:

    root
    maxsize
    length

指针域:

    prev
    next

method:

    1.class Node(object) 
                    构造节点的模块

    2.class CircualDoubleLinedList(object)
                    构造链表的模块

    3. __init__(self,maxsize=None)
                    初始化变量的函数

    4. __len__(self)
                    返回链表长度的函数

    5. headnode(self)
                    构造一个headnode

    6. tailnode(self)
                    构造一个tailnode

    7. append(self,value)
                    在链表尾部插入新节点

    8. appendleft(self,value)
                    在链表头部插入新节点

    9. remove(self,node)
                    删除节点函数

    10. iter_node(self)
                    遍历链表节点函数

    11. __iter__(self)
                    遍历链表节点值函数

    12. iter_node_reverse(self)
                    反向遍历链表节点值函数

实例代码块



# -*- coding:utf-8 -*-

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

"""
    初始化构造一个node,将其前后指针都指向自己,
    形成闭环,再将其赋值给root
"""
class CircualDoubleLinedList(object):
    def __init__(self,maxsize=None):
        self.maxsize = maxsize
        node = Node()
        node.next,node.prev = node,node
        self.root = node
        self.length = 0

    def __len__(self):
        return self.length

    #构造headnode函数
    def headnode(self):
        return self.root.next

    #构造tailnode函数
    def tailnode(self):
        return self.root.prev

    """
        root->node1->node2->tailnode    新增node
    """
    def append(self,value):
        if self.maxsize is not None and len(self) > self.maxsize:
            raise Exception('FULL')
        node = Node(value=value)
        tailnode = self.tailnode()

        tailnode.next = node
        node.prev = tailnode
        node.next = self.root
        self.root.prev = node

        self.length += 1

    """
        从头部插入节点:
                需要对空链表的情况做出判断
    """
    def appendleft(self,value):
        if self.maxsize is not None and len(self) > self.maxsize:
            raise Exception('full')

        node = Node(value=value)

        if self.root.next is self.root:     #empty
            node.next = self.root
            node.prev = self.root
            self.root.next = node
            self.root.prev = node
        else:
            node.prev = self.root
            headnode = self.root.next
            node.next = headnode
            headnode.prev = node
            self.root.next = node

        self.length += 1

    """
        删除节点:
            需要对空链表情况进行分析
            1.将指定删除的节点node的前一个节点指向node->next
            2.将指定删除的节点node的后一个节点指向node->prev
    """
    def remove(self,node):
        if node is self.root:
            return
        else:
            node.prev.next = node.next
            node.next.prev = node.prev
        self.length -= 1
        return node

    """
        遍历链表:
            需要对链表为空的情况做分析
    """
    def iter_node(self):
        if self.root.next is self.root:
            return
        curnode = self.root.next
        while curnode.next is not self.root:
            yield curnode
            curnode = curnode.next
        yield curnode

    """
        for循环遍历链表的值
    """
    def __iter__(self):
        for node in self.iter_node():
            yield node.value

    """
        反向遍历链表
    """
    def iter_node_reverse(self):
        if self.root.prev is self.root:
            return 
        curnode = self.root.prev
        while curnode.prev is not self.root:
            yield curnode
            curnode = curnode.prev
        yield curnode

#单测
def test_double_link_list():
    dll = CircualDoubleLinedList()
    assert len(dll) == 0

    dll.append(0)
    dll.append(1)
    dll.append(2)

    assert list(dll) == [0,1,2]

    assert [node.value for node in dll.iter_node()] == [0,1,2]
    assert [node.value for node in dll.iter_node_reverse()] == [2,1,0]

    headnode = dll.headnode()
    assert headnode.value == 0
    dll.remove(headnode)
    assert len(dll) == 2
    assert [node.value for node in dll.iter_node()] == [1,2]

    dll.appendleft(0)
    assert [node.value for node in dll.iter_node()] == [0,1,2]





4.队列

队列特点:
1.先进先出,后入后出

        -----------------------------------
    --->   5     4       3       2       1  --->     FIFO 结构
        -----------------------------------

数组实现队列原理

    ---->数组实现队列原理:<----

        0->10依次放入列表,
        新添加一个元素,head指针+1
        tail指针指向列表第一个元素,每执行出列操作tail值+1,指向第二个元素...
                head   head   head  head     head   head  ...
                ------------------------------------------------

                0      1      2      3       4      5      6   
                ------------------------------------------------
                tail  tail   tail   tail    tail    tail  ...

实例代码块

# -*- coding:utf-8 -*-

class Array(object):
    def __init__(self,size=32):
        self._size = size
        self._items = [None] * size

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

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

    def __len__(self):
        return self._size

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

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


#################################################
    # 下面是  Queue  实现   数组实现队列
#################################################

class FullError(Exception):
    pass

class ArrayQueue(object):
    def __init__(self,maxsize):
        self.maxsize = maxsize
        self.array = Array(maxsize)
        self.head = 0
        self.tail = 0
    def push(self,value):
        if len(self) >= self.maxsize:
            raise FullError('queue full')
        self.array[self.head % self.maxsize] = value
        self.head += 1

    def pop(self):
        value = self.array[self.tail % self.maxsize]
        self.tail += 1
        return value

    def __len__(self):
        return self.head - self.tail

def test_array_queue():
    import pytest
    size = 5
    q = ArrayQueue(size)
    for i in range(size):
        q.push(i)

    with pytest.raises(FullError) as excinfo:
        q.push(size)
    assert 'full' in str(excinfo.value)

    assert len(q) == size

    assert q.pop() == 0
    assert q.pop() == 1

    q.push(5)
    assert len(q) == 4

    assert q.pop() == 2
    assert q.pop() == 3
    assert q.pop() == 4
    assert q.pop() == 5

    assert len(q) == 0










单链表实现队列原理

从0->5依次插入链表,调用append函数从链表尾部插入
                                    append(value)
    --------------------------------------
        0     1     2     3    4     5
    --------------------------------------
    popleft()                         

先入:append
先出:popleft

代码实例块

# -*- coding:utf-8 -*-

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

class LinkedList(object):
    def __init__(self,maxsize=None):
        self.maxsize = maxsize
        self.root = Node()
        self.length = 0
        self.tailnode = None

    def __len__(self):
        return self.length

    def append(self,value):
        if self.maxsize is not None and len(self) > self.maxsize:
            raise Exception('Full')
        node = Node(value)
        tailnode = self.tailnode
        if tailnode is None:
            self.root.next = node
        else:
            tailnode.next = node
        self.tailnode = node
        self.length += 1

    def appendleft(self,value):
        headnode = self.root.next
        node = Node(value)
        self.root.next = node
        node.next = headnode
        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 __iter__(self):
        for node in self.iter_node():
            yield node.value

    def remove(self,value):     #O(n)
        prevnode = self.root
        curnode = self.root.next
        while curnode.next is not None:
            if curnode.value == value:
                prevnode.next = curnode.next
                del curnode
                self.length -= 1
                return

    def find(self,value):   #O(n)
        index = 0
        for node in self.iter_node():
            if node.value == value:
                return index
            index += 1
        return -1

    def popleft(self):      #O(n)
        if self.root.next is None:
            raise Exception('pop from empty LinkedList')
        headnode = self.root.next
        self.root.next = headnode.next
        self.length -= 1
        value = headnode.value
        del headnode
        return value

    def clear(self):
        for node in self.iter_node():
            del node
        self.root.next = None
        self.length = 0

#################################################
    # 下面是  Queue  实现   单链表实现队列
#################################################
class FullError(Exception):
    pass

class EmptyError(Exception):
    pass

class Queue(object):
    def __init__(self,maxsize=None):
        self.maxsize = maxsize
        self._item_linked_list = LinkedList()

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

    def push(self,value):
        if self.maxsize is not None and len(self) >= self.maxsize:
            raise FullError('Queue full')
        return self._item_linked_list.append(value)

    def pop(self):
        if len(self) <= 0:
            raise EmptyError('Queue empty')
        return self._item_linked_list.popleft()

def test_queue():
    q = Queue()
    q.push(0)
    q.push(1)
    q.push(2)

    assert len(q) == 3

    assert q.pop() == 0
    assert q.pop() == 1
    assert q.pop() == 2

    assert len(q) == 0

    import pytest
    with pytest.raises(EmptyError) as excinfo:
        q.pop()     #raise EmptyError
    assert 'empty' in str(excinfo.value)














未完待续…

猜你喜欢

转载自blog.csdn.net/qq_39469688/article/details/81359661