JHHK

欢迎来到我的个人网站
行者常至 为者常成

【基础】3、链表(一)

目录

链表

一、简介

动态数组有个明显的缺点
可能会造成内存空间的大量浪费
能否用到多少就申请多少内存?

链表可以办到这一点
链表是一种链式存储的线性表,所有元素的内存地址不一定是连续的

img

二、链表的设计

img

链表实现动态数组

LCLinkArray.h文件

#import <Foundation/Foundation.h>
#import "LCArray.h"

NS_ASSUME_NONNULL_BEGIN

@interface LCLinkArray : LCArray

@end

NS_ASSUME_NONNULL_END

LCLinkArray.m文件

#import "LCLinkArray.h"


@interface LCNode : NSObject
@property(nonatomic,strong)id       element;
@property(nonatomic,strong)LCNode * next;


/// 创建一个新的节点
/// @param element 节点元素
/// @param node 节点next指针
+(LCNode*)nodeWithElement:(id)element next:(LCNode*)node;

@end

@implementation LCNode

+(LCNode*)nodeWithElement:(id)element next:(LCNode*)node{
    LCNode*newNode = [[LCNode alloc] init];
    newNode.element = element;
    newNode.next = node;
    return newNode;
}

@end




@interface LCLinkArray()

@end


@implementation LCLinkArray{
    LCNode * _first;
}


- (void)add:(int)index element:(nonnull id)element {
    [self rangeCheckForAdd:index];
    
    if (index == 0) {
        _first = [LCNode nodeWithElement:element next:_first];
    }else{
        LCNode * preNode = [self nodeForIndex:index-1];
        preNode.next = [LCNode nodeWithElement:element next:preNode.next];
    }
    _size++;
}


- (void)clear {
    _first = nil;
    _size = 0;
}


- (nonnull id)get:(int)index {
    return [self nodeForIndex:index].element;
}


- (int)indexOf:(nonnull id)element {
    
    LCNode * node = _first;
    for (int i = 0; i<_size; i++) {
        if ([element isEqual:node.element]) {
            return i;
        }
        node = node.next;
    }
    
    return ELEMENT_NOT_FOUND;
}


- (nonnull id)remove:(int)index {
   
    [self rangeCheck:index];
    
    //first -> node0 -> node1 -> node2
    
    LCNode * node = _first;
    
    if (index == 0) {
        _first = _first.next;
    }else{
        LCNode * preNode = [self nodeForIndex:index-1];
        node = preNode.next;
        preNode.next = node.next;
    }
    _size--;
    return node.element;
}


- (nonnull id)set:(int)index element:(nonnull id)element {
    LCNode * node = [self nodeForIndex:index];
    id oldElement = node.element;
    node.element = element;
    return oldElement;
}


#pragma mark - 内部方法


/// 获取index位置的node对象
/// @param index 索引
-(LCNode*)nodeForIndex:(int)index{
    
    [self rangeCheck:index];
    
    LCNode * node = _first;
    for (int i=0; i<index; i++) {
        node = node.next;
    }
    return node;
}



-(NSString *)description{
    NSMutableString * des = [NSMutableString stringWithFormat:@"size=%d, [",_size];
    
    LCNode * node = _first;
    
    for (int i=0; i<_size; i++) {
        if (i!=0) {
            [des appendString:@", "];
        }
        
        [des appendFormat:@"%@",node.element];
                
        node = node.next;
    }
    
    [des appendString:@"]"];
    
    return des;
}
@end

算法训练

一、_141_环形链表

bool Solution::hasCycle(ListNode *head) {
    
    //思路:快慢指针
    
    //空链表或链表只有一个节点时,返回false
    if (head == nullptr || head->next == nullptr) {
        return false;
    }
    
    
    //避免起始时两个指针指向相同
    ListNode* slow = head;          //慢指针指向首个节点
    ListNode* fast = head->next;    //快指针指向第二个节点
    
    
    while (fast!=nullptr && fast->next!=nullptr) {
        slow = slow->next;
        fast = fast->next->next;
        
        if (slow == fast) {
            return true;
        }
    }
    
    return false;
}

二、_206_反转链表

/// 递归方式实现反转链表逻辑
/// @param head 链表
ListNode* Solution::reverseList(ListNode* head){
    
    if (head == nullptr || head->next == nullptr) return head;
    
    ListNode* newHead = reverseList(head->next);
    head->next->next = head;
    head->next = nullptr;
    return newHead;
}

/// 迭代方式实现反转链表逻辑
/// @param head 链表
ListNode* Solution::reverseList2(ListNode* head){
    
    if (head == nullptr || head->next == nullptr) return head;
    
    ListNode* newHead = nullptr;
    while (head != nullptr) {
        ListNode* tmp = head->next;
        head->next = newHead;
        
        newHead = head;
        head = tmp;
    }
   return newHead;
}

三、_237_删除链表中的节点

void Solution::deleteNode(ListNode* node){
    node->val  = node->next->val;
    node->next = node->next->next;
}

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.