数据结构与算法

数据结构是以某种形式将数据组织在一起的集合,它不仅存储数据,还支持访问和处理数据的操作。

数据的逻辑结构

1.线性结构:数据元素之间存在一个对一个的关系。

2.树形结构:结构中的数据元素存在一个对多个的关系。

3.图形结构或网状结构:结构中的数据元素存在多个对多个的关系。

4.集合结构:结构中的数据元素之间除了同属于一个集合关系外,无其他数据关系。

 

数据类型,是一个值的集合和定义在此集合上的一组操作的总称。

抽象数据类型,是指一个数学模型以及定义在此数据模型上的一组操作。

 

算法是为求解一个问题需要遵循的、被清楚指定的简单指令的集合。

一个算法必须满足五个重要特性:有穷性、确定性、可行性、有输入、有输出。

设计算法要求:正确性、可读性、健壮性、效率与低存储量需求

 

时间复杂度与大O记法

“大O记法”:对于单调的整数函数f,如果存在一个整数函数g和实常数c>0,使得对于充分大的n总有f(n)<=c*g(n),就说函数g是f的一个渐近函数(忽略常数),记为f(n)=O(g(n))。也就是说,在趋向无穷的极限意义下,函数f的增长速度受到函数g的约束,亦即函数f与函数g的特征相似。

时间复杂度:假设存在函数g,使得算法A处理规模为n的问题示例所用时间为T(n)=O(g(n)),则称O(g(n))为算法A的渐近时间复杂度,简称时间复杂度,记为T(n)

时间复杂度的几条基本计算规则

  1. 基本操作,即只有常数项,认为其时间复杂度为O(1)
  2. 顺序结构,时间复杂度按加法进行计算
  3. 循环结构,时间复杂度按乘法进行计算
  4. 分支结构,时间复杂度取最大值
  5. 判断一个算法的效率时,往往只需要关注操作数量的最高次项,其它次要项和常数项可以忽略
  6. 在没有特殊说明时,我们所分析的算法的时间复杂度都是指最坏时间复杂度

常见时间复杂度之间的关系

O(1) < O(logn) < O(n) < O(nlogn) < O(n2) <O(n2logn) < O(n3) < O(2n) < O(n!) < O(nn)

 Python list操作

python dict操作

 

python中的list与tuple两种类型采用的顺序表实现技术。list就是采用分离式技术实现的动态顺序表,若将数据区更换为更大的存储空间,则可以不在改变表对象的前提下对其数据区进行扩充,所有使用这个表的地方都不必修改 只要在程序的运行环境(计算机系统)还有空间存储,这种表结构就不会因为满了而导致操作无法进行 这种技术实现的顺序表称为动态顺序表

 在Python的官方实现中,list实现采用了如下的策略:在建立空表(或者很小的表)时,系统分配一块能容纳8个元素的存储区;在执行插入操作(insert或append)时,如果元素存储区满就换一块4倍大的存储区。但如果此时的表已经很大(目前的阀值为50000),则改变策略,采用加一倍的方法。引入这种改变策略的方式,是为了避免出现过多空闲的存储位置。

 链表(linked list)是由一组被称为结点的数据元素组成的数据结构,每个结点都包含结点本身的信息和指向下一个结点的地址。由于每个结点都包含了可以链接起来的地址信息,所以用一个变量就能够访问整个结点序列。也就是说,结点包含两部分信息:一部分用于存储数据元素的值,称为信息域;另一部分用于存储下一个数据元素地址的指针,称为指针域。链表中的第一个结点的地址存储在一个单独的结点中,称为头结点或首结点。链表中的最后一个结点没有后继元素,其指针域为空

 

单链表的实现

class Node(object):
    """节点"""
    def __init__(self,elem):
        self.elem =elem
        self.next = None


