数据结构与算法自学网站(快乐学习数据结构)

可视化数据结构与算法

带教程的数据结构操作:
https://visualgo.net/zh
是我最喜欢的网站了,教程也很详细,想自学也可以点击Esc,离开并进入探索模式。并且随着数据图动态变化,旁边还有代码进行配套讲解。也可以自己绘制图表来演示。

旧金山大学David Galles:
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
特别齐全,什么算法都有。并且带插入带删除带排序等所有基本操作。
附加该网站的可视化例子的html+javascript的代码:
https://www.cs.usfca.edu/~galles/visualization/source.html

可按照代码进行步骤演示:
https://algorithm-visualizer.org/backtracking/knights-tour-problem
每一步对应哪一行代码运行都可以显示出来,还可以自己改动代码。用这个网站学完再看不懂代码就离谱。

主打排序算法:
https://www.toptal.com/developers/sorting-algorithms
先点击网页上方的Problem Size,选择一个尺寸,20,30,40还是50,都行,于是你就可以看到下面整个大表中有图片显示出来了。

  • 列。代表每一个排序算法。从左到右依次为:插入、选择、冒泡、Shell、合并Merge、堆排序、快排、快排3。
    单击每个算法的链接,你可以看到这个算法的详细解释,其中包括:算法的伪代码、算法的复杂度、相关的讨论、重点、及该算法的相关参考文档。
  • 行。不同的数据样本。从上到下依次为:随机样本、几乎排好序的样本、最差的样本(反序)、有一些相同项的样本。
    这些样本在不同的算法上都会有不同的表现。
  • 单元格。每个单元格都是一个图片。用鼠标单击图片,可以动画地演示算法整个过程。其中两个小红箭头表示了正在需要“交换顺序的数据”。

贼酷炫的排序算法:
http://sorting.at/
UI帅到没话说。但功能相比就很少了。

寻路算法可视化:
http://qiao.github.io/PathFinding.js/visual/
选择寻路算法与限制条件(还可以设置障碍墙),可以看这个算法寻路的可视化步骤。

一个个人博客:
https://bost.ocks.org/mike/algorithms/
里面着重讲算法(采样,随机乱序,排序,迷宫)的意义及优劣点,逐步深入,作者讲的很细

一个显示排序过程的python脚本:
学排序算法有点麻烦,但是这个python脚本写的真好

(需要 Cairo图片库支持)

#!/usr/bin/env python
"""
    Some of these algorithms are all rather literally from Knuth - as a
    consequence they're not very Pythonic, and not terribly readable.

    In some cases I've modified the algorithm to make sure that all items are
    present once and only once in the array of sortables every time we
    memoizePath (i.e. that the algorithm is in-place). 
    
    Page numbers refer to The Art of Computer Programming vol. 3.

    This code is in the public domain - do whatever you like with it.
"""
import random, math, sys
from optparse import OptionParser
import cairo

def intRGB(r, g, b):
        return (r/255.0, g/255.0, b/255.0)

HIGHLIGHT=intRGB(0xff, 0x72, 0x72)

class NiceCtx(cairo.Context):
    defaultBorderColour = intRGB(0x7d, 0x7d, 0x7d)
    def stroke_border(self, border):
        src = self.get_source()
        width = self.get_line_width()
        self.set_source_rgba(*self.defaultBorderColour)
        self.stroke_preserve()
        self.set_source(src)
        self.set_line_width(width - (border * 2))
        self.stroke()


class Canvas:
    def __init__(self, width, height):
        self.width, self.height = width, height
        self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
        self.background(1, 1, 1)

    def ctx(self):
        return NiceCtx(self.surface)

    def background(self, r, g, b):
        c = self.ctx()
        c.set_source_rgb(r, g, b)
        c.rectangle(0, 0, self.width, self.height)
        c.fill()
        c.stroke()

    def save(self, fname):
        self.surface.write_to_png(fname)
            

class Sortable:
    def __init__(self, i):
        self.i = i
        self.path = []

    def __cmp__(self, other):
        return cmp(self.i, other.i)

    def __repr__(self):
        return str(self.i)


