数据结构相关代码(对列、栈、链表、树、排序算法等)

数据结构说明及代码合集

算法:输入 输出 有穷性 确定性 可行性
顺序表:表头信息(容量,个数) 数据区
一体式 分离式
1 栈:栈(有时称为“后进先出栈”)是一个元素的有序集合,其中添加移除新元素总发生在同一端。

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

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

     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)

2 队列:队列是项的有序结合,其中添加新项的一端称为队尾,移除项的一端称为队首

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

    def isEmpty(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)

面试题:如何实现两个队列生成一个栈

q1 = Queue()
q2 = Queue()
alist = [1,2,3,4,5]
#将数据加入队列
for i in alist:
    q1.enqueue(i)
while True:    
    while q1.size() > 1:
        item = q1.dequeue()
        q2.enqueue(item)
    print(q1.dequeue())
    
    q1,q2 = q2,q1
    
    if q1.size() == 0:
        break

队列应用:烫手山芋游戏介绍:6个孩子围城一个圈,排列顺序孩子们自己指定。第一个孩子手里有一个烫手的山芋,需要在计时器计时1秒后将山芋传递给下一个孩子,依次类推。规则是,在计时器每计时7秒时,手里有山芋的孩子退出游戏。该游戏直到剩下一个孩子时结束,最后剩下的孩子获胜。请使用队列实现该游戏策略,排在第几个位置最终会获胜。
分析:为了模拟这个圈,我们可以使用队列。假设游戏开始时,排在队列中的第一个(队首)的孩子手里拿着山芋。游戏开始后,拿着山芋的孩子出队列然后再入队列,将山芋传递给下一个孩子。每当山芋到队首孩子手里后,队首的孩子先出队列再入队 列,一次类推。当传递六次后,手里有山芋的孩子淘汰,游戏继续,继续传递山芋。

from basic.queue import Queue

def hotPotato(namelist, num):
    simqueue = Queue()
    for name in namelist:
        simqueue.enqueue(name)

    while simqueue.size() > 1:
        for i in range(num):
            kid = simqueue.dequeue()
            simqueue.enqueue(kid)

        simqueue.dequeue()

    return simqueue.dequeue()

3 双端队列:概念:deque(也称为双端队列)是与队列类似的项的有序集合。它有两个端部,首部和尾部,并且项在集合中保持不变。

class Deque:
    def __init__(self):
        self.items = []
    def isEmpty(self):
        return self.items == []
    def addFront(self, item):
        self.items.append(item)
    def addRear(self, item):
        self.items.insert(0,item)
    def removeFront(self):
        return self.items.pop()
    def removeRear(self):
        return self.items.pop(0)
    def size(self):
        return len(self.items)

双端队列应用- 回文检测:设计程序,检测一个字符串是否为回文
分析:该问题的解决方案将使用 deque 来存储字符串的字符。我们从左到右处理字符串,并将每个字符添加到 deque 的尾部。在这一点上,deque 像一个普通的队列。然而,我们现在可以利用 deque 的双重功能。 deque 的首部保存字符串的第一个字符,deque 的尾部保存最后一个字符。我们可以直接删除并比较首尾字符,只有当它们匹配时才继续。如果可以持续匹配首尾字符,我们最终要么用完字符,要么留出大小为 1 的deque,取决于原始字符串的长度是偶数还是奇数。在任一情况下,字符串都是回文。

from basic.deque import Deque
def palchecker(aString):
    chardeque = Deque()
    for ch in aString:
        chardeque.addRear(ch)
    stillEqual = True
    while chardeque.size() > 1 and stillEqual:
        first = chardeque.removeFront()
        last = chardeque.removeRear()
        if first != last:
            stillEqual = False
    return stillEqual
print(palchecker("lsdkjfskf"))
print(palchecker("radar"))

内存空间也会有这两个最基本的属性:内存空间大小和内存空间的地址。内存空间的大小可以表示该空间可以存储数据值的大小范围,内存空间的地址(用十六进制数值表示)可以用来通过寻址定位、查找到该内存空间中所存储的数据值。
引用:当一个变量中存储的是某一块内存空间的地址,则该变量即可成为那块内存空间的引用。a=10,a就是10所在内存空间的一个引用。
指向:当一个变量中存储了一块内存空间的地址,则称该变量(引用)指向了那块内存。
不同类型数据占用内存空间的大小:整形(4字节),浮点型(8字节),字符型(1字节)
顺序表:list 和 tuple 弊端:顺序表的结构需要预先知道数据大小来申请连续的存储空间,而在进行扩充时又需要进行数据的搬迁。