class SingleLinkList(object):
    """单链表"""

    def __init__(self,node=None):
        self._head = node

    def is_empty(self):
        """判断是否为空"""
        return self._head == None

    def length(self):
        """长度"""
        cur = self._head
        count = 1
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        """遍历链表"""
        cur = self._head
        while cur != None:
            print(cur.elem,end=',')
            cur = cur.next
        print()

    def add(self,item):
        """头部添加"""
        node =Node(item)
        node.next = self._head
        self._head = Node

    def append(self,item):
        """尾部添加"""
        node = Node(item)
        if self.is_empty():
            self._head = node
        else:
            cur = self._head
            while cur.next != None:
                cur = cur.next
            cur.next = node

    def insert(self,pos,item):
        """指定位置添加"""
        if pos <= 0:
            self.add(item)
        elif pos > self.length()-1:
            self.append(item)
        else:
            pre = self._head
            count = 0
            while  count < (pos-1):
                count+=1
                pre = pre.next
            node = Node(item)
            node.next = pre.next
            pre.next = node

    def remove(self,item):
        """删除元素"""
        cur = self._head
        pre = None
        while cur != None:
            if cur.elem == item:
                if cur == self._head:
                    self._head = cur.next

                else:
                    pre.next = cur.next
                break

            else:
                pre = cur
                cur = cur.next

    def search(self,item):
        """判断元素是否在链表中"""
        cur = self._head
        while cur != None:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        return False

if __name__=="__main__":

    li = SingleLinkList()
    print(li.is_empty())
    print(li.length())
    li.append(1)
    print(li.is_empty())
    print(li.length())
    li.append(2)
    li.append(3)
    li.insert(2,100)
    li.travel()
    li.append(9)
    li.remove(2)
    li.travel()
    print(li.search(100))


结果:
True
1
False
2
1,2,100,3,
1,100,3,9,
True
View Code

 

操作 链表 顺序表
访问元素 O(n) O(1)
在头部插入/删除 O(1) O(n)
在尾部安插入/删除 O(n) O(1)
在中间插入/删除 O(n) O(n)

 

 

 

 

 

单向循环链表:单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头结点。

class Node:
    """节点"""
    def __init__(self, item):
        self.item = item
        self.next = None

    def __str__(self):
        return str(self.item)


class SinCycLinkedList:
    """单向循环链表"""
    def __init__(self):
        self._head = None

    def is_empty(self):
        """判断链表是否为空"""
        return self._head is None

    def length(self):
        """链表长度"""
        if self.is_empty():
            return 0
        count = 1
        cur = self._head
        while cur.next != self._head:
            # print("cur", cur.item)
            count += 1
            cur = cur.next
        return count

    def travel(self):
        """遍历"""
        if self.is_empty():
            return

        cur = self._head
        print(cur.item)
        while cur.next != self._head:
            cur = cur.next
            print(cur.item)

    def add(self, item):
        """在头部添加一个节点"""
        node = Node(item)
        if self.is_empty():
            self._head = node
            node.next = self._head
        else:
            node.next = self._head
            cur = self._head
            while cur.next != self._head:
                cur = cur.next

            cur.next = node
            self._head = node

    def append(self, item):
        """在尾部添加一个节点"""
        node = Node(item)
        if self.is_empty():
            self._head = node
            node.next = self._head
        else:
            cur = self._head
            # print(type(cur), cur.item, cur.next)
            while cur.next != self._head:
                cur = cur.next

            # print(cur.item)
            cur.next = node
            node.next = self._head

    def insert(self, pos, item):
        """指定位置pos添加节点"""
        if pos <= 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            node = Node(item)
            cur = self._head
            cur_pos = 0
            while cur.next != self._head:
                if (pos - 1) == cur_pos:
                    node.next = cur.next
                    cur.next = node
                    break
                cur_pos += 1
                cur = cur.next

    def remove(self, item):
        """删除一个节点"""
        if self.is_empty():
            return

        pre = self._head
        # 删除首节点
        if pre.item == item:
            cur = pre
            while cur.next != self._head:
                cur = cur.next

            cur.next = pre.next     # 删除首节点(跳过该节点)
            self._head = pre.next   # 重新指定首节点

        # 删除其他的节点
        else:
            cur = pre
            while cur.next != self._head:
                if cur.next.item == item:
                    cur.next = cur.next.next
                cur = cur.next

    def search(self, item):
        """查找节点是否存在"""
        if self.is_empty():
            return -1

        cur_pos = 0
        cur = self._head
        if cur.item == item:
            return cur_pos

        while cur.next != self._head:
            if cur.item == item:
                return cur_pos
            cur_pos += 1
            cur = cur.next

        if cur_pos == self.length() - 1:
            return -1


