objective-c算法详解(一、链表)

链表的介绍:

链表可以说是一种最为基础的数据结构。在维护集合数据的时候拥有很大的帮助,尤其是在增,删上拥有很大的效率今天总结一下曾经学习的链表。

在ios的开发中,掌握一些常用的算法可以帮助我们更加有效率的开发。

链表的总类:

  • 单链表
  • 双向链表
  • 循环链表

今天先来讲述下单链表:元素之间由一个单独的指针链接。这种结构的链表允许从第一个元素开始遍历到最后一个元素。

各元素之间通过一个指针连接起来而组成。每个元素包含两个部分:数据成员和一个被称为next的指针。通过这好种结构,将每个元素的next指针设置为指向其后面的元素。最后一个元素的Next设置为NULL,简单的表示链表的尾端。链表开始处的元素是”head“,链表的末尾的元素称为”tail“。

图一

根据上面说的,其实我们可以把链表看作一系列连续的元素,要知道这些元素是动态分配在内存中的。其实元素与元素之间的连接是为了保证我们能够访问到每个元素。如果其中有一个链接被丢失,那么从这个链接开始往后的所有链接都将被丢失。

我曾经在一本书上看过一句话:“你的弱点又多弱,你的强度就有多强”,这句话来形容链表非常的恰当。

进入今天的主题:

单链表接口的定义:

初始化链表:

-(void)listInit :(List*) list;

该函数必须在其他操作之前调用。,使用listInit初始化一个链表,方便我们执行其他操作。初始化非常简单,只需要将size设置为0,head与tail设置为null,就完成了初始化操作。

在指定的element后添加:

-(int)listInsNext:(List*) list over:(ListElemt *) element over:(ListElemt *)newElement;

简单的说,插入操作就是对链表进行新的连接,例如有两个节点A和C,要在A节点后加入B节点。首先先让B的next指针指向C。然后C,然后A的next指针指向B。这样就完成了简单的操作。但是但是当插入到head位置的话,新元素前面就没有节点了,这样怎么办?很简单,只需要将新元素next指针指向当前链表的头部就可以了。当传入的element为空,直接插入到头部就可以了。

图一:

移除指定element后的元素:

-(int)listRemNext:(List*) list over:(ListElemt *) element;

移除element身后的元素,而不是element本身,至于为什么,我们后在以后进行说明。需要考虑两点,移除头节点,以及其他节点。

操作其实很简单。例如有A,B,C三个节点,我们只需要申请一个D,让D指向A的下一个元素,然后A的next指向A的next的next。这样连接中我们就将B直接去掉,剩下A,C。之后ARC会帮我们自动回收掉B

图二:

输出链表

-(void)outPut:(List*) list;

采用一个循环,初始化一个指针pre,让这个指针指向list的head。每次循环后进行判断,并且重新规划:pre = pre->next

以下为一些宏定义,方便我们快速访问和监测List和ListElemt:

#define list_size(list)((list)->size)

#define list_head(list)((list)->head)
#define list_tail(list)((list)->tail)
#define list_is_head(list,element)((element)==(list)->head ? 1:0)
#define list_is_tail(element)((element)->next = NULL ? 1:0)
#define list_data(element)((element)->data)
#define list_next(element)((element)->data)

ListElemt.h代码:

//
//  ListElemt.h
//  ok
//
//  Created by MrLoong on 15/8/8.
//  Copyright (c) 2015年 MrLoong. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface ListElemt : NSObject{
    @public id data;
    @public ListElemt *next;
}
@end

list.h代码如下:


//  List.h
//  Created by MrLoong on 15/8/8.
//  Copyright (c) 2015年 MrLoong. All rights reserved.
//

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

@interface List : NSObject{
   @public ListElemt *head;
   @public ListElemt *tail;
   @public int size;
}
//初始化链表
-(void)listInit :(List*) list;
//在指定的element后添加newElement
-(int)listInsNext:(List*) list over:(ListElemt *) element over:(ListElemt *)newElement;
//移除指定element后的元素
-(int)listRemNext:(List*) list over:(ListElemt *) element;
//输出链表
-(void)outPut:(List*) list;

#define list_size(list)((list)->size)

