数据结构代码(Python)

数据结构代码(Python)

链表

链表的创建

# 建立链表结点对象
class Node():
    def __init__(self, value):
        self.value = value
        self.next = None

# 建立[1,2,3]的链表
node1 = Node(1)
node2 = Node(2)
node3 = Node(3)

# 正向链接
node1.next = node2
node2.next = node3
print(node1.value, node1.next.value, node1.next.next.value)

# 反向链接
node3.next = node2
node2.next = node1
print(node3.value, node3.next.value, node3.next.next.value)
# 创建单链表的结点
class SingeNode:
    def __init__(self, item):
        # item存放值
        self.item = item
        # next指向下一个结点
        self.next = None


# 创建单链表
class LinkList:
    def __init__(self):
        # 创建一个空头结点
        self.head = None

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

    def __len__(self):
        """计算链表的长度"""
        # cur表示游标也就是指针,定义指向头结点
        cur = self.head
        # count表示计数器
        count = 0
        while cur is not None:
            count += 1
            # cur指针向后移一位
            cur = cur.next
        return count

    def travel(self):
        """遍历链表"""
        cur = self.head
        while cur is not None:
            print(cur.item)
            # 指针向后移
            cur = cur.next

    def creat_linklist_head(self, li=None, item=None):
        """头插法"""
        # 如果传入的是列表
        if li:
            # 创建头结点
            self.head = SingeNode(li[0])
            # 把剩下的元素插入进去
            for element in li[1:]:
                # 创建剩下元素的结点
                node = SingeNode(element)
                # 新建结点的next指针指向上一个结点
                node.next = self.head
                # 头指针指向新建结点
                self.head = node

        # 如果传入的是某个值
        elif item:
            node = SingeNode(item)
            # 新建结点的next指针指向上一个结点
            node.next = self.head
            # 头指针指向新建结点
            self.head = node
        return self.head

    def creat_linklist_tail(self, li=None, item=None):
        """尾插法"""
        # 如果传入的是列表
        if li:
            # 创建头结点
            self.head = SingeNode(li[0])
            # 创建尾结点
            tail = self.head
            # 把剩下的元素插入进去
            for element in li[1:]:
                node = SingeNode(element)
                # 尾结点的next指针指向新建结点
                tail.next = node
                # 尾结点指向现在这个结点
                tail = node
        # 如果传入的是值
        elif item:
            # 创建尾结点
            tail = self.head
            node = SingeNode(item)
            # 尾结点的next指针指向新建结点
            tail.next = node
            # 尾结点指向现在这个结点
            tail = node
        return self.head

    def insert(self, pos, item):
        """指定位置添加元素"""
        # 若指定位置pos为第一个元素之前,执行头插法
        if pos <= 0:
            self.creat_linklist_head(item=item)
        # 若指定位置pos为最后一个元素之后,执行尾插法
        elif pos > len(self) - 1:
            self.creat_linklist_tail(item=item)
        else:
            node = SingeNode(item)
            # 定义一个计数器记录pos前一个位置
            count = 0
            # 定义一个pre指针指向pos-1,初始从头结点向指定位置移动
            pre = self.head
            while count < (pos - 1):
                count += 1
                # pre指针向后移动
                pre = pre.next
            # 插入结点的next指针指向pre指针的next
            node.next = pre.next
            # pre指针的next指向插入的结点
            pre.next = node

    def search(self, item):
        """指定值进行查找"""
        # 定义一个游标指向头结点
        cur = self.head
        while cur is not None:
            # 当此刻cur指针的值等于传入的值时
            if cur.item == item:
                return True
            # 指针向后移一位
            cur = cur.next
        return False

    def remove(self, item):
        """删除指定值的结点"""
        # 定义一个游标指向头结点并且依次往后取值
        cur = self.head
        # 定义一个pre指针指向None
        pre = None
        while cur is not None:
            # 如果头结点的值等于指定值
            if cur.item == item:
                # 如果指定值是第一个结点
                if not pre:
                    self.head = cur.next
                # 如果指定值是最后一个结点
                else:
                    pre.next = cur.next
                break
            else:
                # 将pre指针指向cur值
                pre = cur
                # cur指针一次向后移一位
                cur = cur.next

    def creat_2_LinkList_head(self, li=None, item=None):
        """头插法"""

        def head(value):
            node = SingeNode(value)
            if self.is_empty():
                # 如果是空链表,将头结点指向node
                self.head = node
            else:
                # 将node的next指向head的头节点
                node.next = self.head
                # 将head的头节点的prev指向node
                self.head.prev = node
                # 将head头结点指向node
                self.head = node

        if li:
            for elment in li:
                head(elment)
        elif item:
            head(item)
        # return self.head

    def creat_2_LinkList_tail(self, li=None, item=None):
        """尾部插入元素"""

        def tail(value):
            node = SingeNode(value)
            if self.is_empty():
                # 如果是空链表,将head头结点指向node
                self.head = node
            else:
                # 移动到链表尾部
                cur = self.head
                while cur.next is not None:
                    cur = cur.next
                # 将尾节点cur的next指向node
                cur.next = node
                # 将node的prev指向cur
                node.prev = cur

        if li:
            for element in li:
                tail(element)
        elif item:
            tail(item)