if __name__ == "__main__":
    ll = SinCycLinkedList()
    ll.add(1)       # 1
    ll.add(2)       # 2 1
    # ll.travel()
    ll.append(3)    # 2 1 3
    ll.insert(2, 4) # 2 1 4 3
    ll.insert(4, 5) # 2 1 4 3 5
    ll.insert(0, 6) # 6 2 1 4 3 5
    print("length:", ll.length())        # 6
    ll.travel()                           # 6 2 1 4 3 5
    print("search(3)", ll.search(3))     # 4
    print("search(7)", ll.search(7))     # -1
    print("search(6)", ll.search(6))    # 0
    print("remove(1)")
    ll.remove(1)
    print("length:", ll.length())       # 6 2 4 3 5
    print("remove(6)")
    ll.remove(6)
    ll.travel()

结果:
length: 6
6
2
1
4
3
5
search(3) 4
search(7) -1
search(6) 0
remove(1)
length: 5
remove(6)
2
4
3
5
View Code

 

双向链表:一种更复杂的链表是 "双向链表" 或 "双面链表"。每个节点有两个链接:一个指向前一个节点,当次节点为第一个节点时,指向空值;而另一个指向下一个节点,当此节点为最后一个节点时,指向空值。

class Node:
    """节点"""
    def __init__(self, item):
        self.item = item
        self.prev = None
        self.next = None


class DLinkList:
    """双向链表"""
    def __init__(self):
        self._head = None

    def is_empty(self):
        """判断链表是否为空"""
        return self._head is None

    def length(self):
        """获取链表长度"""
        if self.is_empty():
            return 0
        else:
            cur = self._head
            count = 1
            while cur.next is not None:
                count += 1
                cur = cur.next

            return count

    def travel(self):
        """遍历链表"""
        print("↓↓" * 10)
        if self.is_empty():
            print("")

        else:
            cur = self._head
            print(cur.item)
            while cur.next is not None:
                cur = cur.next
                print(cur.item)
        print("↑↑" * 10)

    def add(self, item):
        """链表头部添加节点"""
        node = Node(item)
        if self.is_empty():
            self._head = node
        else:
            cur = self._head

            node.next = cur
            cur.prev = node
            self._head = node

    def append(self, item):
        """链表尾部添加节点"""
        node = Node(item)
        if self.is_empty():
            self._head = node
        else:
            cur = self._head
            # 遍历找到最后一个节点
            while cur.next is not None:
                cur = cur.next

            # 在尾节点添加新的节点
            cur.next = node
            node.prev = cur

    def insert(self, pos, item):
        """指定位置添加"""
        # 头部添加
        if pos <= 0:
            self.add(item)

        # 尾部添加
        elif pos > (self.length() - 1):
            self.append(item)

        # 其他位置添加
        else:
            node = Node(item)

            cur = self._head
            cur_pos = 0
            while cur.next is not None:
                if cur_pos == (pos - 1):
                    # 与下一个节点互相指向
                    node.next = cur.next
                    cur.next.prev = node
                    # 与上一个节点互相指向
                    cur.next = node
                    node.prev = cur
                cur_pos += 1
                cur = cur.next

    def remove(self, item):
        """删除节点"""
        if self.is_empty():
            return
        else:
            cur = self._head
            # 删除首节点
            if cur.item == item:
                self._head = cur.next
                cur.next.prev = None

            # 删除其他节点
            else:
                while cur.next is not None:
                    if cur.item == item:
                        # 删除之前:1 ←→ [2] ←→ 3
                        # 删除之后:1 ←→ 3
                        cur.prev.next = cur.next
                        cur.next.prev = cur.prev
                    cur = cur.next

                # 删除尾节点
                if cur.item == item:
                    cur.prev.next = None


    def search(self, item):
        """查找节点是否存在"""
        if self.is_empty():
            return -1
        else:
            cur = self._head
            cur_pos = 0
            while cur.next is not None:
                if cur.item == item:
                    return cur_pos

                cur_pos += 1
                cur = cur.next

            if cur_pos == (self.length() - 1):
                return -1


