cocos2d程序员架构算法设计模式和编程理论

排序算法

2016-10-21  本文已影响196人  小黑_Coder

排序算法总结

数据结构 + 算法 = 程序

今天闲来没事,我们就来聊一聊几个耳熟能详的排须算法,也算是对自己所学的一个总结。由于个人学识肤浅,难免会有些错误,希望大家积极指出。

1.冒泡排序

相信学过C的人都了解它,这也可能是好多人接触到的第一个排序算法。在实际项目中也是用的非常多的一种排序算法

算法描述

算法实现(C语言)

void bubbleSortFunction(int *arr, int count) {
    
    for (int i = 0; i < count; i++) {
        
        for (int j = 0; j < count - i - 1; j++) {
            
            if (arr[j] < arr[j+1]) {
                
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
}

算法分析

算法图解

图片来自网络,如果涉及侵权请告知。

冒泡排序.gif

选择排序

此算法我能唯一想到的好处应该是思想简单不占用额外的内存空间。无论什么数进去都是O(n^2)的时间复杂度,所以在选用它的时候,数据规模越小越好。

算法原理

算法实现(C语言)

void selectionSort(int *arr, int count) {
    
    for (int i = 0; i < count; i++) {
        
        int minIndex = i;
        for (int j = i+1; j < count; j++) {
            
            if (arr[j] < arr[minIndex]) {
                
                minIndex = j;
            }
        }
        int temp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp;
    }
}

算法分析

算法图解

图片来自网络,如果涉及侵权请告知。

选择排序.gif

插入排序

想想我们在打扑克牌抓拍这个过程,我们就能理解什么是插入排序了。如果你重来没有打过扑克牌,那么我想对你说,为了能很好的理解插入排序这个算法,快去斗一局地主吧。

算法描述

显然上面第二步找到新元素的位置还有很多种算法,比如二分查找,插值查找,斐波那契查找,树表查找,哈希查找。但是查找算法不是本文讨论的重点,因此我们选择最易理解的顺序查找

算法实现(C语言)

void insertSortFunction(int *arr, int count) {
    
    for (int i = 1; i < count; i++) {
        
        int temp = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] >= temp) {
            
            arr[j+1] = arr[j];
            j--;
        }
        arr[j+1] = temp;
    }
}

算法图解

图片来自网络,如果涉及侵权请告知。

插入排序.gif

希尔排序

第一个突破O(n^2)的排序算法,是对插入排序的一种改进。

算法描述

算法实现(C语言)

void shellsortFunction(int *arr, int count, int tk) {

    for (int k = 0; k < tk; k++) {
        
        for (int i = 1; k + i * tk < count; i++) {
            
            int temp = arr[k+i*tk];
            int j = k+(i-1)*tk;
            while (j >= k && arr[j] >= temp) {
                
                arr[j+tk] = arr[j];
                j = j - tk;
            }
            arr[j+tk] = temp;
        }
    }
}

算法分析

算法图解

图片来自网络,如果涉及侵权请告知。

希尔排序.gif

归并排序

归并算法是建立在归并操作上的一种有效的排序算法,该算法是分治法的一个典型应用。将已有序的子序合并,得到完全有序的序列。即先使每个子序列有序,在使子序列段间有序。归并排序和选择排序一样性能 不受输入数据的影响时间复杂度始终是O(nlgn),当然节省了时间就要付出更多空间的代价

算法描述

算法实现(C语言)

void merge(int *left, int countL, int *right, int countR) {
    
    int temp[countL+countR];
    int i = 0, j = 0;
    while (i < countL && j < countR) {
        
        if (left[i] < right[j]) {
            
            temp[i+j] = left[i];
            i++;
        } else {
            
            temp[i+j] = right[j];
            j++;
        }
    }
    for (; i < countL; i++) {
        
        temp[i+j] = left[i];
    }
    for (; j < countR; j++) {
        
        temp[i+j] = right[j];
    }
    for (int i = 0; i < countR+countL; i++) {
        
        left[i] = temp[i];
    }
}

void mergeSort(int *arr, int count) {
    
    if (count > 1) {
        
        int middle = count / 2;
        mergeSort(arr, middle);
        if (count % 2 == 0) {
            
            mergeSort(&arr[middle], middle);
            merge(arr, middle, &arr[middle], middle);
        } else {
            
            mergeSort(&arr[middle], middle+1);
            merge(arr, middle, &arr[middle], middle+1);
        }
    }
}

算法分析

算法图解

图片来自网络,如果涉及侵权请告知。

归并排序.gif

快速排序

快速排序,听名字就知道它存在的意义。它是处理大数据最快的算法之一。通过一趟排序将待排元素分隔成独立的两个部分,其中一部分元素均比另一部分的元素小(大),然后分别对这两个部分的元素进行快速排序,从而达到整个序列有序的目的

算法描述

算法实现

void quickSort(int *arr, int begin, int end) {
    
    if (begin < end && end - begin > 1) {//如果带排序列只有一个元素必定为有序,区间错误无法排序

        int  fontIndex = begin, backIndex = end, standard = arr[backIndex];
        while (fontIndex < backIndex) {//从前扫描的下标等于从后扫描的下标相等的时候,说明此趟排序已经将元素划分为三部分
            
            //将大于基准的元素,尽量放在待排序列的后面
            while (fontIndex < backIndex && arr[fontIndex] < standard) {
                
                fontIndex++;
            }
            if (fontIndex < backIndex) {
                
                arr[backIndex--] = arr[fontIndex];
            }
            //将小于基准的元素,尽量放在待排序列的前面
            while (fontIndex < backIndex && arr[backIndex] > standard) {
                
                backIndex--;
            }
            if (fontIndex < backIndex) {
                
                arr[fontIndex++] = arr[backIndex];
            }
        }
        arr[fontIndex] = standard;//将基准放在小于基准序列和大于基准序列的中间
        quickSort(arr, begin, fontIndex-1);
        quickSort(arr, fontIndex+1, end);
    }
}

void quickSortFunction(int *arr, int count) {
    
    quickSort(arr, 0, count-1);
}

算法分析

算法图解

图片来自网络,如果涉及侵权请告知。

快速排序.gif

堆排序

堆排序是指利用堆这种数据结构所设计的一种排序算法。堆积四一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的建制或索引总是小(大)于它的父节点。

算法描述

堆排序可以用二叉树的结构来表示,但是在实际的应用中我问还可以更节省内存,因为完全二叉树的特性我们可以使用数字来简单的表示它。注意在数据量很大的时候数组和二叉树这两种表示法,它们耗用的内存还是有很大差异的

算法实现(C语言)

void heapOne(int *arr, int maxIndex, int index) {
    
    int leftChildIndex = index * 2 + 1;//左孩子在数组中的下标
    int rightChildIndex = index * 2 + 2;//右孩子在数组中的下标
    if (leftChildIndex >= maxIndex && rightChildIndex >= maxIndex) {//已经是叶子结点
        
        return;
    }
    int leftChildValue = INT_MAX;
    int rightChildValue = INT_MAX;
    if (leftChildIndex <= maxIndex) {
        
        leftChildValue = arr[leftChildIndex];
    }
    if (rightChildIndex <= maxIndex) {
        
        rightChildValue = arr[rightChildIndex];
    }
    if (arr[index] < leftChildValue && arr[index] < rightChildValue) {//满足堆的要求
        
        return;
    } else {//找出左右孩子中最大的和它交换,然后继续调整直到满足堆的要求
        
        if (leftChildValue < rightChildValue) {
            
            int temp = arr[index];
            arr[index] = arr[leftChildIndex];
            arr[leftChildIndex] = temp;
            heapOne(arr, maxIndex, leftChildIndex);
        } else {
            
            int temp = arr[index];
            arr[index] = arr[rightChildIndex];
            arr[rightChildIndex] = temp;
            heapOne(arr, maxIndex, rightChildIndex);
        }
    }
}


void heapSortFunction(int *arr, int count) {
    
    for (int i = (count-1)/2; i >= 0; i--) {
        
        heapOne(arr, count-1, i);
    }
    while (count > 0) {
        
        int temp = arr[0];
        arr[0] = arr[count-1];//将堆顶元素用最后一个叶子结点元素代替
        count--;
        heapOne(arr, count, 0);
        arr[count] = temp;//为了节约内存,将堆顶的元素从数组的最后向前逐一放置
    }
}

算法分析

算法图解

图片来自网络,如果涉及侵权请告知。

堆排序.gif

计数排序

计数排序的核心在于将待排序列的数据值转换为键存储在额外开辟的数组空间中。作为一种线性时间复杂的排序,计数排序要求输入的数据必须是确定范围的整数

算法描述

算法实现

void countingSortFunction(int *arr, int count) {
    
    if (count > 1) {
        
        int min = arr[0], max = arr[0];
        for (int i = 1; i < count; i++) {//找出最大和最小值
            
            if (arr[i] > max) {
                
                max = arr[i];
            }
            if (arr[i] < min) {
                
                min = arr[i];
            }
        }
        if (min != max) {//所有元素不全部相等
            
            int countArr[max-min+1];
            for (int i = 0; i < max-min+1; i++) {
                
                countArr[i] = 0;
            }
            
            for (int i = 0; i < count; i++) {//计数
                
                countArr[arr[i]-min] += 1;
            }
            int j = 0;
            for (int i = 0; i < max-min+1; i++) {//填充
                
                while (countArr[i] != 0) {
                    
                    arr[j] = min + i;
                    countArr[i] -= 1;
                    j++;
                }
            }
        }
    }
}

算法分析

算法图解

图片来自网络,如果涉及侵权请告知。

计数排序.gif

总结

由于个人能力有限,对于排序算法我也只能列举和总结道这里了。如果大家还知道更加好的排序算法,希望能共享出来相互学习。此篇博客写完,我只想说前辈们用了数年甚至一生苦心专研出来的算法,不管是算法本身还是逻辑思维方法很值得我推敲。身为一个算法学习的托班学生,难免会有所疏忽,欢迎各位批评指点。

[ 相关代码] https://github.com/LHCoder2016/SortAlgorithm.git
[ 欢迎讨论] huliuworld@yahoo.com

上一篇 下一篇

猜你喜欢

热点阅读