iOS高级开发数据结构和算法分析iOS-算法篇

数据结构与算法

2018-04-05  本文已影响258人  施忆

一、数据结构

①什么是数据结构

数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。
关于数据结构的起源,请点击了解起源

②基本概念和术语

具体请参考数据结构相关概念
1)数据:指的是能输入到计算机中、并能被计算机程序处理的对象。相对应的就有数据类型(整型、字符型、浮点型等等)。
2)数据元素:指组成数据的、有意义的基本单位,也被称为记录。
3)数据项:是数据不可分割的最小单位,一个数据元素可以由若干数据项组成。
4)数据对象:指性质相同的数据元素的集合,是数据的子集。
5)数据结构:指互相之间存在一种或多种特定关系的数据元素的集合。

③数据结构类型

1、逻辑结构

逻辑结构是指反映数据元素之间的逻辑关系的数据结构,其中的逻辑关系是指数据元素之间的前后件关系,而与他们在计算机中的存储位置无关。
逻辑结构分为:集合结构、线性结构、树形结构、图形结构。

2、物理结构

指数据的逻辑结构在计算机存储空间的存放形式。
数据的物理结构是数据结构在计算机中的表示(又称映像),它包括数据元素的机内表示和关系的机内表示。由于具体实现的方法有顺序、链接、索引、散列等多种,所以,一种数据结构可表示成一种或多种存储结构。
数据元素的机内表示(映像方法):用二进制位的位串表示数据元素。通常称这种位串为节点。当数据元素有若干个数据项组成时,位串中与个数据项对应的子位串称为数据域。因此,节点是数据元素的机内表示(或机内映像)。
关系的机内表示(映像方法):数据元素之间的关系的机内表示可以分为顺序映像和非顺序映像,常用两种存储结构:顺序存储结构链式存储结构。顺序映像借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系。非顺序映像借助指示元素存储位置的指针来表示数据元素之间的逻辑关系。

④常用的数据结构

二、常用算法

①快速排序算法

算法简单学习--快速排序
快速排序的基本思想是:通过一轮排序将待排序元素分割成独立的两部分, 其中一部分的所有元素均比另一部分的所有元素小,然后分别对这两部分的元素继续进行快速排序,以此达到整个序列变成有序序列。快速排序的最坏时间复杂度为O(n²)),平均时间复杂度为O(n*log2n)。

一趟快速排序的算法是

/**
 快速排序

 @param array 需要排序的数据集合,必须是可变数组,因为不可变数组不能进行元素交换
 @param left 该数组的起始下标
 @param right 该数组的末尾下标
 */
- (void)fastSortingArray:(NSMutableArray *)array low:(NSInteger)left high:(NSInteger)right
{
    if (left >= right) {
        return;
    }
    NSInteger i = left;
    NSInteger j = right;
    NSInteger key = [array[left] integerValue];
    
    while (i<j) {
        /*而寻找结束的条件就是,1,找到一个小于或者大于key的数(大于或小于取决于你想升
         序还是降序)2,没有符合条件1的,并且i与j的大小没有反转*/
        while (i<j && key <= [array[j] integerValue]) {
            j--;
        }
        [self swap:array left:i right:j];
        
        /*这是i在当组内向前寻找,同上,不过注意与key的大小关系停止循环和上面相反,
         因为排序思想是把数往两边扔,所以左右两边的数大小与key的关系相反*/
        while (i<j && key >= [array[i] integerValue]) {
            i++;
        }
        [self swap:array left:i right:j];
    }
    
    [self fastSortingArray:array low:left high:i-1];
    [self fastSortingArray:array low:i+1 high:right];
}

//交换数组中的两个数
- (void)swap:(NSMutableArray *)array left:(NSInteger)left right:(NSInteger)right
{
    NSNumber *temp;
    if (array != nil && array.count > 0) {
        temp = array[left];
        array[left] = array[right];
        array[right] = temp;
    }
}

//初始化
- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSMutableArray *array = [NSMutableArray arrayWithObjects:@(1),@(10),@(8),@(7),@(4),@(3), nil];
    [self fastSortingArray:array low:0 high:5];
    for (int i = 0; i < 6; i++) {
        NSLog(@"%@",array[i]);
    }
}

