2021-04-06 数据结构

本文深入探讨了数据结构的时间复杂度计算规则,包括线性结构的顺序表和链表,详细介绍了栈、队列、排序算法(如冒泡、选择、插入、快速排序)以及二分查找和二叉树的相关概念和实现。此外,还涵盖了二叉树的性质及其在实际存储中的应用。
摘要由CSDN通过智能技术生成

2021-04-06数据结构


时间复杂度

1.时间复杂度的计算规则

1、基本操作,认为其时间复杂度为O(1)
sum = 100 + 200
sum = 2002+1002
2、顺序结构,时间复杂度按加法进行计算
第一步:a = 100
第二步:b = 200
第三步:c = a + b
O(1)
3、循环结构,时间复杂度按乘法进行计算

for j in range(0,2):
	for i in range(0,n):
		print(i)

O(n)
分支结构,时间复杂度去最大值
判断一个算法的效率是,往往只需要关注操作数量的最高次项,其他次要项和常数项可以忽略
没有特殊说明时,我们分析的算法时间复杂度都是指最坏时间复杂度

线性结构

1.线性结构存储方式的分类

线性结构的实际存储方式,分为两种实现模型:
·顺序表
·链表

2.顺序表

顺序表存储数据的两种情况:
·一体式结构
·分离式结构

3.顺序表的结构

顺序表的完整信息包括两部分:数据区、信息区

4.链表的代码实现

结点代码实现

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

class SinleLinkList(object):
    def __init__(self, node=None):
        self.head = node
    def is_empty(self):
        if self.head is None:
            return True
        else:
            return False
    def length(self):
        cur = self.head
        num = 0
        while cur is not None:
            cur = cur.next
            num = num + 1
        return num
    #头部增加节点
    def add(self,item):
        node = SingleNode(item)
        node.next = self.head
        self.head = node

    # 尾部增加结点
    def append(self,item):
        node = SingleNode(item)
        # 判断是否为空链表,特殊情况
        if self.is_empty():
            self.head = node

        cur = self.head
        while cur.next is not None:
            cur = cur.next
        cur.next = node

    def insert(self,pos,item):
        if pos == 0:
            self.add(item)
        elif pos >= self.length():
            self.append(item)
        else:
            node = SingleNode(item)
            cur = self.head
            count = 0
            while count < pos:
                cur = cur.next
                count = count + 1
            node.next = cur.next
            cur.next = node

    def remove(self,item):
        cur = self.head
        pre = None
        while cur is not None:
            if cur.item == item:
                if cur == self.head:
                    self.head=cur.next
                else:
                    pre.next = cur.next
                    return
            else:
                pre = cur
                cur = cur.next


class Stack(object):
    def __init__(self):
        self.__items = []

    def push(self,item):
        self.__items.append(item)

    def pop(self):
        self.__items.pop()

队列

class Queue(object):
    def __init__(self):
        self.items = []

    def enqueue(self,item):
        self.items.append(item)

    def dequeue(self):
        self.items.pop(0)

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

    def size(self):
        return len(self.items)
  
# 双端队列
class Dequen(object):
    def __init__(self):
        self.items = []

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

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

    def add_front(self, item):
        """头部添加数据"""
        self.items.append(0, item)

    def add_rear(self,item):
        """尾部添加数据"""
        self.items.append(item)

    def remove_front(self):
        self.items.pop(0)

    def remove_rear(self):
        self.items.pop()  

排序

排序算法的稳定性

不稳定的排序算法:选择排序,快速排序,希尔排序,堆排序
稳定的排序算法:冒泡排序,插入排序,归并排序,基数排序

冒泡排序

def bubble_sort(alist):
    n = len(alist)
    count = 0
    for j in range(0, n-1):
        for i in range(0, n-j-1):
            if alist[i] > alist[i+1]:
                alist[i], alist[i+1] = alist[i+1], alist[i]
                count = count+1
        if count == 0:
                break
    return alist

选择排序

def select_sort(alist):
    n = len(alist)
    for j in range(0,n-1):
        min_index = j
        for i in range(j+1,n):
            if alist[i] < alist[min_index]:
                min_index = i
        if j != min_index:
            alist[j], alist[min_index] = alist[min_index], alist[j]
    return alist

插入排序

def insert_sort(alist):
    n = len(alist)
    for i in range(1,n):
        for j in range(i,0,-1):
            if alist[j] < alist[j-1]:
                alist[j], alist[j-1] = alist[j-1], alist[j]
            else:
                break
    return alist

快速排序