class TrackList:
    def __init__(self, itms):
        self.lst = [Sortable(i) for i in itms]

    def __getattr__(self, attr):
        return getattr(self.lst, attr)
    
    def memoizePath(self):
        for i, v in enumerate(self):
            v.path.append(i)
    

class PathDrawer:
    def __init__(self, width, height, line, border, highlights, prefix):
        self.width, self.height = width, height
        self.line, self.border = line, border
        self.highlights, self.prefix = highlights, prefix

    def _lineCoords(self, elem, l):
        init = 0.02 # Proportional initial length 
        lst = []
        xscale = (1.0-init)/len(elem.path)
        yscale = 1.0/l
        lst.append((0, yscale/2 + (yscale * elem.path[0])))
        lst.append((init, yscale/2 + (yscale * elem.path[0])))
        for i, v in enumerate(elem.path):
            lst.append(((xscale * i) + init, yscale/2 + (yscale * v)))
        lst.append((1, lst[-1][1]))
        return lst

    def draw(self, algo):
        c = Canvas(self.width, self.height)
        # Clearer when drawn in this order
        l = reversed(algo.lst)
        ctx = c.ctx()
        for elem in l:
            for i in self._lineCoords(elem, len(algo.lst)):
                ctx.line_to(self.width * i[0], self.height * i[1])
            ctx.set_line_cap(cairo.LINE_CAP_BUTT)
            ctx.set_line_join(cairo.LINE_JOIN_ROUND)
            if elem.i in self.highlights:
                ctx.set_source_rgb(*HIGHLIGHT)
            else:
                x = 1 - (float(elem.i)/len(algo.lst)*0.7)
                ctx.set_source_rgb(x, x, x)
            ctx.set_antialias(cairo.ANTIALIAS_SUBPIXEL)
            ctx.set_line_width(self.line)
            ctx.stroke_border(self.border)
        c.save("%s%s.png"%(self.prefix, algo.name))


class Algorithm:
    def __init__(self, entries):
        self.name = self.__class__.__name__
        self.lst = TrackList(entries)
        self.lst.memoizePath()
        self.sort(self.lst)


class Bubble(Algorithm):
    def sort(self, lst):
        bound = len(lst)-1
        while 1:
            t = 0
            for j in range(bound):
                if lst[j] > lst[j+1]:
                    lst[j], lst[j+1] = lst[j+1], lst[j]
                    lst.memoizePath()
                    t = j
            if t == 0:
                break
            bound = t
    

class ListInsertion(Algorithm):
    """
        Broadly based on the list insertion sort on p 97.  
    """
    def sort(self, lst):
        for i in range(1, len(lst)):
            for j in range(i):
                if lst[i] < lst[j]:
                    x = lst.pop(i)
                    lst.insert(j, x)
                    lst.memoizePath()


class Shell(Algorithm):
    """
        Shell's method, p. 84
    """
    def sort(self, lst):
        t = [5, 3, 1]
        for h in t:
            for j in range(h, len(lst)):
                i = j - h
                r = lst[j]
                flag = 0
                while i > -1:
                    if r < lst[i]:
                        flag = 1
                        lst[i+h], lst[i] = lst[i], lst[i+h]
                        i -= h
                        lst.memoizePath()
                    else:
                        break
                lst[i+h] = r


class Selection(Algorithm):
    """
        Selection Sort, p. 139
    """
    def sort(self, lst):
        for j in range(len(lst)-1, 0, -1):
            m = lst.index(max(lst[:j]))  # No, this is not efficient ;)
            lst[m], lst[j] = lst[j], lst[m]
            lst.memoizePath()


class Heap(Algorithm):
    """
        Algorithm from http://en.wikipedia.org/wiki/Heapsort
    """
    def sift(self, lst, start, count):
        root = start
        while (root * 2) + 1 < count:
            child = (root * 2) + 1
            if child < (count-1) and lst[child] < lst[child+1]:
                child += 1
            if lst[root] < lst[child]:
                lst[root], lst[child] = lst[child], lst[root]
                lst.memoizePath()
                root = child
            else:
                return

    def sort(self, lst):
        start = (len(lst)/2)-1
        end = len(lst)-1
        while start >= 0:
            self.sift(lst, start, len(lst))
            start -= 1
        while end > 0:
            lst[end], lst[0] = lst[0], lst[end]
            lst.memoizePath()
            self.sift(lst, 0, end)
            end -= 1