//打印日志
2018-04-04 21:14:29.899014+0800 CommonAlgorithms[7000:405024] 1
2018-04-04 21:14:29.899151+0800 CommonAlgorithms[7000:405024] 3
2018-04-04 21:14:29.899266+0800 CommonAlgorithms[7000:405024] 4
2018-04-04 21:14:29.899424+0800 CommonAlgorithms[7000:405024] 7
2018-04-04 21:14:29.899524+0800 CommonAlgorithms[7000:405024] 8
2018-04-04 21:14:29.899643+0800 CommonAlgorithms[7000:405024] 10

②冒泡排序算法

算法简单学习--冒泡排序
冒泡排序的基本思想是:通过相邻两个元素之间的比较和交换,使较大的元素逐渐从前面移向后面(升序),就像水底下的气泡一样逐渐向上冒泡,所以被称为“冒泡”排序。冒泡排序的最坏时间复杂度为O(n²),平均时间复杂度为O(n²)

//冒泡排序
- (void)bubbleSort:(NSMutableArray *)array
{
    //比较的轮数
    for (int i = 0; i < array.count-1; i++) {
        //每轮比较的次数
        for (int j = 0; j<array.count-1-i; j++) {
            //进行升序排序
            if ([array[j] integerValue] > [array[j+1] integerValue]) {
                //交换元素
                [self swap:array left:j right:j+1];
            }
        }
    }
}

//交换
- (void)swap:(NSMutableArray *)array left:(NSInteger)left right:(NSInteger)right
{
    NSNumber *temp;
    if (array != nil && array.count > 0) {
        temp = array[left];
        array[left] = array[right];
        array[right] = temp;
    }
}

//初始化
- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSMutableArray *array = [NSMutableArray arrayWithObjects:@(1),@(10),@(8),@(7),@(4),@(3),@(0),@(9), nil];
    [self bubbleSort:array];
    for (int i = 0; i < 8; i++) {
        NSLog(@"%@",array[i]);
    }
}

//打印结果
2018-04-04 22:31:07.721115+0800 CommonAlgorithms[7898:459440] 0
2018-04-04 22:31:07.721268+0800 CommonAlgorithms[7898:459440] 1
2018-04-04 22:31:07.721380+0800 CommonAlgorithms[7898:459440] 3
2018-04-04 22:31:07.721518+0800 CommonAlgorithms[7898:459440] 4
2018-04-04 22:31:07.721627+0800 CommonAlgorithms[7898:459440] 7
2018-04-04 22:31:07.721816+0800 CommonAlgorithms[7898:459440] 8
2018-04-04 22:31:07.721921+0800 CommonAlgorithms[7898:459440] 9
2018-04-04 22:31:07.722025+0800 CommonAlgorithms[7898:459440] 10

③选择排序算法

简单选择排序
选择排序算法又分直接/简单选择排序堆排序
直接选择排序的基本思想是:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。直接选择排序的时间复杂度为O(n²)

//简单选择排序
- (void)selectionSort:(NSMutableArray *)array
{
    for (int i = 0; i < array.count-1; i++) {
        for (int j = i+1; j < array.count; j++) {
            //进行升序排序
            if ([array[i] integerValue] > [array[j] integerValue]) {
                [self swap:array left:i right:j];
            }
        }
    }
}

//交换
- (void)swap:(NSMutableArray *)array left:(NSInteger)left right:(NSInteger)right
{
    NSNumber *temp;
    if (array != nil && array.count > 0) {
        temp = array[left];
        array[left] = array[right];
        array[right] = temp;
    }
}

//初始化
- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSMutableArray *array = [NSMutableArray arrayWithObjects:@(1),@(10),@(8),@(7),@(4),@(3),@(0),@(9), nil];
    [self selectionSort:array];
    for (int i = 0; i < 8; i++) {
        NSLog(@"%@",array[i]);
    }
}

//打印日志
2018-04-04 22:54:28.205613+0800 CommonAlgorithms[8140:476345] 0
2018-04-04 22:54:28.206531+0800 CommonAlgorithms[8140:476345] 1
2018-04-04 22:54:28.206671+0800 CommonAlgorithms[8140:476345] 3
2018-04-04 22:54:28.207158+0800 CommonAlgorithms[8140:476345] 4
2018-04-04 22:54:28.207461+0800 CommonAlgorithms[8140:476345] 7
2018-04-04 22:54:28.207605+0800 CommonAlgorithms[8140:476345] 8
2018-04-04 22:54:28.207789+0800 CommonAlgorithms[8140:476345] 9
2018-04-04 22:54:28.208033+0800 CommonAlgorithms[8140:476345] 10

