-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A Swift Stack class implemented by an internal Swift single linked list class
- Loading branch information
0 parents
commit 2b49123
Showing
10 changed files
with
422 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
//import Cocoa | ||
|
||
var str = "Hello, playground" | ||
|
||
typealias CStackInt = CStack<Int> | ||
|
||
let testStack : CStackInt = CStackInt() | ||
|
||
testStack.Push(value: 1) | ||
testStack.Push(value: 2) | ||
testStack.Push(value: 3) | ||
testStack.Push(value: 4) | ||
testStack.Push(value: 5) | ||
testStack.Push(value: 6) | ||
testStack.Push(value: 7) | ||
testStack.Push(value: 8) | ||
|
||
while testStack.Empty() == false { | ||
let v = testStack.Peek() | ||
print(v ?? "v is nil") | ||
let v2 = testStack.Pop() | ||
print(v2 ?? "v2 is nil") | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
// | ||
// CSingleLList.swift | ||
// LinkList | ||
// | ||
// Created by Zhaohui Xing on 10/26/18. | ||
// Copyright © 2018 Zhaohui Xing. All rights reserved. | ||
// | ||
import Foundation | ||
|
||
//class base sll as reference type | ||
public class CSingleLinkedList<T : Equatable> { //Equatable for ! operator in line#60 | ||
var m_Head: CSingleLinkedListNode<T>? | ||
var m_Tail: CSingleLinkedListNode<T>? | ||
|
||
init() { | ||
} | ||
|
||
public init(head: CSingleLinkedListNode<T>) { | ||
self.m_Head = head | ||
self.m_Tail = self.m_Head?.tail | ||
} | ||
} | ||
|
||
extension CSingleLinkedList { | ||
public var head : CSingleLinkedListNode<T>? { | ||
get { | ||
return m_Head | ||
} | ||
set (newNode) { | ||
m_Head = newNode; | ||
m_Tail = newNode?.tail | ||
} | ||
} | ||
} | ||
|
||
extension CSingleLinkedList { | ||
public var tail : CSingleLinkedListNode<T>? { | ||
return m_Tail | ||
} | ||
} | ||
|
||
extension CSingleLinkedList { | ||
public var count : Int { | ||
var nCount : Int = 0 | ||
var cur : CSingleLinkedListNode<T>? = m_Head | ||
|
||
while cur != nil { | ||
cur = cur?.next | ||
nCount += 1 | ||
} | ||
|
||
return nCount | ||
} | ||
} | ||
|
||
extension CSingleLinkedList { | ||
public subscript (value : T) -> CSingleLinkedListNode<T>? { | ||
var cur : CSingleLinkedListNode<T>? = m_Head | ||
|
||
while cur != nil && cur!.data != value { | ||
cur = cur?.next | ||
} | ||
|
||
return cur | ||
} | ||
} | ||
|
||
extension CSingleLinkedList { | ||
public func reverse() { | ||
let prev : CSingleLinkedListNode<T>? = CSingleLinkedListNode<T>(); //This avoid the tail node is nil and while loop cannot go through all nodes | ||
prev?.next = m_Head //prev.next as temperory head shifting cursor | ||
let cur : CSingleLinkedListNode<T>? = m_Head //Using cur.next as moving cursor, Note: this approach the orginal head's next is altered after the loop | ||
|
||
while cur?.next != nil { | ||
let temp: CSingleLinkedListNode<T>? = cur?.next | ||
cur?.next = temp?.next; | ||
temp?.next = prev?.next | ||
prev?.next = temp | ||
} | ||
m_Head = prev?.next | ||
} | ||
} | ||
|
||
extension CSingleLinkedList { | ||
public func reverse2() { | ||
let prev : CSingleLinkedListNode<T>? = CSingleLinkedListNode<T>(); //This avoid the tail node is nil and while loop cannot go through all nodes | ||
prev?.next = m_Head //prev.next as temperory head shifting cursor | ||
var cur : CSingleLinkedListNode<T>? = m_Head?.next //Using cur as moving cursor | ||
|
||
while cur != nil { | ||
let temp: CSingleLinkedListNode<T>? = cur | ||
cur = temp?.next; | ||
temp?.next = prev?.next | ||
prev?.next = temp | ||
} | ||
m_Head?.next = nil; //This one need this call, since using cur as moving cursor and orginal head.next is not altered | ||
m_Head = prev?.next | ||
} | ||
} | ||
|
||
extension CSingleLinkedList { | ||
public func iscycled()->(retFlag : Bool, cycleNode:CSingleLinkedListNode<T>?, tailNode:CSingleLinkedListNode<T>?) { | ||
var bRet : (retFlag : Bool, cycleNode:CSingleLinkedListNode<T>?, tailNode:CSingleLinkedListNode<T>?) = (false, nil, nil) | ||
|
||
if m_Head != nil { | ||
bRet = m_Head!.iscycled() | ||
} | ||
|
||
return bRet | ||
} | ||
} | ||
|
||
extension CSingleLinkedList { | ||
public func AddHead(head: CSingleLinkedListNode<T>) { | ||
head.next = m_Head; | ||
m_Head = head; | ||
} | ||
} | ||
|
||
extension CSingleLinkedList { | ||
public func RemoveHead() { | ||
m_Head = m_Head?.next; | ||
} | ||
} | ||
|
||
extension CSingleLinkedList { | ||
public func reverseBetween(start startIndex: Int, end endIndex: Int) { | ||
if endIndex <= startIndex { | ||
return | ||
} | ||
|
||
var cur : CSingleLinkedListNode<T>? = m_Head | ||
|
||
//tempPrev is the start node to swap sequence. | ||
var tempPrev : CSingleLinkedListNode<T>? //"?" allowing following calling "tempPrev = nil", otherwise compiling error for it | ||
tempPrev = nil | ||
|
||
let steps : Int = (0 < startIndex) ? startIndex-1 : 0 | ||
for _ in 0...steps { | ||
if cur != nil { | ||
tempPrev = cur | ||
cur = cur?.next; | ||
} | ||
} | ||
if cur == nil { | ||
return | ||
} | ||
|
||
var tempHead: CSingleLinkedListNode<T>? = cur; | ||
|
||
|
||
for _ in startIndex...(endIndex-1) { | ||
if cur?.next != nil { | ||
let temp: CSingleLinkedListNode<T>? = cur?.next | ||
cur?.next = temp?.next; | ||
temp?.next = tempHead | ||
tempHead = temp | ||
} | ||
} | ||
|
||
if tempPrev != nil { | ||
tempPrev?.next = tempHead | ||
} | ||
else { | ||
m_Head = tempHead | ||
} | ||
|
||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// | ||
// CStack.swift | ||
// A stack class implemented by single linkedin list class CSingleList | ||
// | ||
// Created by Zhaohui Xing on 01/02/19. | ||
// Copyright © 2019 Zhaohui Xing. All rights reserved. | ||
// | ||
import Foundation | ||
|
||
public class CStack<T : Equatable> { | ||
let m_Container: CSingleLinkedList<T> | ||
|
||
//Make default initializer public to be accessible | ||
public init() { | ||
m_Container = CSingleLinkedList() | ||
} | ||
} | ||
|
||
extension CStack { | ||
public func Push(value: T) { | ||
let newHead : CSingleLinkedListNode<T> = CSingleLinkedListNode<T>(data:value) | ||
m_Container.AddHead(head: newHead) | ||
} | ||
} | ||
|
||
extension CStack { | ||
public func Pop()->T? { | ||
var tempValue : T? //"?" allowing following calling "tempValue = nil", otherwise compiling error for it | ||
tempValue = nil | ||
|
||
if m_Container.head != nil { | ||
tempValue = m_Container.head?.data | ||
m_Container.RemoveHead() | ||
} | ||
|
||
return tempValue | ||
} | ||
} | ||
|
||
extension CStack { | ||
public func Peek()->T? { | ||
var tempValue : T? //"?" allowing following calling "tempValue = nil", otherwise compiling error for it | ||
tempValue = nil | ||
|
||
if m_Container.head != nil { | ||
tempValue = m_Container.head?.data | ||
} | ||
|
||
return tempValue | ||
} | ||
} | ||
|
||
extension CStack { | ||
public func Empty()->Bool { | ||
var ret : Bool = true | ||
|
||
if m_Container.head != nil { | ||
ret = false | ||
} | ||
return ret | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// | ||
// SingleLList.swift | ||
// LinkList | ||
// | ||
// Created by Zhaohui Xing on 10/26/18. | ||
// Copyright © 2018 Zhaohui Xing. All rights reserved. | ||
// | ||
import Foundation | ||
|
||
public class CSingleLinkedListNode<T> { | ||
var m_Data: T? | ||
var m_Next: CSingleLinkedListNode<T>? | ||
var m_Hashvalue : Int64 //The hash value for hash table | ||
init() { | ||
let m : Int64 = Int64(INT_MAX) | ||
let v1 : Int64 = Int64.random(in: 0 ..< m) | ||
let v2 : Int64 = Int64.random(in: 0 ..< m) | ||
|
||
m_Hashvalue = v1 ^ v2 | ||
} | ||
|
||
public init(data: T) { | ||
let m : Int64 = Int64(INT_MAX) | ||
let v1 : Int64 = Int64.random(in: 0 ..< m) | ||
let v2 : Int64 = Int64.random(in: 0 ..< m) | ||
m_Hashvalue = v1 ^ v2 | ||
|
||
self.m_Data = data | ||
} | ||
|
||
public func clone()-> CSingleLinkedListNode<T> { | ||
let cloneNode : CSingleLinkedListNode<T> = CSingleLinkedListNode<T>(data: self.data!) //reference type "cloneNode", avoid "mutated warning for var" | ||
//cloneNode.next = ((m_Next!) ?? m_Next?.clone() , nil) | ||
/*guard let cloneNode.next = self.m_Next?.clone() else | ||
{ | ||
print("Catched the source next nil") | ||
cloneNode.next = nil | ||
}*/ | ||
if m_Next != nil | ||
{ | ||
cloneNode.next = self.m_Next!.clone() | ||
} | ||
return cloneNode | ||
} | ||
} | ||
|
||
extension CSingleLinkedListNode { | ||
public var data : T? { | ||
return m_Data | ||
} | ||
} | ||
|
||
extension CSingleLinkedListNode { | ||
public var next : CSingleLinkedListNode<T>? { | ||
set (newNode) { | ||
m_Next = newNode | ||
} | ||
get { | ||
return m_Next | ||
} | ||
} | ||
} | ||
|
||
extension CSingleLinkedListNode { | ||
public var tail : CSingleLinkedListNode<T>? { | ||
let ret = iscycled() | ||
if ret.retFlag { | ||
return ret.tailNode | ||
} | ||
else { | ||
if m_Next != nil { | ||
if m_Next?.tail != nil { | ||
return m_Next?.tail | ||
} | ||
else { | ||
return m_Next | ||
} | ||
} | ||
else { | ||
return self; | ||
} | ||
} | ||
} | ||
} | ||
|
||
extension CSingleLinkedListNode { //: Hashable { | ||
public var hashValue: Int64 { | ||
return m_Hashvalue | ||
} | ||
} | ||
|
||
|
||
extension CSingleLinkedListNode { | ||
public func iscycled()->(retFlag : Bool, cycleNode:CSingleLinkedListNode?, tailNode:CSingleLinkedListNode?) { | ||
var bRet : Bool = false | ||
var cycleNode:CSingleLinkedListNode? | ||
var tailNode:CSingleLinkedListNode? | ||
|
||
var hashLut = [Int64: CSingleLinkedListNode]() //hash table by Dictionary | ||
var cur : CSingleLinkedListNode<T>? = self; | ||
|
||
cycleNode = nil | ||
tailNode = nil | ||
|
||
while cur != nil { | ||
if cur!.next != nil && hashLut[cur!.next!.hashValue] != nil { | ||
cycleNode = cur!.next! | ||
tailNode = cur! | ||
bRet = true | ||
break | ||
} | ||
hashLut[cur!.hashValue] = cur | ||
cur = cur!.next | ||
} | ||
|
||
return (bRet, cycleNode, tailNode); | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
<playground version='5.0' target-platform='macos' executeOnSourceChanges='false'> | ||
<timeline fileName='timeline.xctimeline'/> | ||
</playground> |
7 changes: 7 additions & 0 deletions
7
Stack.playground/playground.xcworkspace/contents.xcworkspacedata
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.