Skip to content

Commit

Permalink
implementation of linked list in objective-c
Browse files Browse the repository at this point in the history
  • Loading branch information
jerryderry committed Oct 6, 2018
1 parent 576940c commit 1e1d204
Show file tree
Hide file tree
Showing 5 changed files with 319 additions and 0 deletions.
19 changes: 19 additions & 0 deletions object-c/06_linkedlist/ListNode.h
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
28 changes: 28 additions & 0 deletions object-c/06_linkedlist/ListNode.m
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
29 changes: 29 additions & 0 deletions object-c/06_linkedlist/SinglyLinkedList.h
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
117 changes: 117 additions & 0 deletions object-c/06_linkedlist/SinglyLinkedList.m
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
126 changes: 126 additions & 0 deletions object-c/06_linkedlist/SinglyLinkedListTests.m
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

0 comments on commit 1e1d204

Please sign in to comment.