数据结构 + 算法

# a+b+c =1000 a²+b²=c²(abc均为自然数),求出abc的组合

for a in range(0,1001):
    for b in range(0,1001):
        for c in range(0,1001):
            if a + b + c == 1000 and a**2 + b**2 == c ** 2:
                print(a,b,c)


for a in range(0,1001):
    for b in range(0,1001):
        c = 1000 - a - b
        if a + b + c == 1000 and a**2 + b**2 == c**2:
            print(a,b,c) 

a = 5
b = 6
c = 10
n = 10
for i in range(n):
    for j in range(n):
        x = i*i
        y = j*j
        z = i*j
for k in range(n):
    w = a*k +45
    v = b*b
d = 33

#实例化一个空列表 然后将0-1000范围的书添加到列表中 4个方法

def txt1():
    a = []
    for i in range(1000):
        a = a +[ i]
    return a

def text2():
    a = []
    for i in range(1000):
        a.append(i)
    return a

def txt3():
    return [i for i in range(1000)]

def txt4():
    a = list(range(1000))
    return a

from timeit import Timer
if __name__ == '__main__':
    timer = Timer('txt1()','from __main__ import txt1')
    t1 = timer.timeit(1000)
    print(t1)

    timer = Timer('txt2()','from __main__ import txt2')
    t2 = timer.timeit(1000)
    print(t2)

    timer = Timer('txt3()','from __main__ import txt3')
    t3 = timer.timeit(1000)
    print(t3)
    
    timer = Timer('txt4()','from __main__ import txt4')
    t4 = timer.timeit(1000)
    print(t4)
前奏
数据结构:
    如何用两个队列实现一个栈
    单链表
        链表是由节点组成.并且每一个节点对应的内存空间不是连续开辟,可以解决数组,列表插入,删除元素产生的数据迁移
        节点:
            item:储存的是数据
            next:存储的是下一个节点的地址
        链表:
            head:保存的是第一个节点的地址,head的指向一般不会发生改变.要永远指向第一个节点的地址
        cur 当前节点的地址 ,pre前一个节点的地址
    有序链表:排序
    二叉树:
        根节点
        root的引用指向跟节点
        只有两个分叉
        插入节点
    排序二叉树: 插入的节点,依次和原树中的节点对比,小则插入左侧,大则插入右侧
        深度遍历:
            前序:根左右
            中序:左根右 遍历出的就是一个有序的节点
            后序:左右根
算法:
    二分查找:必须是在有序的前提
    选择:
    冒泡:
    插入:
    希尔:插入就是一个增量为1的希尔排序
    快速排序:


使用不同的形式组织数据,在基于查询时的时间复杂程度是不一样的,因此认为算法是为了解决实际问题而设计的,
数据结构是算法需要处理问题的载体
View Code
# ●Stack()创建一个空的新栈。 它不需要参数,并返回-个空栈。
# ●push(item)将一 个新项添加到栈的顶部。它需要item做参数并不返回任何内容。
# ●pop()从栈中删除顶部项。它不需要参数并返回item. 栈被修改.
# ●peek()从栈返回顶部项,但不会删除它。不需要参数。不修改栈。
# ●isEmpty()测试栈是否为空。不需要参数,并返回布尔值。
# ●size()返回栈中的item数量.不需要参数,并返回一个整数。


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

    def push(self,items):
        self.items.append(items)

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

    def peek(self):
        return len(self.items) -1
    
    def isempty(self):
        return self.items ==[]

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

stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)

print(stack.peek())
print(stack.isempty())
print(stack.size())
print(stack.pop())
print(stack.pop())
print(stack.pop())
#先进先出
# ●Queue() 创建-一个空的新队列。它不需要参数,并返回一一个空队列。
# ●enqueue(item) 将新项添加到队尾。它需要 item作为参数,并不返回任何内容。
# ●dequeue() 从队首移除项。它不需要参数并返回item。队列被修改。
# ●isEmpty()查看队列是否为空。它不需要参数,并返回布尔值。
# ●size() 返回队列中的项数。它不需要参数,并返回- -个整数。