if __name__ == '__main__':
    pass
    # 头插法创建单链表
    # p = LinkList()
    # p.creat_linklist_head(1)
    # p.creat_linklist_head(2)
    # p.creat_linklist_head(3)
    # # 遍历链表
    # p.travel()

    # 尾插法创建单链表
    # p = LinkList()
    # p.creat_linklist_tail(1)
    # p.creat_linklist_tail(2)
    # p.creat_linklist_tail(3)
    # # 遍历链表
    # p.travel()

    # 列表创建单链表
    # li = [1, 2, 3]
    # # 创建单链表
    # p = LinkList()
    # 头插法创建
    # p.creat_linklist_head(li=li)
    # 尾插法创建
    # p.creat_linklist_tail(li=li)
    # # 遍历链表
    # p.travel()

    # 插入链表
    # p.insert(len(li)-1, 3)
    # p.travel()

    # 查找链表
    # print(p.search(0))

    # 删除链表
    # p.remove(4)
    # p.travel()

    # 创建头插法双链表
    # p1 = LinkList()
    # p1.creat_2_LinkList_head(item=1)
    # p1.creat_2_LinkList_head(item=2)
    # p1.creat_2_LinkList_head(item=3)
    # p1.travel()
    # 列表创建头插法链表
    # l1 = [1, 2, 3]
    # p1 = LinkList()
    # p1.creat_2_LinkList_head(li=l1)
    # p1.travel()

    # 创建尾插法双链表
    # p1 = LinkList()
    # p1.creat_2_LinkList_tail(1)
    # p1.creat_2_LinkList_tail(2)
    # p1.creat_2_LinkList_tail(3)
    # p1.travel()
    # 列表创建尾插法链表
    # l1 = [1, 2, 3]
    # p1 = LinkList()
    # p1.creat_2_LinkList_head(li=l1)
    # p1.travel()

双链表的创建与使用

from LinkList.link_list import *


class creat_double_LinkList:
    def __init__(self):
        # 创建一个空头结点
        self.head = None

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

    def add(self, item):
        """头部插入元素"""
        node = SingeNode(item)
        if self.is_empty():
            # 如果是空链表,将_head指向node
            self.head = node
        else:
            # 将node的next指向_head的头节点
            node.next = self.head
            # 将_head的头节点的prev指向node
            self.head.prev = node
            # 将_head 指向node
            self.head = node

    def travel(self):
        """遍历链表"""
        cur = self.head
        while cur is not None:
            print(cur.item)
            cur = cur.next


if __name__ == '__main__':
    dlk = creat_double_LinkList()
    dlk.add(1)
    dlk.add(2)
    dlk.travel()