def quick_sort(alist,start,end):
    if start >= end:
        return
    mid = alist[start]

    left = start
    right = end

    while left < right:
        while alist[right] >= mid and left < right:
            right -= 1
        alist[left] = alist[right]
        while alist[left] < mid and left < right:
            left += 1
        alist[right] = alist[left]

    alist[left] = mid

    quick_sort(alist,start,left-1)
    quick_sort(alist,right+1,end)

二分查找

递归

def binary_search(alist, item):
    n = len(alist)

    if n == 0:
        return False

    mid = n//2
    if item == alist[mid]:
        return True
    elif item > alist[mid]:
        return binary_search(alist[mid+1:],item)
    elif item < alist[mid]:
        return binary_search(alist[0:mid],item)

非递归

def binary_search(alist, item):
    n = len(alist)
    start = 0
    end = n-1
    while start <= end:
        mid = (start + end)//2
        if alist[mid] == item:
            return mid
        elif alist[mid] < item:
            start = mid + 1
        elif alist[mid] > item:
            end = mid - 1
    return False

二叉树

二叉树的性质

性质1:在二叉树的第i层上至多有2i-1个结点(i>0)
性质2:深度为k的二叉树至多又2k-1个结点(k>0)
性质3:对于任意一颗二叉树,如果其叶节点数为N0,而度数为2的节点总数为N2,则N0=N2+1
性质4:最多有n个结点的完全二叉树的深度必为log2(n+1)
性质5:对完全二叉树,若从上至下、从左至右编号,则编号为i的结点,其左孩子编号必为2i,其右孩子编号必为2i+1,其父节点的编号必为i//2(i=1时为根,除外)

二叉树实现

class Node(object):
    """节点类"""
    def __init__(self, item):
        self.item = item
        self.lchild = None
        self.rchild = None

class BinaryTree(object):
    """完全二叉树"""
    def __init__(self, node=None):
        self.root = node

    def add(self, item):
        if self.root == Node:
            self.root = Node(item)
            return

        queue = []
        queue.append(self.root)
        while True:
            node = queue.pop(0)
            if node.lchild == None:
                node.lchild = Node(item)
                return
            else:
                queue.append(node.lchild)

            if node.rchild == None:
                node.rchild = Node(item)
                return
            else:
                queue.append(node.rchild)

    def preorder_travel(self, root):
        """先序遍历"""
        if root is not None:
            print(root.item,end="")
            self.preorder_travel(root.lchild)
            self.preorder_travel(root.rchild)

    def inorder_travel(self, root):
        """中序遍历"""
        if root is not None:
            self.preorder_travel(root.lchild)
            print(root.item,end="")
            self.preorder_travel(root.rchild)

    def postorder_travel(self, root):
        """后序遍历"""
        if root is not None:
            self.preorder_travel(root.lchild)
            self.preorder_travel(root.rchild)
            print(root.item,end="")
