数据结构

 

1、什么是数据结构?

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

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

2、数据结构按照其逻辑结构可以分为,线性结构;树结构;图结构

线性结构:数据结构中的元素存在一对一的相互关系;比如列表,有一个前驱,一个后继

树结构:数据结构中的元素存在一对多的相互关系;有一个前驱,多个后继

图结构:数据结构中的元素存在多对多的相互关系;有多个前驱,多个后继

3、c语言的数组和python中列表的不同?

c语言数组1、元素的类型一样;2、数组的大小固定

列表:1、元素的类型可以不一样;2、列表的大小不固定

4、python中的列表是怎么存储的?

 

栈:

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

栈的基本操作:进栈,出栈,取栈顶。

栈的一个具体应用,括号匹配问题。

代码:

def bracket_match(string):
    bracket_dict = {")": "(", "]": "[", "}": "{", ">": "<"}
    li = []
    for item in string:
        if item in ["(","[","{","<"]:
            li.append(item)
        elif item in [")","]","}",">"]:
            if len(li) == 0:
                print("多了右括号%s"%item)
                return False
            elif li[-1] != bracket_dict[item]:
                print("右括号和左括号不匹配")
                return False
            elif li[-1] == bracket_dict[item]:
                li.pop()
    if len(li) !=0:
        print("多了左括号")
        return False
    else:
        print("括号匹配")
        return True

 函数栈

关于栈的一道面试题:

进栈顺序为1,2,3;下面那个不可能是出栈顺序?

A:1,2,3

B:1,3,2

C:2,1,3

D:2,3,1

E:3,2,1

F:3,1,2

F不可能

 栈的另外一个应用:

迷宫问题:

maze = [
    [1,1,1,1,1,1,1,1,1,1],
    [1,0,0,1,1,1,0,0,1,1],
    [1,0,0,0,0,1,1,0,0,1],
    [1,0,0,1,1,1,1,0,1,1],
    [1,0,0,0,0,0,0,0,0,1],
    [1,0,1,1,1,0,1,1,0,1],
    [1,0,1,1,1,0,1,1,0,1],
    [1,0,0,0,0,0,1,1,0,1],
    [1,1,1,1,1,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1]
        ]

direction = [lambda x,y:(x,y-1),
 lambda x,y:(x+1,y),
 lambda x,y:(x,y+1),
 lambda x,y:(x-1,y)
 ]


def find_path(x1,y1,x2,y2):
    """
    整体思想:向当前点的4个方向前进,如果前进方向上的点为0,则表示可以前进,找到一个方向就往前前进;如果一个点无法前进
    则回溯,直到回溯到能够前进的点,如果回溯到起点之后,stack中无值,则表示没有正确路径,或者找到正确路径输出正确路径。
    :param x1:起始点行坐标
    :param y1:起始点列坐标
    :param x2:终点行坐标
    :param y2:终点列坐标
    :return: True  or   False
    """
    # 初始化,起点终点和栈,将起点加到栈中,并设置起点为走过
    start = (x1,y1)
    end = (x2,y2)
    stack = []
    current = start
    stack.append(current)
    maze[current[0]][current[1]] = 2
    # 当当前节点不为终点时,执行循环,为终点则跳出循环打印路径
    while current != end:
        # 在4个方向上前进
        for d in direction:
            next_node = d(*current)
            # 前进的点值为0时
            if maze[next_node[0]][next_node[1]] == 0:
                current = next_node
                stack.append(current)
                maze[current[0]][current[1]] = 2
                # 4 个方向中有为0 的点,则for循环不会正常结束
                break
        # 4个方向中没有为0的,则for循环正常结束,进入else中,栈pop掉当前节点,回溯到上一个节点继续循环
        else:
            stack.pop()
            if len(stack) == 0:
                print("回溯超过起点,错误!无正确路径")
                return False
            current = stack[-1]
    print(stack)
    return True


