forked from wangzheng0822/algo
-
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.
implementation of linked list in objective-c
- Loading branch information
1 parent
576940c
commit 1e1d204
Showing
5 changed files
with
319 additions
and
0 deletions.
There are no files selected for viewing
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,19 @@ | ||
// | ||
// ListNode.h | ||
// algo | ||
// | ||
// Created by Wenru Dong on 2018/10/6. | ||
// Copyright © 2018年 Wenru Dong. All rights reserved. | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
@interface ListNode : NSObject | ||
|
||
@property int value; | ||
@property ListNode *next; | ||
|
||
- (instancetype)initWithValue:(int)value; | ||
+ (instancetype)nodeWithValue:(int)value; | ||
|
||
@end |
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,28 @@ | ||
// | ||
// ListNode.m | ||
// algo | ||
// | ||
// Created by Wenru Dong on 2018/10/6. | ||
// Copyright © 2018年 Wenru Dong. All rights reserved. | ||
// | ||
|
||
#import "ListNode.h" | ||
|
||
@implementation ListNode | ||
|
||
- (instancetype)initWithValue:(int)value { | ||
if (self = [super init]) { | ||
_value = value; | ||
} | ||
return self; | ||
} | ||
|
||
+ (instancetype)nodeWithValue:(int)value { | ||
return [[self alloc] initWithValue:value]; | ||
} | ||
|
||
- (NSString*)debugDescription { | ||
return [NSString stringWithFormat:@"%d", _value]; | ||
} | ||
|
||
@end |
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,29 @@ | ||
// | ||
// SinglyLinkedList.h | ||
// algo | ||
// | ||
// Created by Wenru Dong on 2018/10/6. | ||
// Copyright © 2018年 Wenru Dong. All rights reserved. | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
#import "ListNode.h" | ||
|
||
@interface SinglyLinkedList : NSObject | ||
|
||
@property ListNode* head; | ||
|
||
- (ListNode*)nodeWithValue:(int)value; | ||
- (ListNode*)nodeAtIndex:(NSUInteger)index; | ||
|
||
- (void)insertNodeWithValue:(int)value; | ||
- (void)insertNode:(nonnull ListNode*)node; | ||
+ (void)insertNodeWithValue:(int)value afterNode:(nonnull ListNode*)node; | ||
+ (void)insertNode:(nonnull ListNode*)aNode afterNode:(nonnull ListNode*)node; | ||
- (void)insertNodeWithValue:(int)value beforeNode:(nonnull ListNode*)node; | ||
- (void)insertNode:(nonnull ListNode*)aNode beforeNode:(nonnull ListNode*)node; | ||
|
||
- (void)deleteNode:(nonnull ListNode*)node; | ||
- (void)deleteNodesWithValue:(int)value; | ||
|
||
@end |
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,117 @@ | ||
// | ||
// SinglyLinkedList.m | ||
// algo | ||
// | ||
// Created by Wenru Dong on 2018/10/6. | ||
// Copyright © 2018年 Wenru Dong. All rights reserved. | ||
// | ||
|
||
#import "SinglyLinkedList.h" | ||
|
||
@implementation SinglyLinkedList | ||
|
||
- (ListNode*)nodeWithValue:(int)value { | ||
ListNode* current = _head; | ||
while (current && current.value != value) { | ||
current = current.next; | ||
} | ||
return current; | ||
} | ||
|
||
- (ListNode*)nodeAtIndex:(NSUInteger)index { | ||
ListNode* current = _head; | ||
NSUInteger position = 0; | ||
while (current && position != index) { | ||
current = current.next; | ||
position++; | ||
} | ||
return current; | ||
} | ||
|
||
- (void)insertNodeWithValue:(int)value { | ||
ListNode* aNode = [ListNode nodeWithValue:value]; | ||
[self insertNode:aNode]; | ||
} | ||
|
||
- (void)insertNode:(nonnull ListNode *)node { | ||
node.next = _head; | ||
_head = node; | ||
} | ||
|
||
+ (void)insertNodeWithValue:(int)value afterNode:(nonnull ListNode *)node { | ||
ListNode* aNode = [ListNode nodeWithValue:value]; | ||
[SinglyLinkedList insertNode:aNode afterNode:node]; | ||
} | ||
|
||
+ (void)insertNode:(nonnull ListNode *)aNode afterNode:(nonnull ListNode *)node { | ||
aNode.next = node.next; | ||
node.next = aNode; | ||
} | ||
|
||
- (void)insertNodeWithValue:(int)value beforeNode:(nonnull ListNode *)node { | ||
ListNode* aNode = [ListNode nodeWithValue:value]; | ||
[self insertNode:aNode beforeNode:node]; | ||
} | ||
|
||
- (void)insertNode:(nonnull ListNode *)aNode beforeNode:(nonnull ListNode *)node { | ||
ListNode* fakeHead = [ListNode nodeWithValue:0]; | ||
fakeHead.next = _head; | ||
ListNode* current = fakeHead; | ||
while (current.next && current.next != node) { | ||
current = current.next; | ||
} | ||
if (current.next == nil) { | ||
return; | ||
} | ||
aNode.next = node; | ||
current.next = aNode; | ||
} | ||
|
||
- (void)deleteNode:(nonnull ListNode *)node { | ||
if (node.next) { | ||
node.value = node.next.value; | ||
node.next = node.next.next; | ||
return; | ||
} | ||
if (_head == nil) return; | ||
ListNode* current = _head; | ||
while (current.next && current.next != node) { | ||
current = current.next; | ||
} | ||
current.next = nil; | ||
} | ||
|
||
- (void)deleteNodesWithValue:(int)value { | ||
ListNode* fakeHead = [ListNode nodeWithValue:value+1]; | ||
fakeHead.next = _head; | ||
ListNode* prev = fakeHead; | ||
ListNode* current = _head; | ||
while (current) { | ||
if (current.value != value) { | ||
prev.next = current; | ||
prev = prev.next; | ||
} | ||
current = current.next; | ||
} | ||
if (prev.next) { | ||
prev.next = nil; | ||
} | ||
_head = fakeHead.next; | ||
} | ||
|
||
- (NSString*)debugDescription { | ||
NSMutableString* info = [[NSMutableString alloc] init]; | ||
ListNode* current = _head; | ||
if (current) { | ||
[info appendString:current.debugDescription]; | ||
} | ||
current = current.next; | ||
while (current) { | ||
[info appendString:@"->"]; | ||
[info appendString:current.debugDescription]; | ||
current = current.next; | ||
} | ||
return [NSString stringWithString:info]; | ||
} | ||
|
||
@end |
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,126 @@ | ||
// | ||
// SinglyLinkedListTests.m | ||
// SinglyLinkedListTests | ||
// | ||
// Created by Wenru Dong on 2018/10/6. | ||
// Copyright © 2018年 Wenru Dong. All rights reserved. | ||
// | ||
|
||
#import <XCTest/XCTest.h> | ||
#import "ListNode.h" | ||
#import "SinglyLinkedList.h" | ||
|
||
@interface SinglyLinkedListTests : XCTestCase | ||
|
||
@end | ||
|
||
@implementation SinglyLinkedListTests | ||
{ | ||
SinglyLinkedList* _list; | ||
NSArray* _nodes; | ||
} | ||
- (void)setUp { | ||
[super setUp]; | ||
ListNode* node1 = [ListNode nodeWithValue:1]; | ||
ListNode* node2 = [ListNode nodeWithValue:2]; | ||
ListNode* node3 = [ListNode nodeWithValue:3]; | ||
ListNode* node4 = [ListNode nodeWithValue:4]; | ||
ListNode* node5 = [ListNode nodeWithValue:5]; | ||
ListNode* node6 = [ListNode nodeWithValue:6]; | ||
node1.next = node2; | ||
node2.next = node3; | ||
node3.next = node4; | ||
node4.next = node5; | ||
node5.next = node6; | ||
|
||
_list = [[SinglyLinkedList alloc] init]; | ||
_list.head = node1; | ||
_nodes = [NSArray arrayWithObjects:node1, node2, node3, node4, node5, node6, nil]; | ||
} | ||
|
||
- (void)tearDown { | ||
// Put teardown code here. This method is called after the invocation of each test method in the class. | ||
[super tearDown]; | ||
} | ||
|
||
- (void)testNodeWithValue { | ||
XCTAssertEqualObjects([_list nodeWithValue:1], _list.head); | ||
XCTAssertNil([_list nodeWithValue:10]); | ||
} | ||
|
||
- (void)testNodeAtIndex { | ||
XCTAssertEqualObjects([_list nodeAtIndex:4], _nodes[4]); | ||
XCTAssertNil([_list nodeAtIndex:10]); | ||
} | ||
|
||
- (void)testInsertNodeWithValue { | ||
[_list insertNodeWithValue:9]; | ||
XCTAssertEqual(_list.head.value, 9); | ||
XCTAssertEqual(_list.head.next.value, 1); | ||
} | ||
|
||
- (void)testInsertNode { | ||
ListNode* aNode = [ListNode nodeWithValue:7]; | ||
[_list insertNode:aNode]; | ||
XCTAssertEqualObjects(_list.head, aNode); | ||
} | ||
|
||
- (void)testInsertNodeWithValueAfterNode { | ||
[SinglyLinkedList insertNodeWithValue:12 afterNode:_nodes[3]]; | ||
XCTAssertEqual([[_list nodeAtIndex:4] value], 12); | ||
} | ||
|
||
- (void)testInsertNodeAfterNode { | ||
ListNode* aNode = [ListNode nodeWithValue:28]; | ||
[SinglyLinkedList insertNode:aNode afterNode:_nodes[5]]; | ||
ListNode* prevNode = (ListNode *)_nodes[5]; | ||
XCTAssertEqualObjects(aNode, prevNode.next); | ||
} | ||
|
||
- (void)testInsertNodeBeforeNode { | ||
ListNode* aNode = [ListNode nodeWithValue:27]; | ||
ListNode* prevNode = (ListNode *)_nodes[3]; | ||
[_list insertNode:aNode beforeNode:_nodes[4]]; | ||
XCTAssertEqualObjects(aNode, prevNode.next); | ||
} | ||
|
||
- (void)testInsertNodeBeforeUnconnectedNode { | ||
ListNode* aNode = [ListNode nodeWithValue:27]; | ||
ListNode* floatingNode = [ListNode nodeWithValue:36]; | ||
[_list insertNode:aNode beforeNode:floatingNode]; | ||
for (NSUInteger i = 0; i < 6; i++) { | ||
XCTAssertEqualObjects([_list nodeAtIndex:i], _nodes[i]); | ||
} | ||
} | ||
|
||
- (void)testDeleteNode { | ||
[_list deleteNode:_nodes[0]]; | ||
XCTAssertEqual(_list.head.value, 2); | ||
[_list deleteNode:_nodes[5]]; | ||
ListNode* lastNode = (ListNode *)_nodes[4]; | ||
XCTAssertNil(lastNode.next); | ||
} | ||
|
||
- (void)testDeleteNodesWithValue { | ||
ListNode* firstNode = [ListNode nodeWithValue:1]; | ||
ListNode* secondNode = [ListNode nodeWithValue:1]; | ||
[_list insertNode:firstNode]; | ||
[_list insertNode:secondNode]; | ||
[_list deleteNodesWithValue:1]; | ||
for (NSUInteger i = 1; i < 6; i++) { | ||
XCTAssertEqualObjects([_list nodeAtIndex:i-1], _nodes[i]); | ||
} | ||
} | ||
|
||
- (void)testDebugDescription { | ||
XCTAssertEqualObjects(_list.debugDescription, @"1->2->3->4->5->6"); | ||
} | ||
|
||
//- (void)testPerformanceExample { | ||
// // This is an example of a performance test case. | ||
// [self measureBlock:^{ | ||
// // Put the code you want to measure the time of here. | ||
// }]; | ||
//} | ||
|
||
@end |