排序算法

2021-02-22  本文已影响0人  甲乙飞鱼

冒泡排序

- (void)sort {

    for (NSInteger end = self.array.count - 1; end > 0; end--) {
        
        //初始值等于1 防止数组未排序前就是有序数组  (第二个循环一次未修改 第一个循环直接退出)
        NSInteger isNum = 1;
        for (NSInteger i = 1; i <= end; i++) {
            
            if ([self cmp:i-1 to:i] > 0) {
                
                [self swapIndex:i to:i-1];
                isNum = i;
            }
        }
        
        end = isNum;
    }
}

选择排序

- (void)sort {

    for (NSInteger end = self.array.count - 1; end > 0; end--) {
        
        NSInteger isNum = 0;
        
        for (NSInteger i = 1; i <= end; i++) {

            if ([self cmp:i to:isNum] > 0) {
                
                isNum = i;
            }
        }
        
        [self swapIndex:isNum to:end];
    }
}

堆排序

- (void)sort {

    self.heapSize = (int)self.array.count;
    
    // 原地建堆  (最大堆)
    for (int i = (self.heapSize >> 1) - 1; i >= 0; --i) {
        
        //所有的非叶子节点依次下虑 最大堆就排好了
        [self siftDown:i];
    }
    
    //交换堆顶元素和尾元素 (交换一次微元素位置 --1)
    //尾元素位置 == 1 时数组有序了
    while(self.heapSize > 1) {
        
        [self swapIndex:0 to:--self.heapSize];
        
        [self siftDown:0];
    }  
}
- (void)siftDown:(int)index {
    
    int element = [self.array[index] intValue];
    
    int childIndex;
    
    //self.heapSize >> 1  最后一个非叶子节点的 index
    //index 每次传入的是最后一个飞叶子节点-1
    //half 最后一个非叶子节点的 index
    //index < half ; index = childIndex
    //这个index < half
    //因为 index = childIndex  childIndex 必然大于 index
    //第一次循环index = half 然后每次循环都是 index > half 所以在等待循环里的break;  break 时 下虑到了叶子节点

    for(int half = self.heapSize >> 1; index < half; index = childIndex) {
             
        //左子节点的 index
        childIndex = (index << 1) + 1;
           
        //左子节点的 index位置的值
        int child = [self.array[childIndex] intValue];
            
        //右子节点的 index
        int rightIndex = childIndex + 1;
               
        //rightIndex < self.heapSize  节点的index 必须小于数组的size
        //[self cmpElement:[self.array[rightIndex] intValue] to:child]
        //右子节点的值 大于 左子节点的值
        if (rightIndex < self.heapSize && [self cmpElement:[self.array[rightIndex] intValue] to:child] > 0) {
              
            // 记录 左右子节点 比较大的值 和 index
            childIndex = rightIndex;
                   
            child = [self.array[rightIndex] intValue];
               
        }//这里没有else  是因为 childIndex  child 已经记录了 左子节点的index 和 值了
        
               
        // 如果 父节点的值 大于 最大子子节点的值 则不需下虑 退出此次循环
        if ([self cmpElement:element to:child] >= 0) {
                  
            break;
        }

        //如果 父节点的值 小于于 最大子子节点的值 则需下虑  继续循环下去
        self.array[index] = @(child);
    }
    
    self.array[index] = @(element);
}

插入排序

- (void)sort {
    
    for (int begin = 1; begin < self.array.count; begin++) {
        
        // 待插入元素的索引
        int a = begin;
        // 待插入元素
        int b = [self.array[a] intValue];
               
        // 判断插入位置 并把插入位置到待插入位置的元素往后挪移一位
        while (a > 0 && [self cmpElement:b to:[self.array[a - 1] intValue]] < 0) {

            self.array[a] = self.array[a-1];
            
            a--;
        }
        // 待插入元素放到最终的何时位置
        self.array[a] = @(b);
    }
}

归并排序

- (void)sort {

    self.leftArr = [NSMutableArray array];
    
    [self sortBegin:0 end:self.array.count];
}


