zoukankan      html  css  js  c++  java
  • 数据结构基础

    什么时数据结构?

          数据结构是指相互之间存在着一种或者多种关系的数据元素的集合和该集合中数据元素之间的关系组成。

           简单来说,数据结构就是设计数据以何种方式组织并存储在计算机中。

           比如:列表、集合与字典都是一种数据结构。

           还是那句话:程序=数据机构+算法

    数据结构的分类:

        数据结构按照其逻辑结构可分为线性结构、数结构、图结构

         线性结构:数据结构中的元素存在一对一的相互关系

         树结构:数据结构中的元素存在一对多的相互关系

         图结构:数据结构中的元素存在多对多相互关系

    列表:在其它编程语言中称为‘数组’,是一种基本的数据结构类型。

           它使用顺序存储。

    栈:

      栈是一个数据集合,可以理解为只能在一端进行插入或删除操作的列表。

      栈的特点:后进先出。

    栈的概念:

      栈顶

      栈底

    栈的基本操作:

        进栈:push

        出栈:pop

       取栈顶:gettop

    例子:

    def brace_match(s):
        stack = []
        match = {')':'(', ']':'[', '}':'{'}
        match2 = {'(':')', '[':']', '{':'}'}
        for ch in s:
            if ch in {'(', '[', '{'}:#如果是这里
                stack.append(ch)
            elif len(stack) == 0:
                print("缺少%s" % match[ch])
                return False
            elif stack[-1] == match[ch]:
                stack.pop()
            else:
                print("括号不匹配")
                return False
        if len(stack) > 0:
            print("缺少%s" % (match2[stack[-1]]))
            return False
        return True
    
    
    brace_match("[{()[]}{}{}")
    View Code

    队列:

    队列是一个数据集合,仅允许在列表的一端进行插入,另一端进行删除。

    进行插入的一端称为队尾,插入动作称为进队或入队。

    进行删除的一端称为对头,删除动作称为出队。

    队列的性质:先进先出。

    双向队列的性质:队列的两端都允许进行进队和出队操作。

     环形队列:

    环形队列的概念:

     迷宫问题:

    两种方法:

    from collections import deque
    
    maze = [
        [1,1,1,1,1,1,1,1,1,1],
        [1,0,0,1,0,0,0,1,0,1],
        [1,0,0,1,0,0,0,1,0,1],
        [1,0,0,0,0,1,1,0,0,1],
        [1,0,1,1,1,0,0,0,0,1],
        [1,0,0,0,1,0,0,0,0,1],
        [1,0,1,0,0,0,1,0,0,1],
        [1,0,1,1,1,0,1,1,0,1],
        [1,1,0,0,0,0,0,0,0,1],
        [1,1,1,1,1,1,1,1,1,1]
    ]
    
    dirs = [
        lambda x,y:(x-1,y),  #
        lambda x,y:(x,y+1),  #
        lambda x,y:(x+1,y),  #
        lambda x,y:(x,y-1),  #
    ]
    
    
    def solve_maze(x1, y1, x2, y2):
        """
        方法一
    
        :param x1:
        :param y1:
        :param x2:
        :param y2:
        :return:
        """
    
        stack = []
        stack.append((x1,y1))#x1,y1是起点
        maze[x1][y1] = 2
        while len(stack) > 0:   # 当栈不空循环
            cur_node = stack[-1]
            if cur_node == (x2,y2): #到达终点
                for p in stack:
                    print(p)
                return True
            for dir in dirs:
                next_node = dir(*cur_node)#加*就是打散
                if maze[next_node[0]][next_node[1]] == 0:   #找到一个能走的方向
                    stack.append(next_node)
                    maze[next_node[0]][next_node[1]] = 2  # 2表示已经走过的点
                    break
            else: #如果一个方向也找不到就把它删除
                stack.pop()
        else:
            print("无路可走")
            return False
    
    
    def solve_maze2(x1,y1,x2,y2):
        queue = deque()
        path = []    # 记录出队之后的节点
        queue.append((x1,y1,-1))#这是放入的起点元素
        maze[x1][y1] = 2        #把放入的元素设置为2
        while len(queue) > 0:
            cur_node = queue.popleft()#把元素从左边放出来
            path.append(cur_node)#把这个放到path里面
            if cur_node[0] == x2 and cur_node[1] == y2:  #到了终点,我们用回溯找路径
                print(path)
                real_path = []
                x,y,i = path[-1]
                real_path.append((x,y))
                while i >= 0:
                    node = path[i]
                    real_path.append(node[0:2])
                    i = node[2]
                real_path.reverse()
                # for p in real_path:
                #     print(p)
                return True
            for dir in dirs:#这是广度优先的查找
                next_node = dir(cur_node[0], cur_node[1])#这个是往左右移动
                if maze[next_node[0]][next_node[1]] == 0:#然后判断是否是可以通过的
                    queue.append((next_node[0], next_node[1], len(path)-1))
                    maze[next_node[0]][next_node[1]] = 2 # 标记为已经走过
        else:
            print("无路可走")
            return False
    
    
    
    
    solve_maze(1,1,8,8)
    View Code

    链表:

    建立链表:

       头插入法和尾插入法:

     一般的插入和删除方法:

        

    双链表:

     列表与链表的时间复杂度:

           按元素值查找 O(N)

            按小标查找O(N)

           在某元素后插入O(1)

           删除某元素O(1)

    哈希冲突:

     

    解决这个问题:

    方法一:

    方法二:

    二叉树:

    根据根节点的先后顺序分前中后序遍历。

    创建二叉树:

    from collections import deque
    
    
    class BiTreeNode:
        def __init__(self, data):
            self.data = data
            self.lchild = None
            self.rchild = None
    
    a = BiTreeNode('A')
    b = BiTreeNode('B')
    c = BiTreeNode('C')
    d = BiTreeNode('D')
    e = BiTreeNode('E')
    f = BiTreeNode('F')
    g = BiTreeNode('G')
    
    e.lchild = a
    e.rchild = g
    a.rchild = c
    c.lchild = b
    c.rchild = d
    g.rchild = f
    
    root = e
    
    def pre_order(root):
        if root:
            print(root.data, end='')
            pre_order(root.lchild)
            pre_order(root.rchild)
    
    def in_order(root):
        if root:
            in_order(root.lchild)
            print(root.data, end='')
            in_order(root.rchild)
    
    
    def post_order(root):
        if root:
            post_order(root.lchild)
            post_order(root.rchild)
            print(root.data, end='')
    
    
    def level_order(root):
        queue = deque()
        queue.append(root)
        while len(queue) > 0:
            node = queue.popleft()
            print(node.data,end='')
            if node.lchild:
                queue.append(node.lchild)
            if node.rchild:
                queue.append(node.rchild)
    
    
    
    pre_order(root)
    print("")
    in_order(root)
    print("")
    post_order(root)
    print("")
    level_order(root)
    View Code

     

    贪心算法:(找零钱)

    # greedy algorithm
    
    money = [100,50,20,5,1]
    
    def change_money(x):
        change = [0,0,0,0,0]
        for i,m in enumerate(money):
            change[i] = x // money[i]
            x = x % money[i]
        if x > 0:
            print("还剩%s" % x)
        return change
    
    print(change_money(356.2))
    View Code

    斐波那切数列:

    def fib(n):
        f = [1,1]
        for i in range(2, n+1):
            f.append(f[-1]+f[-2])
        print(f)
        return f[n]
    
    fib(5)
    View Code

    动态规划里面的最长上升子序列:

    def LIS(x):
        F = [0 for _ in range(len(x))]
        p = [-1 for _ in range(len(x))]
        # 初始化
        F[0] = 1
        p[0] = -1
        for k in range(1, len(F)):
            max_loc = -1
            max_num = 0
            # 内层循环表示F[0:k]里所有小于x[k]的对应位置的F[i]的最大值
            for i in range(0, k):
                if x[i] < x[k]:
                    if F[i] > max_num:
                        max_loc = i
                        max_num = F[i]
            F[k] = max_num + 1
            p[k] = max_loc
    
        max_i = 0
        for i in range(1,len(F)):
            if F[i] > F[max_i]:
                max_i = i
    
        lis = []
        i = max_i
        while i >= 0:
            lis.append(x[i])
            i = p[i]
        lis.reverse()
        return lis
    
    print(LIS([9,7,2,8,3,5,2]))
    View Code

    最大子序列:(不要求连着)

    def LCS(x, y):
        F = [[0 for _ in range(len(y)+1)] for _ in range(len(x)+1)]
        p = [[0 for _ in range(len(y)+1)] for _ in range(len(x)+1)]
        for i in range(1, len(x)+1):
            p[i][0] = 2
        for j in range(1, len(y)+1):
            p[0][j] = 1
    
        # 0 斜向  1 横向 j-1   2竖向 i-1
        for i in range(1, len(x)+1):
            for j in range(1, len(y)+1):
                if x[i-1] == y[j-1]:
                    F[i][j] = F[i-1][j-1]+1
                    p[i][j] = 0
                else:
                    #F[i][j] = max(F[i-1][j], F[i][j-1])
                    if F[i-1][j] > F[i][j-1]:
                        F[i][j] = F[i-1][j]
                        p[i][j] = 2
                    else:
                        F[i][j] = F[i][j-1]
                        p[i][j] = 1
    
        lcs = []
        i = len(x)
        j = len(y)
        while i > 0 or j > 0:
            if p[i][j] == 0:
                lcs.append(x[i-1])
                i -= 1
                j -= 1
            elif p[i][j] == 1:
                j -= 1
            else:
                i -= 1
        lcs.reverse()
        return lcs
        #return F[i][j]
    
    print(LCS("ABBCBDE", "DBBCDB"))
    View Code

    最长公共子序列:(要求连着)

    def LCSS(x, y):
        F = [[0 for _ in range(len(y)+1)] for _ in range(len(x)+1)]
        p = [[0 for _ in range(len(y)+1)] for _ in range(len(x)+1)]
        # 0 不匹配 1匹配
        for i in range(1, len(x)+1):
            for j in range(1, len(y)+1):
                if x[i-1] == y[j-1]:
                    F[i][j] = F[i-1][j-1]+1
                    p[i][j] = 1
                else:
                    F[i][j] = 0
                    p[i][j] = 0
        max_val = 0
        max_i = 0
        max_j = 0
        for i in range(1, len(x)+1):
            for j in range(1, len(y)+1):
                if F[i][j] > max_val:
                    max_val = F[i][j]
                    max_i = i
                    max_j = j
        #tracback
        lcss = []
        i = max_i
        j = max_j
        while p[i][j] == 1:
            lcss.append(x[i-1])
            i -= 1
            j -= 1
    
        lcss.reverse()
        return lcss
    
    print(LCSS("ABBCBDE", "DBBCDB"))
    View Code
  • 相关阅读:
    HTML表单
    CSS等高布局的6种方式
    HTML用户反馈表单
    HTML美化修饰<A>
    sql查询语句 --------一个表中的字段对应另外一个表中的两个字段的查询语句
    jq 表格添加删除行
    js 静止f1到f12 和屏蔽鼠标右键
    手机自适应页面的meta标签
    tp3.2 的验证码的使用
    php多线程抓取网页
  • 原文地址:https://www.cnblogs.com/1a2a/p/8400203.html
Copyright © 2011-2022 走看看