4 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是不像顺序表一样连续存储数据,而是每一个结点(数据存储单元)里存放下一个结点的信息(即地址)

# coding=utf-8
# 单向链表

class Node():
    def __init__(self,item):
        self.item = item
        self.next = None
    def __str__(self):
        return str(self.item)
class Link():
    def __init__(self):
        #永远指向链表中第一个节点
        self._head = None
    def isEmpty(self):
        return self._head is None
    def add(self,item):
        node = Node(item)
        node.next = self._head
        self._head = node
    def length(self):
        count = 0
        if self.isEmpty():
            return count
        else:
            cur = self._head
            while cur is not None:
                count += 1
                cur = cur.next
            return count
    def travel(self):
        cur = self._head
        while cur is not None:
            print(cur)
            cur = cur.next
    def append(self,item):
        node = Node(item)
        cur = self._head
        if self.isEmpty():
            self._head = node
        else:
            while cur is not None:
                #因为循环遍历结束后cur会指向空并非最后一个节点
                pre_cur = cur
                cur = cur.next
            pre_cur.next = node   
    def search(self,item):
        ex = False
        cur = self._head
        while cur is not None:
            if cur.item == item:
                ex = True
                break
            cur = cur.next
        return ex
    def insertTo(self,item,index):
        cur = self._head
        ex = 0
        node = Node(item)
        #插入到第一个节点位置
        if index <= 0:
            self.add(item)
        #插入到最后一个节点位置
        elif index >= self.length():
            self.append(item)
        else:
            while cur is not None:
                pre = cur 
                cur = cur.next
                #此处插入的一定不是第一个节点和最后一个节点位置,因此index要减1
                if ex == index-1:
                    node.next = cur
                    pre.next = node
                    break
                ex += 1
    def remove(self,item):
        pre = None
        cur = self._head
        #删除的是第一个节点
        if cur.item == item:
            self._head = cur.next
        else:
            while cur is not None:
                pre = cur
                cur = cur.next
                if cur.item == item:
                    pre.next = cur.next
                    cur.next = None
                cur = cur.next

单向循环链表

# coding=utf-8
class Node:
    """节点"""
    def __init__(self, item):
        self.item = item
        self.next = None
    def __str__(self):
        return str(self.item)
class SinCycLinkedList:
    """单向循环链表"""
    def __init__(self):
        self._head = None
    def is_empty(self):
        """判断链表是否为空"""
        return self._head is None
    def length(self):
        """链表长度"""
        if self.is_empty():
            return 0
        count = 1
        cur = self._head
        while cur.next != self._head:
            # print("cur", cur.item)
            count += 1
            cur = cur.next
        return count
    def travel(self):
        """遍历"""
        if self.is_empty():
            return
        cur = self._head
        print(cur.item)
        while cur.next != self._head:
            cur = cur.next
            print(cur.item)
    def add(self, item):
        """在头部添加一个节点"""
        node = Node(item)
        if self.is_empty():
            self._head = node
            node.next = self._head
        else:
            node.next = self._head
            cur = self._head
            while cur.next != self._head:
                cur = cur.next
            cur.next = node
            self._head = node
    def append(self, item):
        """在尾部添加一个节点"""
        node = Node(item)
        if self.is_empty():
            self._head = node
            node.next = self._head
        else:
            cur = self._head
            # print(type(cur), cur.item, cur.next)
            while cur.next != self._head:
                cur = cur.next
            # print(cur.item)
            cur.next = node
            node.next = self._head
    def insert(self, pos, item):
        """指定位置pos添加节点"""
        if pos <= 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            node = Node(item)
            cur = self._head
            cur_pos = 0
            while cur.next != self._head:
                if (pos - 1) == cur_pos:
                    node.next = cur.next
                    cur.next = node
                    break
                cur_pos += 1
                cur = cur.next
    def remove(self, item):
        """删除一个节点"""
        if self.is_empty():
            return
        pre = self._head
        # 删除首节点
        if pre.item == item:
            cur = pre
            while cur.next != self._head:
                cur = cur.next
            cur.next = pre.next     # 删除首节点(跳过该节点)
            self._head = pre.next   # 重新指定首节点
        # 删除其他的节点
        else:
            cur = pre
            while cur.next != self._head:
                if cur.next.item == item:
                    cur.next = cur.next.next
                cur = cur.next
    def search(self, item):
        """查找节点是否存在"""
        if self.is_empty():
            return -1
        cur_pos = 0
        cur = self._head
        if cur.item == item:
            return cur_pos
        while cur.next != self._head:
            if cur.item == item:
                return cur_pos
            cur_pos += 1
            cur = cur.next
        if cur_pos == self.length() - 1:
            return -1

