Skip to content

Commit 3c96ed8

Browse files
Merge pull request #197 from email2liyang/master
Scala Project for algo
2 parents 418e025 + f5aeb9a commit 3c96ed8

29 files changed

+1395
-5
lines changed

scala/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
target/

scala/build.sbt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
lazy val root = (project in file("."))
2+
.settings(
3+
name := "algo-scala",
4+
version := "1.0",
5+
scalaVersion := "2.12.8",
6+
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.5" % "test"
7+
)

scala/project/build.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sbt.version=1.2.1
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package ch05_array
2+
3+
class ArrayDemo(capacity: Int) {
4+
5+
var data: Array[Char] = new Array[Char](capacity)
6+
var length: Int = 0
7+
8+
def find(index: Int): Char = {
9+
if (index < 0 || index > length) {
10+
return 0.toChar
11+
}
12+
data(index)
13+
}
14+
15+
def insert(index: Int, value: Char): Boolean = {
16+
if (length == capacity) {
17+
return false
18+
}
19+
20+
if (index < 0 || index >= capacity) {
21+
return false
22+
}
23+
24+
for (i <- length until index by -1) {
25+
data(i) = data(i - 1)
26+
}
27+
data(index) = value
28+
length += 1
29+
30+
true
31+
}
32+
33+
def delete(index: Int): Char = {
34+
if (length == 0) {
35+
throw new IllegalStateException("array is empty")
36+
}
37+
if (index >= length) {
38+
throw new IllegalStateException("index out of range, current data length is " + length)
39+
}
40+
val result = data(index)
41+
for (i <- index until length-1) {
42+
data(i) = data(i + 1)
43+
}
44+
45+
length -= 1
46+
result
47+
}
48+
49+
def print: String = {
50+
data.subSequence(0, length).toString
51+
}
52+
53+
}
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
package ch06_linkedlist
2+
3+
import scala.util.control.Breaks._
4+
5+
// the model class for the linked list
6+
class Node(var data: Int, var next: Option[Node])
7+
8+
class SinglyLinkedList(var headOpt: Option[Node]) {
9+
10+
//define constructor without param
11+
def this() = this(None)
12+
13+
14+
def findByValue(value: Int): Option[Node] = {
15+
headOpt.flatMap(head => {
16+
var node = head
17+
while (!node.data.equals(value) && node.next.isDefined) {
18+
node = node.next.get
19+
}
20+
21+
if (node.data.equals(value)) {
22+
return Some(node)
23+
} else {
24+
//arrive the end of the chain
25+
return None
26+
}
27+
})
28+
}
29+
30+
def insertToHead(value: Int): Unit = {
31+
val newNode = new Node(value, None)
32+
insertToHead(newNode)
33+
}
34+
35+
def insertToHead(newNode: Node): Unit = {
36+
headOpt match {
37+
case None =>
38+
//it's an empty linked list, make new node as head
39+
headOpt = Some(newNode)
40+
case Some(head) =>
41+
newNode.next = Some(head)
42+
headOpt = Some(newNode)
43+
}
44+
}
45+
46+
def insertTail(value: Int): Unit = {
47+
val newNode = new Node(value, None)
48+
insertTail(newNode)
49+
}
50+
51+
def insertTail(newNode: Node): Unit = {
52+
headOpt match {
53+
case None =>
54+
//it's an empty linked list, make new node as head
55+
headOpt = Some(newNode)
56+
case Some(head) =>
57+
//need to start to find from head to current tail
58+
var node = head
59+
while (node.next.isDefined) {
60+
node = node.next.get
61+
}
62+
//now node is the tail as node.next is None
63+
//add new tail
64+
node.next = Some(newNode)
65+
}
66+
}
67+
68+
def insertAfter(existNode: Node, value: Int): Unit = {
69+
val newNode = new Node(value, None)
70+
insertAfter(existNode, newNode)
71+
}
72+
73+
def insertAfter(existNode: Node, newNode: Node): Unit = {
74+
existNode.next match {
75+
case None =>
76+
//exist node is tail
77+
newNode.next = None
78+
existNode.next = Some(newNode)
79+
case Some(next) =>
80+
newNode.next = Some(next)
81+
existNode.next = Some(newNode)
82+
}
83+
}
84+
85+
def insertBefore(existNode: Node, value: Int): Unit = {
86+
val newNode = new Node(value, None)
87+
insertBefore(existNode, newNode)
88+
}
89+
90+
def insertBefore(existNode: Node, newNode: Node): Unit = {
91+
headOpt match {
92+
case None =>
93+
throw new IllegalStateException("head node should not be None")
94+
case Some(head) =>
95+
if (existNode.equals(head)) {
96+
insertToHead(newNode)
97+
}
98+
var node = head
99+
while (node.next.isDefined && !node.next.get.equals(existNode)) {
100+
node = node.next.get
101+
}
102+
103+
if (node.next.isEmpty) {
104+
throw new IllegalArgumentException("existNode " + existNode + " does not exist in this chain")
105+
}
106+
107+
newNode.next = node.next
108+
node.next = Some(newNode)
109+
}
110+
}
111+
112+
def deleteByNode(node: Node): Unit = {
113+
headOpt.map(head => {
114+
if (head.equals(node)) {
115+
//deleting head
116+
headOpt = node.next
117+
} else {
118+
var p: Node = head
119+
while (p.next.isDefined && !p.next.get.equals(node)) {
120+
p = p.next.get
121+
}
122+
123+
if (p.next.isEmpty) {
124+
throw new IllegalArgumentException("could not find given node")
125+
}
126+
p.next = node.next
127+
}
128+
129+
})
130+
}
131+
132+
//inverse the link from given node to head
133+
def inverseLink(node: Node): Node = {
134+
if (headOpt.isEmpty) {
135+
throw new IllegalArgumentException("list is empty")
136+
}
137+
138+
var pre: Option[Node] = None
139+
var next: Option[Node] = None
140+
var current: Option[Node] = headOpt
141+
142+
while (current.isDefined && !current.get.equals(node)) {
143+
next = current.get.next
144+
current.get.next = pre
145+
146+
pre = current
147+
current = next
148+
}
149+
150+
current.get.next = pre
151+
152+
current.get
153+
154+
}
155+
156+
def isPalindrome(): Boolean = {
157+
headOpt match {
158+
case None => false
159+
case Some(head) =>
160+
var p: Node = head
161+
var q: Node = head
162+
163+
if (p.next.isEmpty) {
164+
//we only got 1 element in the chain
165+
return true
166+
}
167+
168+
//start to find middle of the chain
169+
while (q.next.isDefined && q.next.get.next.isDefined) {
170+
p = p.next.get
171+
q = q.next.get.next.get
172+
}
173+
var leftLink: Option[Node] = None
174+
var rightLink: Option[Node] = None
175+
q.next match {
176+
case None =>
177+
//p is in the middle of an odd numbers of chain
178+
rightLink = p.next
179+
leftLink = inverseLink(p).next
180+
case Some(_) =>
181+
//p and p.next is in the middle of the even numbers of chain
182+
rightLink = p.next
183+
leftLink = Some(inverseLink(p))
184+
}
185+
186+
compareLinkedNodes(leftLink, rightLink)
187+
}
188+
}
189+
190+
def compareLinkedNodes(leftLink: Option[Node], rightLink: Option[Node]): Boolean = {
191+
var left = leftLink
192+
var right = rightLink
193+
194+
breakable {
195+
while (left.isDefined && right.isDefined) {
196+
if (!left.get.data.equals(right.get.data)) {
197+
break
198+
}
199+
left = left.get.next
200+
right = right.get.next
201+
}
202+
}
203+
//make sure we have loop until the end of the chain
204+
left.isEmpty && right.isEmpty
205+
}
206+
207+
def mkString(): String = {
208+
headOpt.map(head => {
209+
var node = head
210+
val result = new StringBuilder
211+
212+
while (node.next.isDefined) {
213+
result.append(node.data)
214+
node = node.next.get
215+
}
216+
result.append(node.data)
217+
218+
result.mkString
219+
}).getOrElse("")
220+
}
221+
222+
}

0 commit comments

Comments
 (0)