• 排序算法(OC实现)


    排序的分类:

    交换类排序:冒泡排序、快速排序
    插入类排序:直接插入排序、希尔排序
    选择类排序:简单选择排序、堆排序

    交换类排序

    冒泡排序

    时间复杂度:最好(有序情况下)O(n),平均(逆序情况下)O(n^2)
    空间复杂度:O(1)
    算法思想:(从小到大,从前往后)
    第一个记录和第二个记录比较,如果第一个大,则二者交换,否则不交换;然后第二个记录和第三个记录比较,如果第二大,则二者交换,否则不交换……
    这里写图片描述
    代码:(这里是创建了NSMutableArray的分类,下同)

    #import "NSMutableArray+Sort.h"
    
    @implementation NSMutableArray (Sort)
    
    /** 冒泡排序
     *  isAsc YES 表示升序(下同)
     */
    - (void)sortedArrayWithBubleASC:(BOOL)isAsc{
        NSInteger len = self.count;
        for (NSInteger i=len-1; i>0; --i) {
            BOOL flag = NO;
            for (NSInteger j = 0; j < i; ++j) {
                if ((isAsc && self[j] > self[j+1]) || (!isAsc && self[j] < self[j+1])) {
                    [self swapIndex1:j index2:j+1];
                    flag = YES;
                }
            }
            if (!flag) {
                break;
            }
        }
    }
    
    /** 交换2个值 */
    - (void)swapIndex1:(NSInteger)index1 index2:(NSInteger)index2{
        id temp = self[index1];
        self[index1] = self[index2];
        self[index2] = temp;
    }
    @end

    快速排序:

    时间复杂度:最好(越接近无序,算法越高效)O(n),最坏(越接近有序,算法越低效)O(n^2),平均O(nlogn)
    空间复杂度:O(logn)
    这里写图片描述
    代码:

    /** 快速排序 */
    - (void)sortedArrayWithQuickLow:(NSInteger)low high:(NSInteger)high ASC:(BOOL)isAsc{
        NSInteger i = low, j = high;
        if (i < j) {
            id temp = self[i];
            while (i < j){
                while (i < j && ((self[j] > temp && isAsc) || (self[j] < temp && !isAsc))) --j;
                if(i<j) {self[i] = self[j]; ++i;}
                while (i < j && ((self[i] < temp && isAsc) || (self[i] > temp && !isAsc))) ++i;
                if(i<j) {self[j] = self[i]; --j;}
            }
            self[i] = temp;
            [self sortedArrayWithQuickLow:0 high:i-1 ASC:isAsc];
            [self sortedArrayWithQuickLow:i+1 high:high ASC:isAsc];
        }
    }

    选择类排序

    堆排序

    时间复杂度:O(nlogn)(最好,最坏都是这个)
    空间复杂度:O(1)
    可以把堆看为一颗完全二叉树,若父亲结点大于孩子结点,则这样的堆叫做大顶堆;若父亲结点小于孩子结点的值,则这样的堆叫做小顶堆。

    /** 堆排序 */
    - (void)sortedWithHeap:(BOOL)isAsc{
        for (NSInteger i = self.count/2 - 1; i>=0; --i) {
            [self siftWithLow:i high:self.count asc:isAsc];
        }
        for (NSInteger i = self.count - 1; i>=1; --i) {
            id temp = self[0];
            self[0] = self[i];
            self[i] = temp;
            [self siftWithLow:0 high:i asc:isAsc];
        }
    }
    
    - (void)siftWithLow:(NSInteger)low high:(NSInteger)high asc:(BOOL)isAsc{
        NSInteger left = 2 * low + 1;
        NSInteger right = left + 1;
        NSInteger lastIndex = low;
        //左子节点大的情况
        if (left < high && ((self[left] > self[lastIndex] && isAsc) || (self[left] < self[lastIndex] && !isAsc))) lastIndex = left;
        //右子节点大的情况
        if (right < high && ((self[right] > self[lastIndex] && isAsc) || (self[right] < self[lastIndex] && !isAsc))) lastIndex = right;
        //节点改变
        if (lastIndex != low) {
            //较大的节点值将交换到其所在节点的父节点
            id temp = self[low];
            self[low] = self[lastIndex];
            self[lastIndex] = temp;
            //递归遍历
            [self siftWithLow:lastIndex high:high asc:isAsc];
        }
    }

    简单选择排序

    时间复杂度:O(n^2 )
    空间复杂度:O(1)
    思想:从头至尾顺序扫描序列,找出最小的一个记录,和第一个记录交换,接着从剩下的记录中继续这种选择和交换,最终使序列有序。

    /** 简单选择排序 */
    - (void)sortedWithSelect:(BOOL)isAsc{
        for (int i = 0; i < self.count; ++i) {
            int k = i;
            //这个循环是从无序序列中挑出一个最小的元素
            for (int j = i+1; j<self.count; ++j) {
                if ((self[k] > self[j] && isAsc) || (self[k] < self[j] && !isAsc)) {
                    k = j;
                }
            }
            [self swapIndex1:i index2:k];
        }
    }

    插入类排序:

    直接插入排序

    时间复杂度: O(n^2)
    空间复杂度:O(1)
    稳定性:稳定

    代码:

    /** 直接插入排序 */
    - (void)sortedWithInsert:(BOOL)isAsc{
        for (int i = 1; i<self.count; ++i) {
            id temp = self[i];
            int j = i - 1;
            for (; j >= 0 && ((temp < self[j] && isAsc) || ((temp > self[j] && !isAsc))); --j) {
                self[j+1] = self[j];
            }
            self[j+1] = temp;
        }
    }

    希尔排序(缩小增量排序)

    时间复杂度:平均O(nlogn)
    空间复杂度:O(1)
    稳定性:不稳定
    这里写图片描述

    /** 希尔排序 */
    - (void)sortedWithShellStep:(int)step asc:(BOOL)isAsc{
        for (int i = 0; i < self.count; ++i) {
            id temp = self[i];
            int j = i - step;
            for (; j >= 0 && ((temp < self[j] && isAsc) || ((temp > self[j] && !isAsc))); j -= step) {
                self[j+step] = self[j];
            }
            self[j+step] = temp;
        }
    }

    总结:

    时间复杂度:“快些以nlogn的速度归队”(快:快速排序,些:希尔排序,归:归并排序,队:堆排序)
    空间复杂度:快速排序为O(logn),其他的都是O(1)
    稳定性:“心情不稳定快些选好友聊天”(快:快速排序,些:希尔排序,选:直接选择排序,堆:堆排序)
    这里写图片描述

    完整的DEMO见:GitHub地址

  • 相关阅读:
    4.3 DDL 数据类型
    Log4j的简要概述
    Eclipse/IDEA使用小技巧
    idea-生成key的Java代码
    Java8新特性--lamada详解
    JQuery基本语法
    EL与Velocity基本语法总结:
    RAF(RandomAccessFile)类
    Java篇-File类之常用操作
    Java篇-File类之创建删除
  • 原文地址:https://www.cnblogs.com/xiaocai-ios/p/7779764.html
Copyright © 2020-2023  润新知