class Qenche():
    def __init__(self):
        self.item = []

    def enquene(self,item):
        self.item.insert(0,item)

    def dequen (self):
        return self.item.pop()

    def isEmpty(self):
        return self.item ==[]

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

q = Qenche()
q.enquene(1)
q.enquene(2)
q.enquene(3)
print(q.dequen())
print(q.dequen())
print(q.dequen())


#案例:烫手的山芋
# ■烫手山芋游戏介绍: 6个孩子围城-一个圈, 排列顺序孩子们自己指定。第- -个孩子手里有一一个烫手的山芋,需要在计时器计时1秒后将山芋传递给下-一个孩
# 子,依次类推。规则是,在计时器每计时7秒时,手里有山芋的孩子退出游戏。该游戏直到剩下一一个孩子时结束,最后剩下的孩子获胜。请使用队列实现
# 该游戏策略,排在第几个位置最终会获胜。

Kids = ['A','B','C','D','E','F','G','H','I','J','K']  #多少个人都是第五个人获胜
queue = Qenche()
for kid in Kids:
    queue.enquene(kid)
while queue.size() > 1:
    for i in range(6): #没循环一次 山芋传递一次 手里有山芋的孩子永远在对头位置
        kid = queue.dequen()
        queue.enquene(kid)
    queue.dequen()
print("获胜的选手是",queue.dequen())
队列
# ●Deque()创建一 个空的新deque。 它不需要参数,并返回空的deque.
# ●addFront(item)将一 个新项添加到deque的首部。它需要item参数并不返回任何内容。
# ●addRear(item) 将-个新项添加到deque的尾部。它需要item参数并不返回任何内容。
# ●removeFront() 从deque中删除首项。它不需要参数并返回item。deque被修改。
# ●removeRear() 从deque中删除尾项。它不需要参数并返回item。deque 被修改。
# ●isEmpty()测试deque是否为空。它不需要参数,并返回布尔值。
# ●size()返回deque中的项数。它不需要参数,并返回-一个整数。

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

    def addFront(self,items):
        self.items.insert(0,items)

    def addRear(self,items): 
        self.items.append(items)

    def removeFront(self):
        return self.items.pop()

    def removeRear(self):
        return self.items.pop(0)

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

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


q = Deque()
q.addFront(1)
q.addFront(2)
q.addFront(3)
q.addFront(4)

print(q.removeFront())
print(q.removeFront())  #先进先出
print(q.removeFront())
print(q.removeFront())
print(q.removeRear())       #先进后出
print(q.removeRear())



# ●双端队列应用案例:回文检查
# ■回文是一个字符串,读取首尾相同的字符,例如,radar toot madam。

def ishuiwen(s):
    ex = True
    q = Deque()
    for ch in s:
        q.addFront(ch)
    while q.size() > 1:
        if q.removeFront() != q.removeRear():
            ex = False
            break
        return ex

print(ishuiwen("xxqwreqtgqafafs"))
双端队列
# is_ empty(): 链表是否为空
# length():链表长度
# travel():遍历整个链表
# add(item):链表头部添加元素
# append(item):链表尾部添加元素
# insert(pos, item):指定位置添加元素
# remove(item):删除节点
# search(item):查找节点是否存在




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

class Link():
    def __init__(self):
        #构造出一个空的链表  head存储的只能是空或者一个节点的地址
        self._head = None

    def add(self,item):
        node = Node(item)
        node.next = self._head
        self._head = node 

    # def travel(self):
    #     print(self._head.item)
    #     print(self._head.next.item)

    def travel(self):
        #head在链表创建好之后一定是不可变
        cur = self._head
        while cur:
            print(cur.item)
            cur = cur.next

    def isEmpty(self):
        return self._head ==None

    def size(self):
        cur =  self._head
        count = 0
        while cur:
            count +=1
            cur = cur.next
        return count        
    
    def append(self,item):
        node = Node(item)
        #链表是空的直接添加
        if self._head ==None:
            self._head = node
            return

        cur = self._head
        pre = None
        while cur:
            pre = cur
            cur = cur.next
        pre.next = node

    def  search(self,item):
        find = False
        cur = self._head
        while cur:
            if cur.item:
                find = True
                break
            cur = cur.next
        return find
            
    def insert(self,pos,item):
        node = Node(item)
        pre = None
        cur = self._head
        for k in range(pos):
            pre = cur
            cur = cur.next
        pre.next = node
        node.next = cur

    def remove(self,item):
        cur = self._head
        pre = None
        #
        if cur.item ==item:
            self._head = cur.next
            return

        while cur:
            pre =cur
            cur = cur.next
            if cur.item ==item:
                pre.next = cur.next
                return    

    






