Python 线性表

来源:互联网 发布:javascript视教程下载 编辑:程序博客网 时间:2024/05/21 08:35

1.     顺序表

1.1将表中元素顺序地存放在一块连续的存储区域里,元素间的顺序关系由它们的存储顺序自然地表示

1.2 如果表的元素大小不统一,顺序表的存储方式:将实际数据元素另行存储,在顺序表各单元位置保存对相应元素的引用信息(链接)。

1.3 不修改表的结构的操作只有两种模式,直接访问(O(1))、基于一个整型变量,按下标循环检查和处理(O(n))

1.4 Python中list存储空间分配的实现策略:在建立空表时,系统分配一块能容纳8个元素的存储区,区满换一块4倍大的存储区,若表已经很大,则换存储区时容量加倍。

顺序表:

最重要的优势是O(1)时间的定位元素访问。很多简单操作的效率也比较高。

最重要的麻烦是加入/删除等操作的效率问题。这类操作改变表中元素序列的结构,是典型的变动操作。这是由于元素在顺序表的存储区里连续排列。

只有特殊的尾端插入/删除操作具有O(1)的时间复杂度。但插入操作复杂度还受到元素存储区固定大小的限制。通过适当的(加倍)存储区扩充策略,一系列尾端插入可以达到O(1)的平均复杂度。

顺序表的优点和缺点都在于元素存储的集中方式和连续性。如果程序里需要巨大的线性表,采用顺序表实现就需要巨大块的连续存储空间,这也可能造成存储管理方面的困难。

 

2.     链接表

优点:

表结构是通过链接起来的结点形成的,结点之间的顺序由链接关系决定,链接可以修改,表的结构很容易调整和修改。

不需要修改结点里的数据元素或移动它们,只通过修改结点之间的链接,就能灵活的修改表的结构和数据排列方式。

整个表由小的存储块组成,容易安排和管理。

缺点:
定位访问需要线性时间,这是相对顺序表相比的最大劣势。

简单单链表的尾端操作需要线性时间。

要找到当前元素的前一元素,必须从头开始扫描结点。这种操作应尽量避免。双链表可以解决这个问题,但每个结点要付出更高的存储代价。

为存储一个元素需要多用一个链接域。双链表需要增加两个链表域。

 

Python自定义单链表:

class LNode:

    def __init__(self, elem, next_=None):
        self.elem = elem
        self.next = next_


class LinkedListUnderflow(ValueError):
    pass