#define list_head(list)((list)->head)
#define list_tail(list)((list)->tail)
#define list_is_head(list,element)((element)==(list)->head ? 1:0)
#define list_is_tail(element)((element)->next = NULL ? 1:0)
#define list_data(element)((element)->data)
#define list_next(element)((element)->data)

@end

list.m代码如下

//
//  List.m
//  ok
//
//  Created by MrLoong on 15/8/8.
//  Copyright (c) 2015年 MrLoong. All rights reserved.
//

#import "List.h"

@implementation List
//初始化链表
-(void) listInit:(List *)list{
    list->size = 0;
    list->head = NULL;
    list->tail = NULL;
    return;
}

//在元素element后插入newElement 

-(int)listInsNext:(List *)list over:(ListElemt *)element over:(ListElemt *)newElement{

    if(newElement==NULL){
        return -1;
    }

    if(element==NULL){
        if(list_size(list)==0){
            list->tail = newElement;
        }
        newElement->next = list->head;
        list->head = newElement;

    }
    else{
        if(element==NULL){
            list->tail = newElement;
        }
        newElement->next = element->next;
        element->next = newElement;
    }

    list->size++;

    return 0;
}

//移除指定element后的元素
-(int)listRemNext:(List *)list over:(ListElemt *)element{

    ListElemt *oldEmement;

    if(list_size(list)==0){
        return -1;
    }
    if (element==NULL) {
        oldEmement = list->head;
        list->head = list->head->next;

        if(list_size(list)==0){
            list->tail = NULL;
        }
    }
    else{
        if(element->next==NULL){
            return -1;
        }
        oldEmement = element->next;
        element->next = element->next->next;

        if(element->next == NULL){
            list->tail = element;
        }
    }
   // free((__bridge void *)(oldEmement));
    return 0;
}

//输出链表
-(void)outPut:(List *)list{
    ListElemt *pre = list->head;
    while (pre!=nil) {
        NSLog(@"%@",pre->data);
        pre = pre->next;

    }
}

@end

main.m代码:

//
//  main.m
//  ok
//
//  Created by MrLoong on 15/8/8.
//  Copyright (c) 2015年 MrLoong. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "List.h"
#import "ListElemt.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //创建元素
        List *list = [[List alloc] init];
        [list listInit:list];

        ListElemt *element1 = [[ListElemt alloc]init];
        element1->data = [NSNumber numberWithInt:1];

        ListElemt *element2 = [[ListElemt alloc]init];
        element2->data = [NSNumber numberWithInt:2];

        ListElemt *element3 = [[ListElemt alloc]init];
        element3->data = [NSNumber numberWithInt:3];

        ListElemt *element4 = [[ListElemt alloc]init];
        element4->data = [NSNumber numberWithInt:4];

        ListElemt *element5 = [[ListElemt alloc]init];
        element5->data = [NSNumber numberWithInt:5];

        ListElemt *element6 = [[ListElemt alloc]init];
        element6->data = [NSNumber numberWithInt:6];
        //创建元素
        [list listInsNext:list over:list->head over:element1];
        [list listInsNext:list over:element1 over:element2];
        [list listInsNext:list over:element2 over:element3];
        [list listInsNext:list over:element3 over:element4];
        [list listInsNext:list over:element4 over:element5];
        [list listInsNext:list over:element5 over:element6];

        [list outPut:list];
        //删除element2后的元素element3
        [list listRemNext:list over:element2];

        printf("===========================================\n");
        printf("插入完成\n");
        printf("===========================================\n");

        [list outPut:list];
        printf("===========================================\n");
        printf("删除完成\n");
        printf("===========================================\n");
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 22:21:49

objective-c算法详解(一、链表)的相关文章

最短路算法 :Bellman-ford算法 &amp; Dijkstra算法 &amp; floyd算法 &amp; SPFA算法 详解

 本人QQ :2319411771   邮箱 : [email protected] 若您发现本文有什么错误,请联系我,我会及时改正的,谢谢您的合作! 本文为原创文章,转载请注明出处 本文链接   :http://www.cnblogs.com/Yan-C/p/3916281.html . 很早就想写一下最短路的总结了,但是一直懒,就没有写,这几天又在看最短路,岁没什么长进,但还是加深了点理解. 于是就想写一个大点的总结,要写一个全的. 在本文中因为邻接表在比赛中不如前向星好写,而且前向星效率并