link = Link()
link.add(3)
link.add(4)
link.add(5)
link.add(6)
link.add(7)
link.travel()
link.append(8)
link.append(9)
link.search(2,)
print(link.isEmpty())
print(link.size())
print(link.search)
顺序表 和链表
#如何使用两个队列实现一个栈


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

    def enqueue(self,item):
        self.items.insert(0,item)
    
    def dequeue(self):
        return self.items.pop()

    # def tarvel(self):
    #     for item in self.items:
    #         print(item)

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

#如何使用两个队列实现一个栈
alist = [1,2,3,4,5,6,7,8,9]
q1 = Queue()
for i in alist:
    q1.enqueue(i)
q2 = Queue()
while q1.size() > 0:
    #将q1中n-1个值取出来放到q2中
    while q1.size() > 1:
        item = q1.dequeue()
        q2.enqueue(item)
    print(q1.dequeue())

    q1,q2 = q2,q1


# q = Queue()
# q.enqueue(1)
# q.enqueue(2)
# q.enqueue(3)
# q.dequeue()




#如何实现将单链表倒置
class Node():
    def __init__(self,item):
        self.item = item
        self.next = None

class Link():
    def __init__(self):
        self._head = None

    def append(self,item):
        node = Node(item)
        if self._head ==None:
            self._head =node
            return
        cur = self._head
        pre = None

        while cur:
            pre = cur
            cur = cur.next
        pre.next = node
    
    def tarvel(self):
        cur = self._head
        while cur:
            print(cur.item)
            cur = cur.next

    def remove(self,item):
        cur =self._head
        pre = None
        
        if cur.item ==item:
            self._head =cur.next
            return
        while cur:
            pre = cur
            cur = cur.next
            if item == cur.item:
                pre.next = cur.next
                return

    def reverse(self):
        cur = self._head
        pre = None
        next_node = cur.next

        while cur:
            cur.next = pre
            pre = cur
            cur = next_node
            if cur:
                next_node = cur.next
        self._head = pre



Link =Link()
Link.append(1)
Link.append(2)
Link.append(3)
Link.append(4)
Link.append(5)
Link.append(6)
Link.append(7)
Link.remove(1)
Link.tarvel()
试题
#二叉树
    # 根节点
    #     叶子结点
    #         左叶子结点
    #         右叶子结点
    #     树的层级
    #     树的高度
#二叉树的遍历
    # 广度优先
    #     一层一层的进行遍历
    # 深度优先
        #前序:根左右    1245367
        #中序:左跟右    4251637
        #后续:左右根    4526731
#                               1
#                             2   3
#                           4  5  6  7

#二叉树的节点插入

class Node():
    def __init__(self,item):
        self.item = item
        self.left = None
        self.right = None


class Tree():#空树
    def __init__(self):
        self.root = None
    def addNOde(self,item):
        node = Node(item)
        #如果插入第一个节点的情况
        if self.root ==None:
            self.root =node
            return
        cur = self.root  #根节点
        q = [cur]  #列表元素是我们进行遍历判断的节点
        while q:
            newp = q.pop(0)
            if newp.left == None: #如果二叉树左侧节点是空就添加赋值
                newp.left = node
                return
            else:
                q.append(newp.left) #不为空添左节点加到链表当中
            if newp.right ==None: #如果二叉树右侧是空就添加赋值
                newp.right = node
                return
            else:
                q.append(newp.right)#不为空右节点添加到链表当中

    def travel(self):
        cur = self.root
        q = [cur]
        while q:
            nd = q.pop(0)
            print(nd.item)
            if nd.left:
                q.append(nd.left)
            if nd.right:
                q.append(nd.right)

    def forwoar(self,root): #前序 根左右
        if root == None:
            return
        print(root.item)
        self.forwoar(root.left)
        self.forwoar(root.right)

    def middle(self,root):#前序 左根右
        if root == None:
            return
        self.middle(root.left)  
        print(root.item)
        self.middle(root.right)

    def back(self,root): #后续 左右根
        if root == None:
            return
        self.back(root.left)
        self.back(root.right)
        print(root.item)