if __name__ == "__main__":
    ll = DLinkList()
    ll.add(1)       # 1
    ll.add(2)       # 2 1
    ll.append(3)    # 2 1 3
    ll.insert(2, 4) # 2 1 4 3
    ll.insert(4, 5) # 2 1 4 3 5
    ll.insert(0, 6) # 6 2 1 4 3 5
    print("length:", ll.length())   # 6
    ll.travel()                 # 6 2 1 4 3 5
    print("search(3)", ll.search(3))
    print("search(4)", ll.search(4))
    print("search(10)", ll.search(10))
    ll.remove(1)
    print("length:", ll.length())
    ll.travel()
    print("删除首节点 remove(6):")
    ll.remove(6)
    ll.travel()
    print("删除尾节点 remove(5):")
    ll.remove(5)
    ll.travel()
结果:
length: 6
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
6
2
1
4
3
5
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
search(3) 4
search(4) 3
search(10) -1
length: 5
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
6
2
4
3
5
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
删除首节点 remove(6):
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
2
4
3
5
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
删除尾节点 remove(5):
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
2
4
3
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
View Code

 

数据结构只允许在一端进行操作,按照后进先出(LIFO,Last In First Out)。

栈结构的实现

# Author:song
class Stack(object):
    """"""
    def __init__(self):
        self._items = []

    def is_empty(self):
        """判断是否为空"""
        return self._items == []
    def push(self,item):
        """添加新元素到栈顶"""
        self._items.append(item)

    def pop(self):
        """弹出栈顶元素"""
        self._items.pop()

    def peek(self):
        """返回栈顶元素"""
        if self._items:
            return self._items[-1]
        else:
            return None
        pass
    def size(self):
        pass

if __name__=="__main__":
    s=Stack()
    print(s.is_empty())
View Code

 

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。一种先进先出(FIFO,First In First Out)的线性表

队列的实现

class Queue:
    """队列"""
    def __init__(self):
        self.items = []

    def is_empty(self):
        return self.items == []

    def enqueue(self, item):
        """添加元素"""
        self.items.insert(0, item)

    def dequeue(self):
        """从队列头部删除一个元素"""
        return self.items.pop()

    def size(self):
        return len(self.items)


if __name__ == "__main__":
    q = Queue()
    q.enqueue("hello")
    q.enqueue("world")
    q.enqueue("queue")
    print(q.size())
    print(q.dequeue())      # hello
    print(q.dequeue())      # world
    print(q.dequeue())      # queue
View Code

 

双端队列,是一种具有队列和栈的性质的数据结构。

class Deque:
    """双端队列"""
    def __init__(self):
        self.items = []

    def add_front(self, item):
        """从队头加入一个元素"""
        self.items.insert(0, item)

    def add_rear(self, item):
        """从队尾加入一个元素"""
        self.items.append(item)

    def remove_front(self):
        """从队头删除一个元素"""
        return self.items.pop(0)

    def remove_rear(self):
        """从队尾删除一个元素"""
        return self.items.pop()

    def is_empty(self):
        """是否为空"""
        return self.items == []

    def size(self):
        """队列长度"""
        return len(self.items)


if __name__ == "__main__":
    deque = Deque()
    deque.add_front(1)
    deque.add_front(2)
    deque.add_rear(3)
    deque.add_rear(4)
    print(deque.size())             # 4
    print(deque.remove_front())     # 2
    print(deque.remove_front())     # 1
    print(deque.remove_rear())      # 4
    print(deque.remove_rear())      # 3
View Code

 

posted @ 2018-09-07 19:56  Mr.SSC  阅读(458)  评论(0编辑  收藏  举报