Scala数据结构和算法:数据结构(算法)介绍,稀疏数组,一个五子棋程序保存代码

数据结构(算法)的介绍

数据结构的介绍
数据结构是一门研究算法的学科,只从有了编程语言也就有了数据结构.学好数据结构可以编写出更加漂亮,更加有效率的代码。

要学习好数据结构就要多多考虑如何将生活中遇到的问题,用程序去实现解决.

程序 = 数据结构 + 算法

数据结构(数组,队列,栈,链表,树,图)和算法的关系
算法是程序的灵魂,为什么有些网站能够在高并发,和海量吞吐情况下依然坚如磐石,大家可能会说: 网站使用了服务器群集技术、数据库读写分离和缓存技术(比如Redis等),那如果我再深入的问一句,这些优化技术又是怎样被那些天才的技术高手设计出来的呢?

大家请思考一个问题,是什么让不同的人写出的代码从功能看是一样的,但从效率上却有天壤之别, 拿在公司工作的实际经历来说, 我是做服务器的,环境是UNIX,功能是要支持上千万人同时在线,并保证数据传输的稳定, 在服务器上线前,做内测,一切OK,可上线后,服务器就支撑不住了, 公司的CTO对我的代码进行优化,再次上线,坚如磐石。那一瞬间,我认识到程序是有灵魂的,就是算法。如果你不想永远都是代码工人,那就花时间来研究下算法吧!
本章着重讲解算法 的基石-数据结构。

看几个实际编程中遇到的问题
Scala代码:

def main(args: Array[String]): Unit = {
		val str = "scala,scala, hello,world!"
		val newStr = str.replaceAll("scala", "尚硅谷")
		println("newStr=" + newStr) //暴力匹配=>KMP算法
   }

在这里插入图片描述
看几个实际编程中遇到的问题
一个五子棋程序:
Scala数据结构和算法:数据结构(算法)介绍,稀疏数组,一个五子棋程序保存代码_第1张图片
?如何判断游戏的输赢,并可以完成存盘退出和继续上局的功能

约瑟夫问题(丢手帕问题)
Josephu 问题

Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
提示:用一个不带头结点的循环链表来处理Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束。

其它常见算法问题:

Scala数据结构和算法:数据结构(算法)介绍,稀疏数组,一个五子棋程序保存代码_第2张图片
邮差问题
最短路径问题
汉诺塔
八皇后问题
Scala数据结构和算法:数据结构(算法)介绍,稀疏数组,一个五子棋程序保存代码_第3张图片

稀疏sparsearray数组

先看一个实际的需求

编写的五子棋程序中,有存盘退出和续上盘的功能。

Scala数据结构和算法:数据结构(算法)介绍,稀疏数组,一个五子棋程序保存代码_第4张图片

分析问题:
因为该二维数组的很多值是默认值0, 因此记录了很多没有意义的数据.->稀疏数组。

稀疏数组

基本介绍

当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。

稀疏数组的处理方法是:
记录数组一共有几行几列,有多少个不同的值(有效值的个数)
把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模
Scala数据结构和算法:数据结构(算法)介绍,稀疏数组,一个五子棋程序保存代码_第5张图片
应用实例
使用稀疏数组,来保留类似前面的二维数组(棋盘、地图等等)
把稀疏数组存盘,并且可以重新恢复原来的二维数组数
整体思路分析
Scala数据结构和算法:数据结构(算法)介绍,稀疏数组,一个五子棋程序保存代码_第6张图片

代码实现

package datastructure

import scala.collection.mutable.ArrayBuffer

/**
  * @author cherry
  * @create 2019-09-16-22:33
  */
object SparseArrayDemo {
  def main(args: Array[String]): Unit = {
    //先使用二维数据,映射棋盘
    val rows = 11 //棋盘行数
    val cols = 11 //列数
    val chessMap: Array[Array[Int]] = Array.ofDim[Int](rows, cols)
    //初始化
    chessMap(1)(2) = 1 //表示黑子
    chessMap(2)(3) = 2 //表示蓝子
    println("原始的棋盘")
    for (row <- chessMap) {
      for (item <- row) {
        printf("%d ", item)
      }
      //换行
      println()
    }

    /**
      * 对原始的二维数据进行压缩
      * 思路:
      * 1.创建一个ArrayBufffer,可以动态添加数据
      * 2.使用Node对象,表示一行数据
      */
    val sparseArray: ArrayBuffer[Node] = ArrayBuffer()
    //先将第一行数据放入
    sparseArray.append(new Node(rows, cols, 0))
    //遍历chessMap,如果发现有非0的值,创建一个Node对象,并加入到spareArray
    for (i <- 0 until chessMap.length) {
      for (j <- 0 until chessMap(i).length) {
        if (chessMap(i)(j) != 0) {
          //有效数据需要保存
          sparseArray.append(new Node(i, j, chessMap(i)(j)))
        }
      }
    }
    println("稀疏数组的情况是:")
    for (i <- 0 until sparseArray.length) {
      val node: Node = sparseArray(i)
      printf("%d %d %d\n", node.row, node.col, node.value)
    }

    /**
      * 将悉数数组恢复到原盘
      * 思路:
      * 1.读取稀疏数组的第一行,创建一个二维棋盘
      * 2.遍历(从悉数数组的第二行),每读取到一个node,就将对应的值恢复到chessMap2
      */
    val node: Node = sparseArray(0)
    val chessMap2: Array[Array[Int]] = Array.ofDim[Int](node.row, node.col)
    for (i <- 1 until sparseArray.length) {
      val node2: Node = sparseArray(i)
      chessMap2(node2.row)(node2.col) = node2.value
    }
    println("恢复的棋盘")
    for (row <- chessMap2) {
      for (item <- row) {
        printf("%d ", item)
      }
      //换行
      println()
    }
  }

}

class Node(val row: Int, val col: Int, val value: Int)

控制台打印结果
Scala数据结构和算法:数据结构(算法)介绍,稀疏数组,一个五子棋程序保存代码_第7张图片

你可能感兴趣的:(Scala,#,Scala数据结构)