class Stack(object):
    """栈"""

    def __init__(self):  # 初始化的时候要生成一个容器,顺序表就是python中的list,然后再执行操作,可将list设成私有的,self.__items = []这样就不能修改原来的list容器
        self.items = []

    def is_empty(self):
        """判断是否为空"""
        return self.items == []  # 右边是一个判断返回True

    # 对于存放的数据结构是顺序表来讲,尾部压栈出栈复杂度为o(1),对于链表来讲,头部复杂度为o(1),所以要考虑
    def push(self, item):  # 从尾部压,从尾部取
        """加入元素"""
        self.items.append(item)

    def pop(self):
        """弹出元素"""
        return self.items.pop()

    def peek(self):
        """返回栈顶元素"""
        return self.items[len(self.items) - 1]

    def size(self):
        """返回栈的大小"""
        return len(self.items)


if __name__ == "__main__":
    stack = Stack()
    # 进栈
    stack.push(1)
    stack.push(2)
    stack.push(3)
    # 打印栈
    print(stack.items)
    # 打印栈的大小
    print(stack.size())
    # 打印栈顶元素
    print(stack.peek())
    # 打印出栈元素
    print(stack.pop())
    print(stack.pop())
    print(stack.pop())

队列

class Queue(object):
    """队列"""

    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(1)
    q.enqueue(2)
    q.enqueue(3)
    # 打印队列
    print(q.items)
    # 打印队列的大小
    print(q.size())
    # 出队
    print(q.dequeue())
    print(q.dequeue())
    print(q.dequeue())

# 树就是链表的扩充,链表有一个element,和next,但是树有两个分支,所以lchild,rchild.
class Node(object):
    """节点类"""

    def __init__(self, elem, lchild=None, rchild=None):
        self.elem = elem
        self.lchild = lchild
        self.rchild = rchild


# 树的创建,创建一个树的类,并给一个root根节点,一开始为空,随后添加节点
class Tree(object):
    """树类"""

    def __init__(self, root=None):
        # 保存一个根节点,可以有,也可以没有,如果有的话说明self.root后面跟着一串数据,然后.append,在这个基础上进行加.如果self.root=None,self.root = node,为树创建第一个节点
        self.root = root

    def add(self, elem):  # 广度优先的添加方式创建的二叉树
        """为树添加节点"""
        node = Node(elem)
        # 如果树是空的,则对根节点赋值,若没有这行,直接走到下面会出错
        if self.root is None:
            self.root = node
        else:
            queue = [self.root]
            # 对已有的节点进行层次遍历
            while queue:  # 判断队列中是否有元素
                # 弹出队列的第一个元素
                cur = queue.pop(0)
                if cur.lchild is None:
                    cur.lchild = node
                    return
                elif cur.rchild is None:
                    cur.rchild = node
                    return
                else:
                    # 如果左右子树都不为空,加入队列继续判断
                    queue.append(cur.lchild)
                    queue.append(cur.rchild)

    # 广度优先遍历(层次遍历)
    def breadth_travel(self):
        """利用队列实现树的层次遍历"""
        if self.root is None:
            return
        queue = [self.root]
        while queue:  # 这个queue最后是要为空的(上面的那么add的queue,由于满足条件就会return,所以不会空)
            node = queue.pop(0)
            print(node.elem)
            if node.lchild is not None:
                queue.append(node.lchild)
            if node.rchild is not None:
                queue.append(node.rchild)

    # 深度优先遍历
    def preoder(self, root):
        """先序遍历:根->左->右"""
        if root is None:
            return
        print(root.elem)
        self.preoder(root.lchild)
        self.preoder(root.rchild)

    def inoder(self, root):
        """中序遍历:左->根->右"""
        if root is None:
            return
        self.inoder(root.lchild)
        print(root.elem)
        self.inoder(root.rchild)

    def postoder(self, root):
        """后序遍历:左->右->根"""
        if root is None:
            return
        self.preoder(root.lchild)
        self.postoder(root.rchild)
        print(root.elem)