- (void)sortBegin:(NSInteger)begin end:(NSInteger)end {
    
    if (end - begin >= 2) {
        
        NSInteger mid = (begin + end) >> 1;
        // 不断地将当前序列平均分割成2个子序列
        // 知道不能再分割(序列里只剩一个元素)
        [self sortBegin:begin end:mid];
        [self sortBegin:mid end:end];
        // 不断地将两个子序列合并成一个有序的序列
        // 最终只剩一个有序序列
        [self mergeBegin:begin mid:mid end:end];
    }
}

- (void)mergeBegin:(NSInteger)begin mid:(NSInteger)mid end:(NSInteger)end {
    
    NSInteger li = 0;              //归并的两个数组的第一个数组的左边 index
    NSInteger le = mid - begin;    //归并的两个数组的第一个数组的右边 index
    NSInteger ri = mid;            //归并的两个数组的第二个数组的左边 index
    NSInteger re = end;            //归并的两个数组的第二个数组的右边 index
    NSInteger ai = begin;          //归并的两个数组覆盖到那个位置了
    
    //备份左边数组的元素
    for(NSInteger i = li; i < le; ++i) {
        
        self.leftArr[i] = self.array[begin + i];
    }
    
    while(true) {
        
        while(li < le) {
            
            if (ri < re && [self cmpElement:[self.array[ri] intValue] to:[self.leftArr[li] intValue]] < 0) {
                
                self.array[ai++] = self.array[ri++];
                
            } else {
                
                self.array[ai++] = self.leftArr[li++];
            }
        }

        return;
    }
}

不断地将当前序列平均分割成2个子序列
直到不能再分割(序列里只剩一个元素)
不断地将两个子序列合并成一个有序的序列
最终只剩一个有序序列

快速排序

- (void)sort {

    [self sortBegin:0 end:self.array.count];
}

//对 [begin, end) 范围的元素进行快速排序
- (void)sortBegin:(NSInteger)begin end:(NSInteger)end {
    
    if (end - begin < 2) return;

    // 确定轴点位置 O(n)
    NSInteger mid = [self pivotIndexBegin:begin end:end];
    
    // 对子序列进行快速排序
    [self sortBegin:begin end:mid];
    [self sortBegin:mid+1 end:end];
}


/// 构造出 [begin, end) 范围的轴点元素  返回轴点元素的最终位置
- (NSInteger)pivotIndexBegin:(NSInteger)begin end:(NSInteger)end {
    
    NSInteger a = begin + (NSInteger)(arc4random() % (end - begin));
    
    // 随机选择一个元素跟begin位置进行交换
    [self swapIndex:begin to:a];
    
    // 备份begin位置的元素
    int pivot = [self.array[begin] intValue];
    // end指向最后一个元素
    end--;
    
    while (begin < end) {
        while (begin < end) {

            if ([self cmpElement:pivot to:[self.array[end] intValue]] < 0) { // 右边元素 > 轴点元素
                end--;
            } else { // 右边元素 <= 轴点元素
                self.array[begin++] = self.array[end];
                break;
            }
        }
        while (begin < end) {
            
            if ([self cmpElement:pivot to:[self.array[begin] intValue]] > 0) { // 左边元素 < 轴点元素
                begin++;
            } else { // 左边元素 >= 轴点元素
                self.array[end--] = self.array[begin];
                break;
            }
        }
    }
    
    // 将轴点元素放入最终的位置
    self.array[begin] = @(pivot);
    // 返回轴点元素的位置
    return begin;
}

希尔排序

- (void)sort {

    NSMutableArray *stepSequence = [self sedgewickStepSequence];
    
    for (NSInteger i = 0; i < stepSequence.count; i++) {
        
        int step = [stepSequence[i] intValue];
                
        [self sort1:step];
    }
}

//根据步长序列排序  根据分成step列 进行排序
- (void)sort1:(int)step {
    
    //col:第几列 column的简称
    for (int col = 0; col < step; col++) {
        
        for (int begin = step + col; begin < self.array.count; begin += step) {
        
            int cur = begin;
            
            while (cur > col && ([self cmp:cur to:cur - step] < 0)) {
                
                [self swapIndex:cur to:cur-step];
                cur -= step;
            }
        }
    }
}

上一篇下一篇

猜你喜欢

热点阅读