iOS算法:鏈表-2020-08-05

簡介

鏈表(Linked List)是一種物理存儲單元上非連續(xù)玲献、非順序的存儲結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針鏈接次序?qū)崿F(xiàn)的亡资。

單鏈表:

image.png

雙鏈表:

image.png

iOS 數(shù)據(jù)結(jié)構(gòu)之鏈表

這里以單鏈表為主派近,雙鏈表大同小異,不重復(fù)忘嫉。

節(jié)點

C語言中可以用struct表示,那么在OC中就應(yīng)該用類來表示案腺。這里簡單起見庆冕,就兩個成員,數(shù)據(jù)和下一個指針劈榨。

@interface ListNode : NSObject

// key访递,用來標(biāo)識結(jié)點本身,不需要唯一同辣,默認(rèn)情況下可以用data的hash代替
@property (assign, nonatomic) NSInteger key;

// 數(shù)據(jù)
@property (strong, nonatomic) id data;

// 下一個指針
@property (strong, nonatomic) ListNode *next;

@end

如果創(chuàng)建節(jié)點拷姿,就需要初始化函數(shù)。

- (instancetype)initWithData:(id)data {
    self = [super init];
    if (self) {
        _data = data;
    }
    return self;
}

+ (instancetype)nodeWithData:(id)data {
    return [[[self class] alloc] initWithData:data];
}

頭結(jié)點

對于一個單鏈表來講旱函,頭結(jié)點就代表了這個鏈表本身响巢。所以需要一個頭結(jié)點屬性。

@interface List()

// 頭結(jié)點
@property (strong, nonatomic) ListNode *headNode;

@end

添加節(jié)點

可以固定在頭部添加棒妨,這也符合最新使用的原則踪古。
另外提供一個方便方法,將數(shù)組中的值連續(xù)添加進(jìn)去券腔。

// 添加節(jié)點伏穆,加在頭部
- (void)addNode:(ListNode *)node {
    // 空節(jié)點不需要添加
    if (node == nil) {
        return;
    }
    
    // key可以重復(fù),可以相同纷纫,沒必要檢查是否存在
    
    // 添加到頭部
    if (self.head != nil) {
        node.next = self.head;
        self.head = node;
    } else {
        self.head = node;
    }
}

// 方便方法枕扫,添加一組節(jié)點
- (void)addNodes:(NSArray *)datas {
    [datas enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [self addNode:[ListNode nodeWithData:obj]];
    }];
}

讀取所有節(jié)點

遍歷鏈表,打印信息辱魁,同時返回節(jié)點數(shù)組烟瞧。

// 讀取所有節(jié)點
- (NSArray *)readAllNodes {
    NSMutableArray *nodes = [NSMutableArray array];
    ListNode *temp = self.head;
    while (temp) {
        [nodes addObject:temp];
        NSLog(@"node key:%ld; node data: %@", (long)temp.key, temp.data);
        temp = temp.next;
    }
    
    return [nodes copy];
}

倒序排列

對于單鏈表,討論最多的就是倒序輸出染簇。倒序輸出理解起來確實比較麻煩燕刻。
需要引入previous, current, next三個指針輔助理解,相對簡單一點:

image.png
  1. 將下一個保存在next中剖笙。next = current.next;

  2. 反轉(zhuǎn):將下一個指向前一個卵洗。current.next = previous;

  3. 移動:前一個移動到當(dāng)前。previous = current;

  4. 移動:當(dāng)前移動到下一個弥咪。 current = next;

循環(huán)之后过蹂,current已經(jīng)移動到最后,previous就是新的頭

圖解單鏈表反轉(zhuǎn)

// 倒序
- (void)reverse {
    ListNode *previous = nil;
    ListNode *current = self.head;
    ListNode *next = nil;
    
    while (current) {
        // 1. 將下一個保存在`next`中聚至。
        next = current.next;
        // 2. 反轉(zhuǎn):將下一個指向前一個酷勺。
        current.next = previous;
        // 3. 移動:前一個移動到當(dāng)前。
        previous = current;
        // 4. 移動:當(dāng)前移動到下一個扳躬。
        current = next;
    }
    
    // current已經(jīng)移動到最后脆诉,previous就是新的頭
    self.head = previous;
}

測試

image.png
// 生成鏈表
- (IBAction)generateButtonTouched:(id)sender {
    NSString *input = self.inputTextView.text;
    NSArray *array = [input componentsSeparatedByString:@","];
    [self.list addNodes:array];
    
    NSArray *nodes = [self.list readAllNodes];
    NSMutableArray *messages = [NSMutableArray array];
    [nodes enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        ListNode *node = (ListNode *)obj;
        NSString *message = [NSString stringWithFormat:@"%@", node.data];
        [messages addObject:message];
    }];
    self.listLabel.text = [messages componentsJoinedByString:@";"];
}

// 反向鏈表
- (IBAction)reverseButtonTouched:(id)sender {
    [self.list reverse];
    
    NSArray *nodes = [self.list readAllNodes];
    NSMutableArray *messages = [NSMutableArray array];
    [nodes enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        ListNode *node = (ListNode *)obj;
        NSString *message = [NSString stringWithFormat:@"%@", node.data];
        [messages addObject:message];
    }];
    self.reverseLabel.text = [messages componentsJoinedByString:@";"];
}
image.png

demo

https://gitee.com/zhangxusong888/ObjectCDemo/tree/master/AlgorithmDemo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甚亭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子击胜,更是在濱河造成了極大的恐慌亏狰,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件偶摔,死亡現(xiàn)場離奇詭異暇唾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)辰斋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門策州,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人宫仗,你說我怎么就攤上這事够挂。” “怎么了藕夫?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵下硕,是天一觀的道長。 經(jīng)常有香客問我汁胆,道長梭姓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任嫩码,我火速辦了婚禮誉尖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘铸题。我一直安慰自己铡恕,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布丢间。 她就那樣靜靜地躺著探熔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪烘挫。 梳的紋絲不亂的頭發(fā)上诀艰,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機(jī)與錄音饮六,去河邊找鬼其垄。 笑死,一個胖子當(dāng)著我的面吹牛卤橄,可吹牛的內(nèi)容都是我干的绿满。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼窟扑,長吁一口氣:“原來是場噩夢啊……” “哼喇颁!你這毒婦竟也來了漏健?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤橘霎,失蹤者是張志新(化名)和其女友劉穎蔫浆,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茎毁,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡克懊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年忱辅,在試婚紗的時候發(fā)現(xiàn)自己被綠了七蜘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡墙懂,死狀恐怖橡卤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情损搬,我是刑警寧澤碧库,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站巧勤,受9級特大地震影響嵌灰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜颅悉,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一沽瞭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧剩瓶,春花似錦驹溃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至枝缔,卻和暖如春布疙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背愿卸。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工拐辽, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人擦酌。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓俱诸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親赊舶。 傳聞我的和親對象是個殘疾皇子睁搭,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,077評論 2 355