使用python中的pymsql完成如下:表结构与数据创 1. 立 `users` 表和 `orders` 表。 `users` 表有用户ID、用户名、年龄字段,(id,name,age) `orders` 表有订单ID、订单日期、订单金额,用户id字段。(id,order_date,amount,user_id) 2 两表的id作为主键,`orders` 表用户id为users的外键 3 插入数据 `users` (1, '张三', 18), (2, '李四', 20), (3, '王五', 22), (4, '赵六', 25), (5, '钱七', 28); `orders` (1, '2021-09-01', 500, 1), (2, '2021-09-02', 1000, 2), (3, '2021-09-03', 600, 3), (4, '2021-09-04', 800, 4), (5, '2021-09-05', 1500, 5), (6, '2021-09-06', 1200, 3), (7, '2021-09-07', 2000, 1), (8, '2021-09-08', 300, 2), (9, '2021-09-09', 700, 5), (10, '2021-09-10', 900, 4); 查询语句 1. 查询订单总金额 2. 查询所有用户的平均年龄,并将结果四舍五入保留两位小数。 3. 查询订单总数最多的用户的姓名和订单总数。 4. 查询所有不重复的年龄。 5. 查询订单日期在2021年9月1日至9月4日之间的订单总金额。 6. 查询年龄不大于25岁的用户的订单数量,并按照降序排序。 7. 查询订单总金额排名前3的用户的姓名和订单总金额。 8. 查询订单总金额最大的用户的姓名和订单总金额。 9. 查询订单总金额最小的用户的姓名和订单总金额。 10. 查询所有名字中含有“李”的用户,按照名字升序排序。 11. 查询所有年龄大于20岁的用户,按照年龄降序排序,并只显示前5条记录。 12. 查询每个用户的订单数量和订单总金额,并按照总金额降序排序。
06-03
这里是使用 Python 的 PyMySQL 完成上述任务的代码: ```python import pymysql # 连接数据库 conn = pymysql.connect(host='localhost', port=3306, user='root', password='123456', database='test') # 创游标 cur = conn.cursor() # 创 users 表 cur.execute(''' CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(20), age INT ) ''') # 创 orders 表 cur.execute(''' CREATE TABLE orders ( id INT PRIMARY KEY, order_date DATE, amount INT, user_id INT, FOREIGN KEY (user_id) REFERENCES users(id) ) ''') # 插入数据 users_data = [ (1, '张三', 18), (2, '李四', 20), (3, '王五', 22), (4, '赵六', 25), (5, '钱七', 28) ] orders_data = [ (1, '2021-09-01', 500, 1), (2, '2021-09-02', 1000, 2), (3, '2021-09-03', 600, 3), (4, '2021-09-04', 800, 4), (5, '2021-09-05', 1500, 5), (6, '2021-09-06', 1200, 3), (7, '2021-09-07', 2000, 1), (8, '2021-09-08', 300, 2), (9, '2021-09-09', 700, 5), (10, '2021-09-10', 900, 4) ] for user in users_data: cur.execute('INSERT INTO users VALUES (%s, %s, %s)', user) for order in orders_data: cur.execute('INSERT INTO orders VALUES (%s, %s, %s, %s)', order) # 提交事务 conn.commit() # 查询语句 # 1. 查询订单总金额 cur.execute('SELECT SUM(amount) FROM orders') print(cur.fetchone()[0]) # 2. 查询所有用户的平均年龄,并将结果四舍五入保留两位小数。 cur.execute('SELECT ROUND(AVG(age), 2) FROM users') print(cur.fetchone()[0]) # 3. 查询订单总数最多的用户的姓名和订单总数。 cur.execute(''' SELECT users.name, COUNT(*) AS total_orders FROM users JOIN orders ON users.id = orders.user_id GROUP BY users.id ORDER BY total_orders DESC LIMIT 1 ''') print(cur.fetchone()) # 4. 查询所有不重复的年龄。 cur.execute('SELECT DISTINCT age FROM users') print([row[0] for row in cur.fetchall()]) # 5. 查询订单日期在2021年9月1日至9月4日之间的订单总金额。 cur.execute('SELECT SUM(amount) FROM orders WHERE order_date BETWEEN "2021-09-01" AND "2021-09-04"') print(cur.fetchone()[0]) # 6. 查询年龄不大于25岁的用户的订单数量,并按照降序排序。 cur.execute(''' SELECT users.name, COUNT(*) AS total_orders FROM users JOIN orders ON users.id = orders.user_id WHERE age <= 25 GROUP BY users.id ORDER BY total_orders DESC ''') print(cur.fetchall()) # 7. 查询订单总金额排名前3的用户的姓名和订单总金额。 cur.execute(''' SELECT users.name, SUM(amount) AS total_amount FROM users JOIN orders ON users.id = orders.user_id GROUP BY users.id ORDER BY total_amount DESC LIMIT 3 ''') print(cur.fetchall()) # 8. 查询订单总金额最大的用户的姓名和订单总金额。 cur.execute(''' SELECT users.name, SUM(amount) AS total_amount FROM users JOIN orders ON users.id = orders.user_id GROUP BY users.id ORDER BY total_amount DESC LIMIT 1 ''') print(cur.fetchone()) # 9. 查询订单总金额最小的用户的姓名和订单总金额。 cur.execute(''' SELECT users.name, SUM(amount) AS total_amount FROM users JOIN orders ON users.id = orders.user_id GROUP BY users.id ORDER BY total_amount ASC LIMIT 1 ''') print(cur.fetchone()) # 10. 查询所有名字中含有“李”的用户,按照名字升序排序。 cur.execute('SELECT * FROM users WHERE name LIKE "%李%" ORDER BY name ASC') print(cur.fetchall()) # 11. 查询所有年龄大于20岁的用户,按照年龄降序排序,并只显示前5条记录。 cur.execute('SELECT * FROM users WHERE age > 20 ORDER BY age DESC LIMIT 5') print(cur.fetchall()) # 12. 查询每个用户的订单数量和订单总金额,并按照总金额降序排序。 cur.execute(''' SELECT users.name, COUNT(*) AS total_orders, SUM(amount) AS total_amount FROM users JOIN orders ON users.id = orders.user_id GROUP BY users.id ORDER BY total_amount DESC ''') print(cur.fetchall()) # 关闭游标和连接 cur.close() conn.close() ``` 注意:在运行代码之前,需要先安装 PyMySQL 模块,可以使用以下命令进行安装: ``` pip install pymysql ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值