coding=utf-8

双向链表

class Node:
    """节点"""
    def __init__(self, item):
        self.item = item
        self.prev = None
        self.next = None

class DLinkList:
    """双向链表"""
    def __init__(self):
        self._head = None
    def is_empty(self):
        """判断链表是否为空"""
        return self._head is None
    def length(self):
        """获取链表长度"""
        if self.is_empty():
            return 0
        else:
            cur = self._head
            count = 1
            while cur.next is not None:
                count += 1
                cur = cur.next
            return count
    def travel(self):
        """遍历链表"""
        print("↓↓" * 10)
        if self.is_empty():
            print("")
        else:
            cur = self._head
            print(cur.item)
            while cur.next is not None:
                cur = cur.next
                print(cur.item)
        print("↑↑" * 10)
    def add(self, item):
        """链表头部添加节点"""
        node = Node(item)
        if self.is_empty():
            self._head = node
        else:
            cur = self._head
            node.next = cur
            cur.prev = node
            self._head = node
    def append(self, item):
        """链表尾部添加节点"""
        node = Node(item)
        if self.is_empty():
            self._head = node
        else:
            cur = self._head
            # 遍历找到最后一个节点
            while cur.next is not None:
                cur = cur.next
            # 在尾节点添加新的节点
            cur.next = node
            node.prev = cur
    def insert(self, pos, item):
        """指定位置添加"""
        # 头部添加
        if pos <= 0:
            self.add(item)
        # 尾部添加
        elif pos > (self.length() - 1):
            self.append(item)
        # 其他位置添加
        else:
            node = Node(item)
            cur = self._head
            cur_pos = 0
            while cur.next is not None:
                if cur_pos == (pos - 1):
                    # 与下一个节点互相指向
                    node.next = cur.next
                    cur.next.prev = node
                    # 与上一个节点互相指向
                    cur.next = node
                    node.prev = cur
                cur_pos += 1
                cur = cur.next
    def remove(self, item):
        """删除节点"""
        if self.is_empty():
            return
        else:
            cur = self._head
            # 删除首节点
            if cur.item == item:
                self._head = cur.next
                cur.next.prev = None
            # 删除其他节点
            else:
                while cur.next is not None:
                    if cur.item == item:
                        # 删除之前:1 ←→ [2] ←→ 3
                        # 删除之后:1 ←→ 3
                        cur.prev.next = cur.next
                        cur.next.prev = cur.prev
                    cur = cur.next
                # 删除尾节点
                if cur.item == item:
                    cur.prev.next = None
    def search(self, item):
        """查找节点是否存在"""
        if self.is_empty():
            return -1
        else:
            cur = self._head
            cur_pos = 0
            while cur.next is not None:
                if cur.item == item:
                    return cur_pos

                cur_pos += 1
                cur = cur.next
            if cur_pos == (self.length() - 1):
                return -1

面试题:如何将单链表倒序

def reverse(self):
        if self._head:
            cur = self._head
            pre = None
            cur_next = cur.next
            if cur.next is None:
                return
            while True:
                cur.next = pre
                pre = cur
                cur = cur_next
                if cur == None:
                    self._head = cur
                    break
                cur_next = cur_next.next
            self._head = pre

5顺序查找/搜索
搜索查找(从头到尾)

def sequentialSearch(alist, item):
        pos = 0
        found = False
        while pos < len(alist) and not found:
            if alist[pos] == item:
                found = True
            else:
                pos = pos+1
        return found
testlist = [1, 2, 32, 8, 17, 19, 42, 13, 0]
print(sequentialSearch(testlist, 3))
print(sequentialSearch(testlist, 13))

排序查找(没有就直接强退)

def orderedSequentialSearch(alist, item):
        pos = 0
        found = False
        stop = False
        while pos < len(alist) and not found and not stop:
            if alist[pos] == item:
                found = True
            else:
                if alist[pos] > item:
                    stop = True
                else:
                    pos = pos+1
        return found
testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
print(orderedSequentialSearch(testlist, 3))
print(orderedSequentialSearch(testlist, 13))

二分查找

def binarySearch(alist, item):
        first = 0
        last = len(alist)-1
        found = False
    while first<=last and not found:
            midpoint = (first + last)//2
            if alist[midpoint] == item:
                found = True
            else:
                if item < alist[midpoint]:
                    last = midpoint-1
                else:
                    first = midpoint+1
        return found
testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
print(binarySearch(testlist, 3))
print(binarySearch(testlist, 13))

哈希表:是一种非常容易且便捷就可以定位到某一个具体元素的集合。哈希表的每个位置,通常称为一个槽,每个槽可以容纳一个元素,并且由从 0 开始的整数值命名。

hash函数:元素和元素在hash表中所属的槽之间的映射被称为hash函数
哈希值(元素放的对应位置):使用余除法计算哈希值 h(item) = item%11
当我们要搜索一个元素时,我们只需使用哈希函数来计算该元素的槽名称,然后检查哈希表以查看它是否存在。要求:每个元素映射到哈希表中的位置是唯一的

6排序
1 冒泡排序
#核心:将乱序列表中最大元素排列到列表末尾位置

def m_sort(alist):
    for j in range(0,len(alist)-1):
        if alist[j] > alist[j+1]:
            temp = alist[j]
            alist[j] = alist[j+1]
            alist[j+1] = temp
    return alist

def m_sort_final(alist):
    for i in range(0,len(alist)-1):
        for j in range(0,len(alist)-i-1):
            if alist[j] > alist[j+1]:
                temp = alist[j]
                alist[j] = alist[j+1]
                alist[j+1] = temp
return alist

2 选择排序(改进冒泡,每次只做一次交换)

def selectionSort(alist):
   for i in range(len(alist)-1,0,-1):
       positionOfMax=0
       for location in range(1,i+1):
           if alist[location]>alist[positionOfMax]:
               positionOfMax = location

       temp = alist[i]
       alist[i] = alist[positionOfMax]
       alist[positionOfMax] = temp

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

3 插入排序(gap为1的希尔排序)
主要思想是每次取一个列表元素与列表中已经排序好的列表段进行比较,然后插入从而得到新的排序好的列表段,最终获得排序好的列表。

step_1:
def sort(alist):
    i = 1
    if alist[i] < alist[i-1]:
        alist[i],alist[i-1] = alist[i-1],alist[i]
step_2:
def sort(alist):
    i = 2
    while i > 0:
        if alist[i] < alist[i-1]:
            alist[i],alist[i-1] = alist[i-1],alist[i]
            i -= 1
完整代码:
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

4 希尔排序
该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量(gap)”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率比直接插入排序有较大提高。

step_1:
def sort(alist):
    gap = len(alist) // 2
    #将插入排序当做增量为1的希尔排序
    for i 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

- step_2:
def sort(alist):
    gap = len(alist) // 2
    #将增量设置成gap
    for i 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
- 完整代码:
#继续缩小增量
def sort(alist):
    gap = len(alist) // 2
    while gap >= 1:
        #将增量设置成gap
        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

5 归并排序

6 快速排序
• 将列表中第一个元素设定为基准数字,赋值给mid变量,然后将整个列表中比基准小的数值放在基准的左侧,比基准到的数字放在基准右侧。然后将基准数字左右两侧的序列在根据此方法进行排放。
• 定义两个指针,low指向最左侧,high指向最右侧
• 然后对最右侧指针进行向左移动,移动法则是,如果指针指向的数值比基准小,则将指针指向的数字移动到基准数字原始的位置,否则继续移动指针。
• 如果最右侧指针指向的数值移动到基准位置时,开始移动最左侧指针,将其向右移动,如果该指针指向的数值大于基准则将该数值移动到最右侧指针指向的位置,然后停止移动。
• 如果左右侧指针重复则,将基准放入左右指针重复的位置,则基准左侧为比其小的数值,右侧为比其大的数值。

  • 第一次排序:将将比基准小的排列在基准左侧,比基准大的排列在基准右侧
def sort(alist):
    low = 0
    high = len(alist)-1
    #基准:最左侧的数值
    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
    return alist
  • 完整代码:
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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值