# 另外一种写法
def find_path_1(x1,y1,x2,y2):
    start = (x1,y1)
    end = (x2,y2)
    stack = []
    stack.append(start)
    while len(stack) > 0:
        current_node = stack[-1]
        if current_node == end:
            print("找到正确路径")
            print(stack)
            return True
        for d in direction:
            next_node = d(*current_node)
            if maze[next_node[0]][next_node[1]] == 0:
                stack.append(next_node)
                maze[next_node[0]][next_node[1]] = 2
                # break 跳出,for循环的else也不执行
                # 如果while正常执行完,则会执行else中的内容,如果遇到break跳出循环,则else中的内容也不会执行。
                break
        else:
            stack.pop()
    print("回溯超过起点,没有正确路径")
    return False

队列:

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

队列用列表实现方式:

环形队列,front指向队头,rear指向队尾。

前进一步:front = (front + 1)%M;rear = (rear + 1)%M

队满:(rear+1)%M == front%M

队空·:rear%M == front%M

python中队列:

from collections import deque
q = deque()  # 创建一个队列
q.append(1)  # 往队列尾插入值
print(q.popleft())  # 从队列左边出队
q.appendleft(3)  # 往队列左边插入值
print(q.pop())  # 从队列右边出队

# 用队列实现tail功能
q = deque([],5)
for i in range(7):
    q.append(i)
for i in range(5):
    print(q.popleft())

q = deque(open("a.txt","rb"),5)
for i in range(5):
    print(q.popleft().decode())

链表:

链表包含数据值和指向下一个节点的指针。

手动创建链表:

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

a = Node(1)
b = Node(2)
c = Node(3)
a.next = b
b.next = c

p = a
while p != None:
    print(p.item)
    p = p.next

链表与列表常见操作比较:

按元素值查找,列表o(n),链表o(n),列表排序好后可以采用二分查找法,但是链表不行。

按下标查找:列表o(1),链表o(n);

在某元素后插入:列表o(n),链表o(1);

删除某元素:列表o(n),链表o(1);

链表现对于列表的优点

1、在插入和删除操作,速度明显快于列表;

2、使用链表,内存可以更加灵活的分布,可以利用链表重新实现栈和队列;

3、链表的这种链式存储方式,对树和图的结构由明显的启发方式。

建链表的两种方法和建好后再插入值,也可以用类实现;

class Node(object):
    def __init__(self,item):
        self.item = item
        self.next = None
# 建链表色两种方法
# 1、头插法
def create_linklist_head(li):
    head = None
    for i in li:
        p = Node(i)
        p.next = head
        head = p
    return head
# 尾插法
def create_linklist_tail(li):
    head = Node(li[0])
    tail = head
    for i in li[1:]:
        p = Node(i)
        tail.next = p
        tail =p
    return head
def add_node_head(item,head):
    """
    头插法,增加节点
    :param item:需要增加节点的内容
    :param head:将节点添加到哪一个链表上
    :return:返回链表的头节点
    """
    p = Node(item)
    p.next = head
    head = p
    return head
def add_node_tail(item,head):
    """
    尾插法增加一个节点,加在原链表的尾部
    :param item: 增加节点的内容
    :param head: 原链表的头节点
    :return: 原链表的头节点
    """
    p = Node(item)
    h = head
    while h.next != None:
        h = h.next
    h.next = p
    return head
link_list_1 = create_linklist_head([1,2,3,4])
link_list_1 = add_node_head(5,link_list_1)
while link_list_1 != None:
    print(link_list_1.item)
    link_list_1 = link_list_1.next

link_list_2 = create_linklist_tail([1,2,3,4])
add_node_tail(5,link_list_2)  # 因为家在后面,所以不重新赋值也可以
while link_list_2 != None:
    print(link_list_2.item)
    link_list_2 = link_list_2.next

哈希表(散列表)

通过哈希函数来计算数据存储位置的数据结构。

python中,字典和集合都是通过hash表实现的。因此字典中的键是不可变类型,也就是可hash的,也就是能够映射的。

数据库中的索引也可已用hash表

posted on 2018-10-14 23:28  andyAngelo  阅读(160)  评论(0编辑  收藏  举报