EM算法(3):EM算法详解

目录 EM算法(1):K-means 算法 EM算法(2):GMM训练算法 EM算法(3):EM算法详解

[转] KMP算法详解

转载自:http://www.matrix67.com/blog/archives/115 KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段.    我们这里说的KMP不是拿来放电影的(虽然我很喜欢这个软件),而是一种算法.KMP算法是拿来处理字符串匹配的.换句话说,给你两个字符串,你需要回答,B串是否是A串的子串(A串是否包含B串).比如,字符串A="I'm matrix67",字符串B="matrix",我们就说B是A的子串.

[搜索]波特词干(Porter Streamming)提取算法详解(3)

 接上 [搜索]波特词干(Porter Streamming)提取算法详解(2) 下面分为5大步骤来使用前面提到的替换条件来进行词干提取. 左边是规则,右边是提取成功或者失败的例子(用小写字母表示). 步骤1 SSES -> SS                   caresses  ->  caress IES  -> I                          ponies    ->  poni ties      ->  ti SS   -> S

KMP算法详解(图示+代码)

算法过程非常绕,不要企图一次就能看明白,多尝试就会明白一些.下面试图用比较直观的方法解释这个算法,对KMP算法的解释如下: 1. 首先,字符串"BBC ABCDAB ABCDABCDABDE"的第一个字符与搜索词"ABCDABD"的第一个字符,进行比较.因为B与A不匹配,所以搜索词后移一位. 2. 因为B与A不匹配,搜索词再往后移. 3. 就这样,直到字符串有一个字符,与搜索词的第一个字符相同为止. 4. 接着比较字符串和搜索词的下一个字符,还是相同. 5. 直到字

安全体系(三)——SHA1算法详解

本文主要讲述使用SHA1算法计算信息摘要的过程. 安全体系(零)—— 加解密算法.消息摘要.消息认证技术.数字签名与公钥证书 安全体系(一)—— DES算法详解 安全体系(二)——RSA算法详解 为保证传输信息的安全,除了对信息加密外,还需要对信息进行认证.认证的目的有两:一是验证信息的发送者是合法的,二是验证信息的完整性.Hash函数就是进行信息认证的一种有效手段. 1.Hash函数和消息完整性 Hash函数也称为杂凑函数或散列函数,函数输入为一可变长度x,输出为一固定长度串,该串被称为输入x

php 二分查找法算法详解

一.概念:二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表.首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用中间位置记录将表分成前.后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表.重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功. 二.代

【转】AC算法详解

原文转自:http://blog.csdn.net/joylnwang/article/details/6793192 AC算法是Alfred V.Aho(<编译原理>(龙书)的作者),和Margaret J.Corasick于1974年提出(与KMP算法同年)的一个经典的多模式匹配算法,可以保证对于给定的长度为n的文本,和模式集合P{p1,p2,...pm},在O(n)时间复杂度内,找到文本中的所有目标模式,而与模式集合的规模m无关.正如KMP算法在单模式匹配方面的突出贡献一样,AC算法对于

支持向量机(SVM)(五)-- SMO算法详解

一.我们先回顾下SVM问题. A.线性可分问题 1.SVM基本原理: SVM使用一种非线性映射,把原训练            数据映射到较高的维.在新的维上,搜索最佳分离超平面,两个类的数据总可以被超平面分开. 2.问题的提出: 3.如何选取最优的划分直线f(x)呢? 4.求解:凸二次规划 建立拉格朗日函数: 求偏导数: B.线性不可分问题 1.核函数 如下图:横轴上端点a和b之间红色部分里的所有点定为正类,两边的黑色部分里的点定为负类. 设: g(x)转化为f(y)=<a,y> g(x)=

Manacher算法详解

[转] Manacher算法详解 转载自: http://blog.csdn.net/dyx404514/article/details/42061017 Manacher算法 算法总结第三弹 manacher算法,前面讲了两个字符串相算法——kmp和拓展kmp,这次来还是来总结一个字符串算法,manacher算法,我习惯叫他 “马拉车”算法. 相对于前面介绍的两个算法,Manacher算法的应用范围要狭窄得多,但是它的思想和拓展kmp算法有很多共通支出,所以在这里介绍一下.Manacher算法