class LList:
    @staticmethod
    def is_duplicate(elem, current):
        if len(current) == 0:
            return False
        for e in current:
            if elem == e:
                return True

    def __init__(self, elem=[]):
        if len(elem) == 0:
            self._head = None
            self.num = 0
            return
        p = LNode(0)
        self._head = p
        for e in elem:
            p.next = LNode(e)
            p = p.next
        self._head = self._head.next
        self.num = len(elem)

    def is_empty(self):
        return self._head is None

    def __len__(self):
        return self.num

    def prepend(self, elem):  # 在表头插入数据
        self._head = LNode(elem, self._head)
        self.num += 1

    def pop(self):  # 删除表头节点并返回这个节点的数据
        if self._head is None:
            raise LinkedListUnderflow("inpop")
        e = self._head.elem
        self._head = self._head.next
        self.num -= 1
        return e

    def append(self, elem):   # 节点末尾附加
        self.num += 1
        if self._head is None:
            self._head = LNode(elem)
            return
        p = self._head
        while p.next is not None:
            p = p.next
        p.next = LNode(elem)

    def pop_last(self):    # 删除最后节点
        if self._head is None:
            raise LinkedListUnderflow("inpop_last")
        p = self._head
        self.num -= 1
        if p.next is None:
            e = p.elem
            self._head = None
            return e
        while p.next.next is not None:
            p = p.next
        e = p.next.elem
        p.next = None
        return e

    def elements(self):    # 生成器方法
        p = self._head
        while p is not None:
            yield p.elem
            p = p.next

    def __add__(self, other):   # 两链表相加
        if not isinstance(other, LList):
            raise LinkedListUnderflow("TypeError")
        else:
            if self._head is None:
                self._head = other._head
            else:
                p = self._head
                while p.next is not None:
                    p = p.next
                p.next = other._head
            self.num += other.num
            return self


    def insert(self, index, elem):    # 指定索引插入操作
        count = 0
        if index >= self.num or index< 0:
            raise IndexError
        p = LNode(elem)
        self.num += 1
        if index == 0:
            p.next = self._head
            self._head = p
        else:
            e = self._head
            while count < index - 1:
                count += 1
                e = e.next
            p.next = e.next
            e.next = p

    def __delitem__(self, key):     # 删除指定索引元素
        if key >= self.num or key <0:
            raise IndexError
        p = self._head
        if key == 0:
            self._head = p.next
        else:
            count = 0
            while count < key - 1:
                count += 1
                p = p.next
            if key == self.num - 1:
                p.next = None
            else:
                p.next = p.next.next
        self.num -= 1

    def del_minimal(self):  # 删除最小元素
        if self._head is None:
            raise LinkedListUnderflow
        p = self._head
        if p.next is None:
            self._head = None
        min_value = self._head.elem
        while p.next is not None:
            if p.elem < min_value:
                min_value = p.elem
            p = p.next
        self.del_elem(min_value)

    def del_elem(self, elem):   # 删除指定元素
        if self._head is None:
            return
        p = self._head
        if p.next is None:
            if p.elem == elem:
                self._head = None
                self.num -= 1
        while p.next is not None:
            if p.next.elem == elem:
                p.next = p.next.next
                self.num -= 1
            else:
                p = p.next
        if self._head.elem == elem:
            self._head = self._head.next
            self.num -= 1

    def del_if(self, pred):     # 删除满足pred谓词条件的元素
        if self._head is None:
            return
        p = self._head
        if p.next is None:
            if pred(p.elem):
                self._head = None
        while p.next is not None:
            if pred(p.next.elem):
                p.next = p.next.next
                self.num -=1
            else:
                p = p.next
        if pred(self._head.elem):
            self._head = self._head.next
            self.num -= 1

    def del_duplicate(self):    # 删除重复的元素
        if self._head is None or self._head.nextis None:
            return
        p = self._head
        current = [p.elem]
        while p.next is not None:
            if LList.is_duplicate(p.next.elem,current):
                p.next = p.next.next
                self.num -= 1
            else:
               current.append(p.next.elem)
                p = p.next

    def interleaving(self, another):    # 交错变动
        if not isinstance(another, LList):
            raise LinkedListUnderflow
        self.num += another.num
        if self._head is None:
            self._head = another._head
            return
        if another._head is None:
            return
        p = self._head
        e = another._head
        result = LList()
        result._head = LNode(p.elem)
        q = result._head
        q.next = LNode(e.elem)
        q = q.next
        while p.next is not None or e.nextis not None:
            if p.next is not None:
                q.next =LNode(p.next.elem)
                q = q.next
                p = p.next
            if e.next is not None:
                q.next =LNode(e.next.elem)
                q = q.next
                e = e.next
        self._head = result._head


class LCList:   # 循环单链表类
    def __init__(self, elem=[]):
        self._rear = None
        for e in elem:
            self.append(e)

    def is_empty(self):
        return self._rear is None

    def prepend(self, elem):    # 前端插入
        p = LNode(elem)
        if self._rear is None:
            p.next = p
            self._rear = p
        else:
            p.next = self._rear.next
            self._rear.next = p

    def append(self, elem):     # 尾端插入
        self.prepend(elem)
        self._rear = self._rear.next

    def pop(self):  # 前端弹出
        if self._rear is None:
            raise LinkedListUnderflow("inpop of CLList")
        p = self._rear.next
        if self.rear is p:
            self._rear = None
        else:
            self._rear.next = p.next
        return p.elem

原创粉丝点击