class Quick(Algorithm):
    """
        http://www.cs.indiana.edu/classes/a348-dger/lectures/tsort/1.0.2/QSortAlgorithm.java
    """
    def sort(self, lst, left=0, right=None):
        if right is None:
            right = len(lst) - 1
        l = left
        r = right
        if l <= r:
            mid = lst[(left+right)/2]
            while l <= r:
                while l <= right and lst[l] < mid:
                    l += 1
                while r > left and lst[r] > mid:
                    r -= 1
                if l <= r:
                    lst[l], lst[r] = lst[r], lst[l]
                    lst.memoizePath()
                    l+=1
                    r-=1
            if left < r:
                self.sort(lst, left, r)
            if l < right:
                self.sort(lst, l, right)



def main():
    usage = "usage: %prog [options]"
    parser = OptionParser(usage)
    parser.add_option(
        "-a",
        dest="algorithm",
        default=False,
        type="choice",
        choices=["quick", "heap", "selection", "insertion", "bubble", "shell"],
        help="Draw only a named algorithm."
    )
    parser.add_option(
        "-n",
        dest="numelements",
        default="20",
        type="int",
        help="Generate a random sorting sequence of length n"
    )
    parser.add_option(
        "-f",
        dest="readfile",
        help="Read data from file"
    )
    parser.add_option(
        "-p",
        dest="prefix",
        help="File name prefix.",
        default=""
    )
    parser.add_option(
        "-d",
        dest="dump",
        default=False,
        action="store_true",
        help="Dump sequence"
    )
    parser.add_option(
        "-x",
        dest="width",
        type="int",
        default=700,
        help="Image width"
    )
    parser.add_option(
        "-y",
        dest="height",
        type="int",
        default=300,
        help="Image height"
    )
    parser.add_option(
        "-l",
        dest="line",
        type="int",
        default=6,
        help="Total line width"
    )
    parser.add_option(
        "-b",
        dest="border",
        type="int",
        default=1,
        help="Border width"
    )
    parser.add_option(
        "-i",
        dest="highlight",
        type="int",
        default=[],
        action="append",
        help="Highlight digit N (0-based). Can be passed muiltiple times."
    )
    options, args = parser.parse_args()
    if args:
        parser.error("Script takes no arguments.")
    if options.readfile:
        txt = file(options.readfile).read().split()
        lst = [int(i) for i in txt]
    else:
        lst = range(options.numelements)
        random.shuffle(lst)
    if options.highlight:
        if max(options.highlight) > (len(lst)-1):
            parser.error("Highlight element > than list length.")
    if options.dump:
        for i in lst:
            print i,
    ldrawer = PathDrawer(
        options.width,
        options.height,
        options.line,
        options.border,
        options.highlight,
        options.prefix
    )
    for i in [Quick, Heap, Selection, ListInsertion, Bubble, Shell]:
        name = i.__name__
        if options.algorithm:
            if not options.algorithm.lower() == name.lower():
                continue
        print >> sys.stderr, name
        a = i(lst)
        ldrawer.draw(a)


if __name__ == "__main__":
    main()

图片示例:(选择排序)
在这里插入图片描述

  • 折线表示了各个元素的位置变化。
  • 折线的深浅表示了元素的大小。越深则越大

脚本参数:

-a 表示使用什么样的算法,取值为"quick", "heap", "selection", "insertion", "bubble", "shell"-n 表示要排序的数据个数。
-f 表示输入文件。
-p 表示文件前缀。
-d 表示输出顺序。
-x 图片宽度。
-y 图片高度。
-l 所有线的宽度。
-b 边界宽度。

使用示例:

./visualise.py -l 6 -x 700 -y 300 -n 15

正则表达式可视化:
http://www.regexper.com/
悄悄混入
https://www.debuggex.com/
偷偷混入

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值