if __name__ == '__main__':
    tree = Tree()
    tree.add(1)
    tree.add(2)
    tree.add(3)
    tree.add(4)
    tree.add(5)
    tree.add(6)
    tree.add(7)
    tree.add(8)
    tree.add(9)
    print('层次遍历:')
    tree.breadth_travel()
    print('先序遍历:')
    tree.preoder(tree.root)
    print('中序遍历:')
    tree.inoder(tree.root)
    print('后序遍历:')
    tree.postoder(tree.root)

查找算法

# 递归二分查找
def recursive_binary_search(li, item):
    """"递归法"""
    # 递归的停止条件就是直到分完列表没有元素时
    if len(li) == 0:
        return False
    else:
        # 查找列表中间索引的位置
        midpoint = len(li) // 2
        # 如果查找的值等于中间位置的值,那么就返回True
        if item == li[midpoint]:
            return True
        else:
            # 如果查找的值小于中间位置的值,那么向中间位置的前面查找
            if item < li[midpoint]:
                return recursive_binary_search(li[:midpoint], item)
            else:
                # 如果查找的值大于中间位置的值,那么向中间位置的后面查找
                return recursive_binary_search(li[midpoint + 1:], item)


# 非递归二分查找
def non_recursive_binary_search(li, item):
    """非递归"""
    # 定义一个头指针
    first = 0
    # 定义一个尾指针
    last = len(li) - 1
    while first <= last:
        # 定义一个中间指针
        midpoint = (first + last) // 2
        if item == li[midpoint]:
            return True
        elif item < li[midpoint]:
            # 尾指针到中间指针的前一个位置
            last = midpoint - 1
        else:
            # 头指针到中间指针的后一个位置
            first = midpoint + 1
    return False


if __name__ == '__main__':
    li = [0, 1, 2, 8, 13, 17, 19, 32, 42, ]
    print("递归二分查找法:")
    print(recursive_binary_search(li=li, item=8))
    print(recursive_binary_search(li=li, item=3))
    print("=" * 20)
    print("非递归二分查找法:")
    print(non_recursive_binary_search(li=li, item=8))
    print(non_recursive_binary_search(li=li, item=3))

排序算法

冒泡排序

# 可以将这个算法操作在顺序表上(改变存储位置),也可以操作在链表上(改变node节点)
# 不论list是什么要,O(n)=n^2
def bubble_sort(alist):
    for j in range(len(alist)-1, 0, -1):  # n-1,n-2,,,1
        # j表示每次遍历需要比较的次数,是逐渐减小的
        for i in range(j):
            if alist[i] > alist[i+1]:
                alist[i], alist[i+1] = alist[i+1], alist[i]


li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
bubble_sort(li)
print(li)

选择排序

def selcet_sort(alist):
    for i in range(len(alist) - 1):
        min_num = alist[i]
        for j in range(i + 1, len(alist)):
            if alist[j] < min_num:
                min_num = alist[j]
                alist[i], alist[j] = alist[j], alist[i]

li = [54,26,93,17,77,31,44,55,20]
selcet_sort(li)
print(li)

插入排序

# # #这个想法像选择排序,每次对比选出最大,没有插序的相邻之间对比,向前移
alist = [54, 226, 93, 17, 77, 44, 4, 55, 21]
# 0,   1,  2,  3  4, 5, 6 ,7, 8


def insert_sort1(alist):
    for j in range(1, len(alist)):
        max = alist[j]
        # 先写第一个循化,可以直接用下表list[1],然后再加上外循环,看看j与list[1]下标的关系
        for i in range(0, len(alist)-1, 1):
            if alist[i] > max:
                max = alist[i]
                alist[j], alist[i] = alist[i], alist[j]
    print(alist)


insert_sort1(alist)
print(alist)

# version1插序的相邻之间对比,向前移,用下面的方法