④直接插入排序算法

直接插入排序
直接插入排序的基本思想是从第二个元素开始,依次和前面的元素比较,如果比前面的元素小则将元素依次向后移位,给需要插入的元素腾出空间。与选择排序类似的是当前索引左边的所有元素都是有序的,但是它们最终的位置不确定,因为后面可能还会出现更小或更大的元素。所以为了给更小或更大的元素腾出空间,它们随时都可能被移动。如果到达了数组的右端时,数组顺序就完成了。

//直接插入排序
- (void)insertSort:(NSMutableArray *)array
{
    //从第二个元素开始
    for (int i = 1; i < array.count; i++) {
        int j = i;
        //记录第下个元素
        NSInteger temp = [array[i] integerValue];
        //进行升序排序
        while (j>0 && temp < [array[j-1] integerValue]) {
            //把大于temp的值放到temp的位置
            [array replaceObjectAtIndex:j withObject:array[j-1]];
            j--;
        }
        //然后把temp的值放在前面的位置
        [array replaceObjectAtIndex:j withObject:[NSNumber numberWithInteger:temp]];
    }
}

//初始化
- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSMutableArray *array = [NSMutableArray arrayWithObjects:@(1),@(10),@(8),@(7),@(4),@(3),@(0),@(9), nil];
    [self insertSort:array];
    for (int i = 0; i < 8; i++) {
        NSLog(@"%@",array[i]);
    }
}

//打印日志
2018-04-04 23:28:32.355955+0800 CommonAlgorithms[8696:503068] 0
2018-04-04 23:28:32.356091+0800 CommonAlgorithms[8696:503068] 1
2018-04-04 23:28:32.356209+0800 CommonAlgorithms[8696:503068] 3
2018-04-04 23:28:32.356301+0800 CommonAlgorithms[8696:503068] 4
2018-04-04 23:28:32.356422+0800 CommonAlgorithms[8696:503068] 7
2018-04-04 23:28:32.356687+0800 CommonAlgorithms[8696:503068] 8
2018-04-04 23:28:32.356801+0800 CommonAlgorithms[8696:503068] 9
2018-04-04 23:28:32.356916+0800 CommonAlgorithms[8696:503068] 10

⑤二分查找算法

二分查找--百度百科
二分查找也称折半查找,它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
二分查找的基本思想是:与猜数字游戏类似,就是那个有人说“我正想着一个1到100的数字”的游戏。我们每回应一个数字,那个人就会说这个数字是高了、低了还是对了。

/**
 二分查找

 @param array 需要查找的数组且必须为有序数组
 @param key 目标元素
 @param lower 数组起始下标
 @param upper 数组末尾下标
 @return 目标元素在数组的下标
 */
- (NSInteger)twoPointLookup:(NSArray *)array target:(NSInteger)key lower:(NSInteger)lower upper:(NSInteger)upper
{
    if (lower < upper) {
        //获取中间数组下标
        NSInteger middle = (lower+upper)/2;
        //与目标元素相等则直接返回
        if (key == [array[middle] integerValue]) {
            return middle;
        }
        //目标元素小于中间值
        else if (key < [array[middle] integerValue]) {
            //递归调用,起始下标为lower,末尾下标则改为middle-1
            return [self twoPointLookup:array target:key lower:lower upper:middle-1];
        }
        else {
            //递归调用,起始下标则改为middle+1,末尾下标为upper
            return [self twoPointLookup:array target:key lower:middle+1 upper:upper];
        }
    }
    else {
        return -1;
    }
}

//初始化
- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSArray *array = @[@(1),@(2),@(3),@(4),@(5),@(6),@(7),@(8)];
    NSInteger log = [self twoPointLookup:array target:6 lower:0 upper:7];
    NSLog(@"%ld",log);
}

//打印日志
2018-04-05 00:08:13.526588+0800 CommonAlgorithms[9122:531299] 5

⑥堆排序算法

⑦哈希排序算法

⑧二叉树的先序遍历(非递归)

请期待后续更新

三、Demo下载

后期更新会加上

四、相关简书推荐

刀客传奇算法简单学习系列
神经骚栋大话数据结构系列

上一篇 下一篇

猜你喜欢

热点阅读