node = Node(3)
tree= Tree()
tree.addNOde(1)
tree.addNOde(2)
tree.addNOde(3)
tree.addNOde(4)
tree.addNOde(5)
tree.addNOde(6)
tree.addNOde(7)
# tree.travel()
tree.forwoar(tree.root)
tree.middle(tree.root)
tree.back(tree.root)


#二叉树  and 排序 二叉树
    #乱序数据插入的时候 要遵循一个准则:
    #后续插入的数值 如果比根节点小 插入根节点的左侧 否则插入到根节点的右侧

class Nodeto():
    def __init__(self,item):
        self.item = item
        self.left = None
        self.right = None

class SortTree(Tree):
    def __init__(self):
        self.root = None
    
    def add(self,item):
        cur = self.root
        if self.root ==None:
            self.root = node
            return
        while cur:
            #向右侧插入
            if item > cur.item:
                if cur.right ==None:
                    cur.right = node
                    return
                else:
                    cur = cur.right
                #想左插入
            else:
                if cur.left == None:
                    cur.left = node
                    return
                else:
                    cur = cur.left
        

tree = SortTree()
alist = [3,5,6,3,4,2,54,3,4,23,4,3,4,2]
for i in alist:
    tree.add(i)
tree.forwoar(tree.root)
二叉树
# #二分查找
# ●二分查找: -定是基于有序集合的查找
# ■有序列表对于我们的实现搜索是很有用的。在顺序查找中,当我们与第一个元素进行比较时,如果第一 个元素不是我们要查找的,则最多还有n-1个元素
# 需要进行比较。二分查找则是从中间元素开始, 而不是按顺序查找列表。如果该元素 是我们正在寻找的元素,我们就完成了查找。如果它不是, 我们可
# 以使用列表的有序性质来消除剩余元素的一半。如果我们正在查找的元素大于中间元素,就可以消除中间元素以及比中间元素小的一半元素。如果该元素
# 在列表中,肯定在大的那半部分。然后我们可以用大的半部分重复该过程,继续从中间元素开始,将其与我们正在寻找的内容进行比较。


alist = [1,2,3,4,5,6,7,8,9,]

def find(alist,item):
    find = False
    mid = len(alist)  // 2  #中间元素
    first = 0
    last = len(alist) -1 

    while first <= last:
        mid = (first + last) //2
        if alist[mid] < item:  ##去除中间的元素去右侧寻找
            first = mid + 1
        elif alist[mid] > item: 
            last = mid -1
        else:
            find = True
        return find

print(find(alist,5))
二分查找
#冒泡排序

# def sort0(alist):
#     for i in range(len(alist)-1):
#         if alist[i] > alist[i+1]:
#             alist[i],alist[i+1] = alist[i+1],alist[i]
#     return alist


# #主键将乱序的最大值找出防止在乱序列的尾部
# def sort(alist):
#     for j in range(len(alist)-1):
#         for i in range(len(alist)-1-j):
#             if alist[i] > alist[i+1]:
#                 alist[i],alist[i+1] = alist[i+1],alist[i]
#     return alist



# alist = [3,8,7,4,9,2]
# print(sort(alist))


#选择排序


def sort(alist) :
    for j in range(0, len(alist)-1) :
        max_index = 0 #最大值的下标
        for i in range(1, len(alist)-j):
            if alist [max_index] < alist[i]:
                max_index = i
        alist[len(alist)-1-j],alist[max_index] = alist [max_index], alist[len(alist)-1-j]
    return alist

