算法学习列表

由于某些机缘巧合的原因,最近重新开始学习算法,学习那二十年前的我最喜欢,而却又抛弃了的东西。虽然现在已不能全心全意埋头苦学,也没有了当年灵光的头脑和意气风发的精神面貌,但却可细水长流,慢慢品尝。岁月就像那深藏的红酒,越品越醇。

 

Reference:

https://www.runoob.com/w3cnote/the-friendship-algorithm-the-big-bang-theory.html

  

一、排序  

  快速排序(Quick Sort):

  通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

def quick_sort(arr):
    if len(arr)<=1:
        return arr
    else:        
        pivot=arr[0]
        less=[i for i in arr[1:] if i<=pivot]
        greater=[i for i in arr[1:] if i>pivot]
        return quick_sort(less)+[pivot]+quick_sort(greater)

 

  归并排序(Merge Sort):

  也叫合并排序,是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

算法步骤:

1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置

3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

4. 重复步骤3直到某一指针达到序列尾

5. 将另一序列剩下的所有元素直接复制到合并序列尾

 

复制代码
def merge_sort(arr):
    if len(arr)<=1:
        return arr
    else:
        mid=len(arr)//2
        left=merge_sort(arr[:mid])
        right=merge_sort(arr[mid:])
        return merge(left,right)
        
        

def merge(a,b):
    x=len(a)
    y=len(b)
    low=0
    high=0
    r=[]
    while low<x and high<y:
        if a[low]<b[high]:
            r.append(a[low])
            low+=1
        else:
            r.append(b[high])
            high+=1
        
    if low==x:
        r=r+b[high:]
        return r
    elif high==y:
        r=r+a[low:]
        return r
    

data=[4,6,9,1,2,7,3,0,5,8]
print("Org:  ", data)
print("Sort: ",merge_sort(data))
复制代码

 

二、二叉树

  遍历:

复制代码
    def preorder_traverse(self, root: TreeNode) -> List[int]:   # 前序遍历(先根遍历)
        def preorder(node: TreeNode):
            if not node:
                return
            r.append(node.val)
            preorder(node.left)
            preorder(node.right)
        
        r = []
        preorder(root)
        return r
        
        
    def inorder_traverse(self, root: Optional[TreeNode]) -> List[int]:  # 中序遍历(中根遍历)
        def inorder(node: TreeNode):
            if not node:
                return
            if node.left:
                t1=inorder(node.left)
                if t1:
                    r.append(t1)
            r.append(node.val)
            if node.right:
                t2=inorder(node.right)
                if t2:
                    r.append(t2)
        r = []
        inorder(root)
        return r


    def postorder_traverse(self, root: Optional[TreeNode]) -> List[int]:  # 后序遍历(后根遍历)
        def postorder(node: TreeNode):
            if not node:
                return
            postorder(node.left)
            postorder(node.right)
            r.append(node.val)
        
        r = []
        postorder(root)
        return r


   def levelOrder_traverse(self, root: Optional[TreeNode]) -> List[List[int]]:  # 层序遍历
        s=[]
        s.append(root)
        r=[]
        while len(s)>0:
            next=[]
            tmp_r=[]
            for i in s:
                if not i:
                    continue
                if i:
                    tmp_r.append(i.val)
                if i.left:
                    next.append(i.left)
                if i.right:
                    next.append(i.right)
            if len(tmp_r)>0:
                r.append(tmp_r)
            s=next
        return r
复制代码

 

 

三、查找搜索

  二分查找(Binary Search):

  首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。 

复制代码
def binarySearch(arr,n):
    print("========== Search %s in %s =========="%(n,arr))
    if arr==None or len(arr)==0: return None

    arrLen=len(arr)
    min=0
    max=arrLen-1
    mid=int(arrLen/2)
    
    while mid>=0 and mid<=arrLen-1:
        pivot=arr[mid]
        if n==pivot:
            return mid
        elif max==0 or min==arrLen-1:
            return None
        elif n<pivot:
            max=mid
            mid=int((min+max)/2)            
        elif n>pivot:
            min=mid
            mid=int((min+max+1)/2)

    return None
复制代码

 

  广度优先搜索(Breadth-First Search,BFS):

  【From】https://www.cnblogs.com/cs-whut/p/11147348.html

  在广度优先搜索算法中,解答树上结点的扩展是按它们在树中的层次进行的。首先生成第一层结点,同时检查目标结点是否在所生成的结点中,如果不在,则将所有的第一层结点逐一扩展,得到第二层结点,并检查第二层结点是否包含目标结点,……,对层次为 n+1 的任一结点进行扩展之前,必须先考虑完层次为 n 的结点的每种可能的状态。因此,对于同一层结点来说,求解问题的价值是相同的,可以按任意顺序来扩展它们。通常采用的原则是先生成的结点先扩展。

       为了便于进行搜索,要设置一个表存储所有的结点。由于在广度优先搜索算法中,要满足先生成的结点先扩展的原则,所以存储结点的表一般采用队列这种数据结构。

       广度优先搜索算法的搜索步骤一般是:

(1)从队列头取出一个结点,检查它按照扩展规则是否能够扩展,如果能则产生一个新结点。

(2)检查新生成的结点,看它是否已在队列中存在,如果新结点已经在队列中出现过,就放弃这个结点,然后回到第(1)步。否则,如果新结点未曾在队列中出现过,则将它加入到队列尾。

(3)检查新结点是否目标结点。如果新结点是目标结点,则搜索成功,程序结束;若新结点不是目标结点,则回到第(1)步,再从队列头取出结点进行扩展。

       最终可能产生两种结果:找到目标结点,或扩展完所有结点而没有找到目标结点。

       如果目标结点存在于解答树的有限层上,广度优先搜索算法一定能保证找到一条通向它的最佳路径,因此广度优先搜索算法特别适用于只需求出最优解的问题。当问题需要给出解的路径,则要保存每个结点的来源,也就是它是从哪一个节点扩展来的。

复制代码
void BFS()
{
    队列初始化;
    初始结点入队;

    while(队列非空)
    {  
          队头元素出队,赋给current;

          while(current 还可以扩展)
          {
              由结点current扩展出新结点new;
              if (new 重复于已有的结点状态) continue;
              new结点入队;

              if (new结点是目标状态)
              {
                置flag = true;
                break;
              }
          }
    }
}
复制代码

 

  深度优先搜索(Depth-First Search,DFS):

  【From】https://www.cnblogs.com/DWVictor/p/10048554.html

  深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法。它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节点,然后从另一条路开始走到底,这种尽量往深处走的概念即是深度优先的概念。

复制代码
/**
 * DFS核心伪代码
 * 前置条件是visit数组全部设置成false
 * @param n 当前开始搜索的节点
 * @param d 当前到达的深度
 * @return 是否有解
 */
bool DFS(Node n, int d){
    if (isEnd(n, d)){//一旦搜索深度到达一个结束状态,就返回true
        return true;
    }
 
    for (Node nextNode in n){//遍历n相邻的节点nextNode
        if (!visit[nextNode]){//
            visit[nextNode] = true;//在下一步搜索中,nextNode不能再次出现
            if (DFS(nextNode, d+1)){//如果搜索出有解
                //做些其他事情,例如记录结果深度等
                return true;
            }
 
            //重新设置成false,因为它有可能出现在下一次搜索的别的路径中
            visit[nextNode] = false;
        }
    }
    return false;//本次搜索无解
}
复制代码

 

posted @   Pekkle  阅读(141)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
历史上的今天:
2017-12-07 有用的 Angular CLI 命令参数
点击右上角即可分享
微信分享提示