首页 > 技术文章 > 算法(2):数据结构

neozheng 2018-10-16 21:50 原文

数据结构:

数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成
简单来说, 数据结构就是设计数据以何种方式组织度存储在计算机中
比如:列表、集合和字典等都是一种数据结构
“程序=数据结构+算法”

数据结构的分类:

数据结构按照逻辑结构可分为线性结构、树结构和图结构
线性结构:数据结构中的元素存在一对一的相互关系
树结构:数据结构中的元素存在一对多的相互关系
图结构:数据结构中的元素存在多对多的相互关系

另外,32位机器上,一个整数占4个字节(4*8bit=32),一个地址也占4个字节

栈:

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

栈的特点:后进先出(last-in,first-out)
栈的概念:栈顶(表尾;最后一个元素),栈底(表头;0号元素)
栈的基本操作:
    进栈(压栈):push
    出栈:pop
    取栈顶(只查看栈顶的值,但不把栈顶删除): gettop
使用一般的列表结构即可实现栈

栈的应用 -- 括号匹配问题:

括号匹配问题:给一个字符串,其中包含小括号、中括号、大括号,求该字符串中的括号是否匹配
如:
    ()[]{}  # 匹配
    ([{()}])  # 匹配
    []( # 不匹配
    [(])  # 不匹配

示例代码:

class BracketError(BaseException):
    def __init__(self,msg):
        super(BracketError,self).__init__()
        self.msg = msg

    def __str__(self):
        return "<%s>" %self.msg

class Stack(object):
    """实现栈的类"""
    def __init__(self):
        self.stack = []

    def push(self,ele):
        self.stack.append(ele)
    def pop(self):
        if len(self.stack) == 0:
            return None
        return self.stack.pop()
    def get_top(self):
        if len(self.stack) == 0:
            return None
        return self.stack[-1]

    def is_empty(self):
        return len(self.stack) == 0  # 返回的是一个Bool值

# 栈的应用:括号匹配问题
def bracket_match(s):
    stack = Stack()
    match_dict = {
        ")":"(",
        "]":"[",
        "}":"{"
    }
    for char in s:
        if char in ["(","[","{"]: # char 为左括号
            stack.push(char)  # 左括号放到 栈 里面
        else:  # char 为右括号
            if stack.is_empty():
                raise BracketError("%s expected"%match_dict[char])
            left_bracket = stack.get_top()
            if match_dict[char] != left_bracket:
                raise BracketError("%s not match"%char)
            else:
                stack.pop()
    if not stack.is_empty():
        raise BracketError("lacking corresponding right brackets")

s = "}[]()"
bracket_match(s)

 

链表

1. 链表定义:

# 链表是由一系列节点组成的元素集合。每个节点包含两部分:数据域item 和 指向下一个节点的指针next。通过节点之间的相互连接,最终串联成一个链表

示意图:

示例代码:

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

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

# 把 a 和 b, c 连接起来
a.next = b    
b.next = c

print(a.next.item)
print(a.next.next.item)

# 打印结果:
# 2
# 3

2. 链表的创建和定义

链表的创建:
1) 头插法:插到头节点前面
2) 尾插法:插到尾节点后面

# 示例代码:

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

def create_linkedlist_head(li):        # 通过列表进行 头插法 创建链表
    head = Node(li[0])    # 利用列表的第一个元素创建链表头(头节点)
    
    for ele in li[1:]:
        node = Node(ele)    # 创建链表头的上一个节点

        # 新创建的这个节点的 next 指向 头节点,然后让新创建的这个节点作为头节点
        node.next = head
        head = node

    return head  # 返回头节点

def print_linkedlist(lk):
    # 链表的遍历
    while lk:    # 节点不为空
        print(lk.item, end=",")
        lk = lk.next
    print()

lk1 = create_linkedlist_head([1,2,3])
print_linkedlist(lk1)

# print_linkedlist(lk1) 执行结果: 
# 3,2,1,

def create_linkedlist_tail(li):        # 通过列表 尾插法 创建链表
    head = Node(li[0])    
    tail = head          # 此处必须通过这种赋值方式,才能让 最初的tail 指向 head; 如果 tail = Node(li[0]) ,此时 tail 和 head 是不同的 Node 实例
    
    for ele in li[1:]:
        node = Node(ele)
        # 创建新节点,上一个tail的next指向这个新节点,然后让这个新节点成为 tail 节点
        tail.next = node
        tail = node
    return head

lk2 = create_linkedlist_tail([1,2,3,6,8])
print_linkedlist(lk2)
# 上面打印结果:
# 1,2,3,6,8,

链表节点的插入和删除

插入:

代码:

p.next = curNode.next
curNode.next = p
# 上面两步的顺序不能反,即应该先把 4 和 2 链起来,两把 1 和 4 链起来

删除:

代码:

curNode.next = curNode.next.next

双链表

# 双链表的每个节点有两个指针:一个指向后一个节点,另一个指向前一个节点

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

 

示意图:

双链表的插入和删除:

# 双链表的插入
p.next = curNode.next
curNode.next.prior = p
p.prior = curNode
curNode.next = p

# 双链表的删除
p = curNode.next
curNode.next = p.next
p.next.prior = curNode

 

推荐阅读