alist = [3,8,7,4,9,2]
print(sort(alist))
冒泡排序
#插入排序

#并有序子集中元案的个数,还可以表示下标
i=1
#alist[iJ乱序子集中的第一个元案
#alist[i-I]有序子集中的最后一个元素
if alist[i] < alist[i-1]:#乱序子集中的第一个元素值小于有序子集中的最后一个元素的值,交赖位置
    alist[i],alist[i-1] = alist[i-1], alist[i]
else:
    pass
i +=1

i = 2
while i > 0 :
    if alist[i] < alist[i-1]:
        alist[i],alist[i-1] = alist[i-1],alist[i]
        i -= 1
    else:
        break

#完整代码
def sort(alist):
    for i in range(1,len(alist)):
        while i > 0:
            if alist[i] < alist[i-1]:
                alist[i],alist[i-1] = alist[i-1],alist[i]
                i -=1
            else:
                break
    return alist

alist = [3,5,6,7,9,1]
print(sort(alist))
插入排序
# -希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本,该方法的基本思想
# 是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量(gap) ”的元素组成的)分别进行直接插入排序,然后依次缩减增量
# 再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。 因为直接插入排序在元素基本有序
# 的情况下(接近最好情况),效率是很高的, 因此希尔排序在时间效率比直接插入排序有较大提高。


# 希尔排序    
#     gap
#         增量值
#         拆分出来的数组      
#   插入排序就是增量为1的希尔排序

def sort(alist) :
    gap = len(alist)//2 #初识gap

    while gap >= 1: 
        for i in range (gap, len(alist)):
            while i > 0:
                if alist[i] < alist[i- gap]:
                    alist[i],alist[i-gap] = alist[i-gap], alist[i]
                    i -= gap
                else:
                    break
        gap //= 2       
    return alist

alist = [2,5,7,9,0,8,6,3]
print(sort(alist))
希尔排序
#快速排序
    # 1.指定一个基数(乱序中的第一个数据值)
    # 2.将比基数小的数据放置在基数的左侧,比基数大的数放在基数的右侧
    # 3.从右边开始偏移hegh
def sort(alist,start,end):
    low = start
    high = end
    #递归结束的条件
    if low > high:
        return
    #基准:最左侧的数值
    mid = alist[low]
    #low和high的关系只能是小于,当等于的时候就要填充mid了
    while low < high:
        while low < high:
            if alist[high] > mid:
                high -= 1
            else:
                alist[low] = alist[high]
                break
        while low < high:
            if alist[low] < mid:
                low += 1
            else:
                alist[high] = alist[low]
                break
        
        #当low和high重复的时候,将mid填充
        if low == high:
            alist[low] = mid #or alist[high] = mid  
            break
    #执行左侧序列
    sort(alist,start,high-1)
    #执行右侧序列
    sort(alist,low+1,end)
    return alist
alist = [6,1,2,7,9,3,4,5,10,8]
print(sort(alist,0,len(alist)-1))
快速排序
def merge_sort(alist):
    n = len(alist)
    #结束递归的条件
    if n <= 1:
        return alist
    #中间索引
    mid = n//2

    left_li = merge_sort(alist[:mid])
    right_li = merge_sort(alist[mid:])

    #指向左右表中第一个元素的指针
    left_pointer,right_pointer = 0,0
    #合并数据对应的列表:该表中存储的为排序后的数据
    result = []
    while left_pointer < len(left_li) and right_pointer < len(right_li):
        #比较最小集合中的元素,将最小元素添加到result列表中
        if left_li[left_pointer] < right_li[right_pointer]:
            result.append(left_li[left_pointer])
            left_pointer += 1
        else:
            result.append(right_li[right_pointer])
            right_pointer += 1
    #当左右表的某一个表的指针偏移到末尾的时候,比较大小结束,将另一张表中的数据(有序)添加到result中
    result += left_li[left_pointer:]
    result += right_li[right_pointer:]

    return result

alist = [3,8,5,7,6]
print(merge_sort(alist))
归并排序

猜你喜欢

转载自www.cnblogs.com/The-Meaning-of-Life111/p/12597508.html