def insert_sort2(alist):
    # 从第二个位置,即下标为1的元素开始向前插入
    for i in range(1, len(alist)):
        # 从第i个元素开始向前比较,如果小于前一个元素,交换位置
        for j in range(i, 0, -1):
            if alist[j] < alist[j-1]:
                alist[j], alist[j-1] = alist[j-1], alist[j]


alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
insert_sort2(alist)
print(alist)


# version2
# 对于上面的用for j in range(i, 0, -1):来控制i,与i-1,i-2的比较,操作比较复杂
# 这里用 while i>0: i-=1 来控制指针向0的方向移动,随着i的变动,每次只比较i与i-1
def insert_sort3(alist):
    # 从第二个位置,即下标为1的元素开始向前插入
    for i in range(1, len(alist)):
        # 从第i个元素开始向前比较,如果小于前一个元素,交换位置
        while i > 0:
            if alist[i] < alist[i-1]:
                alist[i], alist[i-1] = alist[i-1], alist[i]
                i -= 1
            else:
                break


alist = [54, 26, 93, 1711, 77, 31, 44, 55, 20]
insert_sort3(alist)
print(alist)

希尔排序

def shell_sort(alist):
    n = len(alist)
    gap = n//2  # gap=4

    while gap >= 1:  # gap一直变化到1
        for j in range(gap, n):  # for控制的是gap=4时的4个子序列
            i = j
            while i > 0:  # 跟之前插入排序一样,对于一个序列的具体操作,与普通插入的区别就是gap步长
                if alist[i] < alist[i-gap]:
                    alist[i], alist[i-gap] = alist[i-gap], alist[i]
                    i -= gap
                else:
                    break
        gap //= 2  # gap减半


alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
shell_sort(alist)
print(alist)

快速排序

def quick_sort(alist, start, end):
    """快速排序"""

    # 递归的退出条件
    if start >= end:
        return

    # 设定起始元素为要寻找位置的基准元素
    mid = alist[start]

    # low为序列左边的由左向右移动的游标
    low = start

    # high为序列右边的由右向左移动的游标
    high = end

    while low < high:
        # 如果low与high未重合,high指向的元素不比基准元素小,则high向左移动
        # 加=号表示将2个一样的值放到一边,不加的话,最终迭代后也会正确
        while low < high and alist[high] >= mid:
            high -= 1
        # 将high指向的元素放到low的位置上
        alist[low] = alist[high]

        # 如果low与high未重合,low指向的元素比基准元素小,则low向右移动
        while low < high and alist[low] < mid:
            low += 1
        # 将low指向的元素放到high的位置上
        alist[high] = alist[low]

    # 退出循环后,low与high重合,此时所指位置为基准元素的正确位置
    # 将基准元素放到该位置
    alist[low] = mid

    # 对基准元素左边的子序列进行快速排序
    # 这里要保证使用同一个list,这样产生的多个子序列下标是保持不变的,才能恢复成一个list
    quick_sort(alist, start, low-1)

    # 对基准元素右边的子序列进行快速排序
    quick_sort(alist, low+1, end)


alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
quick_sort(alist, 0, len(alist)-1)
print(alist)

归并排序

def merge_sort(alist):
    if len(alist) <= 1:#递归的终止条件 
        return alist
    # 二分分解
    num = len(alist)/2
    left = merge_sort(alist[:num]) 
    right = merge_sort(alist[num:])
    # 合并
    return merge(left,right)

def merge(left, right):
    '''合并操作,将两个有序数组left[]和right[]合并成一个大的有序数组'''
    #left与right的下标指针
    l, r = 0, 0
    result = []
    while l<len(left) and r<len(right):
        if left[l] < right[r]:
            result.append(left[l])
            l += 1
        else:
            result.append(right[r])
            r += 1
    result += left[l:]#当上面的while循环出来时,一个list的元素是取完的,保证将另外一个list余下的元素append
    result += right[r:]
    return result#是一个新list,不再使用之前list下标

alist = [54,26,93,17,77,31,44,55,20]
sorted_alist = mergeSort(alist)
print(sorted_alist)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值