Code基础——2.排序

常用的排序算法c和python代码实现

1.交换式排序:冒泡排序、快速排序

2.选择式排序:简单选择排序、堆排序

3.插入式排序:简单插入排序、希尔排序

4.归并式排序:归并排序递归实现、归并排序非递归实现

1.交换式排序

交换式排序:冒泡排序、快速排序

冒泡排序

冒泡排序(Bubble Sort)的基本思想为两两比较相邻的数据,如果顺序为反序则进行交换,直到没有反序的记录为止。

冒泡排序可以有几种写法,其三种不同实现的代码如下:

#include <stdio.h>

void Swap(int *a , int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}

//最简单的排序,从第一个元素开始向后与每一个元素进行比较,交换得到最小的元素,放在第i个位置
//这样的排序进行了较多次无用的比较,当然,这并不是所谓的冒泡排序
void SimpleBubble(int array[] , int length){
    for(int i = 0 ; i < length ; i++){
        for(int j = i+1 ; j < length ; j++){
            if(array[i] > array[j]){
                Swap(&array[i],&array[j]);
            }
        }
    }
}

//从第一个位置开始,由下往上两两元素进行比较,判断并交换得到最小值
//这样排序依次循环确定第i个位置的元素
void LittleBubble(int array[] ,int length){
    for(int i =0 ; i < length ; i++){
        for(int j = length -1 ; j > i ;j --){
            if(array[j] < array[j-1]){
                Swap(&array[j],&array[j-1]);
            }
        }
    }
}

//增加标志位isSwap来表示是否存在反序或者是否进行过交换操作
//直到序列没有反序记录为止
void BubbleSort(int array[] , int length){
    int isSwap = 1;
    for(int i = 0 ; i < length ; i ++){
        if(isSwap){
            isSwap = 0;
            for(int j = length -1 ; j > i ; j --){

                if(array[j] < array[j-1]){
                    Swap(&array[j],&array[j-1]);
                    isSwap = 1;
                }
            }
        }
    }
}

void Print(int array[] , int length){
    for (int i = 0 ; i < length ;i++){
        printf(" %d",array[i]);
    }
}

int main(){
    int array[] = {6,5,3,1,0,2,9,8,4,7};
    BubbleSort(array,10);
    Print(array,10);
    return 0;
}

python版本:

#Sort Algorithm Python Version
class SortPy:
    # SimpleBubble
    def SimpleBubble(self, l):
        for i in range(0, len(l)):
            for j in range(i + 1, len(l)):
                if l[i] > l[j]:
                    l[i], l[j] = l[j], l[i]

    # littleBubble
    def littleBubble(self, l):
        for i in range(0, len(l)):
            for j in range(len(l) - 1, i, -1):
                if l[j] < l[j - 1]:
                    l[j], l[j - 1] = l[j - 1], l[j]

    # bubbleSort
    def BubbleSort(self, l):
        isSwap = 1
        for i in range(0, len(l)):
            if isSwap:
                isSwap = 0
                for j in range(len(l) - 1, i, -1):
                    if l[j] < l[j - 1]:
                        l[j], l[j - 1] = l[j - 1], l[j]
                        isSwap = 1


if __name__ == "__main__":
    l = [2, 4, 4, 455, 6, 77, 5, 43]
    sortPy = SortPy()
    sortPy.BubbleSort(l)
    print(l)

快速排序

快速排序(Quick Sort)是在实践中最快的已知排序算法,平均运行时间是O(N log N)。快速排序之所以快是因为其精炼的、高度优化的内部循环。最坏情况的性能为O(N2),如今高度优化后的快速排序更加简单易懂。

和归并排序一样,快速排序也是一种分治的递归算法。

将数组array进行快速排序QuickSort的基本算法由以下四步组成:

  • 1.如果数组长度为0或者1,则直接返回;
  • 2.选取pivot,可采用Median3或其他方法来获取枢纽元素pivot;
  • 3.划分子集;
  • 4.递归调用QuickSort;

交换式快速排序C代码示例,简化代码这里选取索引为0的为pivot

#include <stdio.h>

void Swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

void Quick_Sort(int array[], int left, int right)
{
    if (left >= right)
        return;

    int i = left,pivot = left ,j = right;
    //Notice1:只有当i<j时才进入循环,i与j循环移动与pivot位置进行比较
    while (i < j) {
        //Notice2:指示哨兵j所处元素依次与pivot处元素进行比较,如果大于或等于则继续j--向前移动;如果小于pivot处的值,则跳出该次while循环
        while (array[j] >= array[pivot] && i<j ) {j--;}
        //Notice3:指示哨兵i所处元素依次与pivot处元素进行比较,如果小于或等于则继续i++向后移动;如果大于pivot处的值,则跳出该次while循环
        while (array[i] <= array[pivot] && i<j ) {i++;}

        //Notice4:当j与i都跳出while循环时,比较此时i与j的大小,若i任然小于j,则交换两个位置的元素,再次进入外部while循环;如果i已经大于或者等于j,即可break跳出循环,确定此次pivot处的最终值
        if (i < j) {
            Swap(&array[i], &array[j]);
        }
        else {
            break;
        }
    }
    //Notice5:交换i与pivot处元素,即确定该pivot处元素最终位置,已i位置为界完成此次子集划分
    Swap(&array[i], &array[pivot]);
    //Notice6:递归调用快速排序
    Quick_Sort(array, left, i - 1);
    Quick_Sort(array, i + 1, right);
}

void QuickSort(int array[], int length)
{
    Quick_Sort(array, 0, length -1);
}

int main()
{
    int L[] = { 2,4,4,455,6,77,5,43 };
    int len = sizeof(L)/sizeof(L[0]);
    QuickSort(L,len);
    for(int i = 0 ; i <len ; i++){
        printf("array[%d] = %d\n",i,L[i]);
    }
    while (1) {}
}

快速排序Python实现

# Sort Algorithm Python Version
class SortPy:

    # quickSort
    def quick_sort(self, l, left, right):
        if left >= right:
            return
        i, pivot, j = left, left, right
        while i < j:
            while l[j] >= l[pivot] and i < j:
                j -= 1
            while l[i] <= l[pivot] and i < j:
                i += 1
            if i < j:
                l[i], l[j] = l[j], l[i]
            else:
                break
        l[i], l[pivot] = l[pivot], l[i]
        self.quick_sort(l, left, i - 1)
        self.quick_sort(l, i + 1, right)

    def QuickSort(self, l):
        self.quick_sort(l, 0, len(l) - 1)

选择式排序

选择类排序:简单选择排序、堆排序

简单选择排序

简单选择排序(Simple Selection Sort),基本思想是:标记第i个元素为最小值下标min开始向后进行遍历比较,不断更新最小值下标min,结束该次循环后判断min是否改变,若改变即交换i位置元素及min位置的最小元素。

void SelectSort(int array[] , int length){
    int min;
    for(int i = 0 ; i <length ; i++){
        min  = i ;  //Notice1:以第一个元素为最小开始向后遍历比较
        for(int j = i+1 ; j < length ; j++){  //Notice2:j从i+1开始向后遍历
            if(array[j] < array[min]){  //Notice3:每次都是array[j]与array[min]进行比较,来确定和更新最小值所在下标
            min = j;
            }
        }
        if(min != i){
            Swap(&array[i] ,&array[min]);
        }
    }
}

选择排序Python实现

# Sort Algorithm Python Version
class SortPy:

    # selectsort
    def SelectSort(self, l):
        for i in range(len(l)):
            min = i
            for j in range(i+1, len(l)):
                if l[j] < l[i]:
                    min = j
            if min != i:
                l[i], l[min] = l[min], l[i]

堆排序

堆排序(Heap Sort)是一个非常稳定的算法,排序平均使用的比较只比最坏情况界指出的略少。

void AdjustHeap(int array[] , int i , int length){
    //Notice2:保存开始节点的值为temp,减少直接交换的次数
    int temp = array[i];
    for(int j = i*2 +1 ; j <length ; j = j*2+1){
        //Notice3:循环对比该节点的子结点中的值与temp中的值
        //为i的位置找到当前结点及其子结点之中最大的值
        if(j+1 < length && array[j] < array[j+1])
            j++;
        if(temp > array[j] )
            break;
        array[i] = array[j];
        i = j;
    }
    //Notice4:最后将temp中保存的值放置在合适的位置
    array[i] = temp;
}

void HeapSort(int array[] ,int length){
    //Notice1:首先进行的是第一次调整堆,从堆的最后一个非叶子结点开始
    //由右向左、由下至上构造第一个最大堆
    for(int i = length/2 - 1 ; i >= 0 ; i --){
        AdjustHeap(array , i ,length);
    }

    //Notice5;第一次最大堆构造完成之后,位于索引0处的元素即为最大值
    //将最大值放置末尾,再进行调整堆,之后进行循环操作即可得到有序
    for(int i = length -1 ; i > 0 ; i --){
        Swap(&array[0],&array[i]);
        AdjustHeap(array, 0, i );
    }
}

堆排序python实现:

# Sort Algorithm Python Version
class SortPy:

    # heapsort
    def HeapSort(self, l):
        for i in range(len(l) // 2 - 1, -1, -1):
            self.AdjustHeap(l, i, len(l))
        for i in range(len(l)-1, 0, -1):
            l[0], l[i] = l[i], l[0]
            self.AdjustHeap(l, 0, i)

    def AdjustHeap(self, l, i, length):
        temp = l[i]
        j = 2 * i + 1
        while j < length:
            if j + 1 < length and l[j] < l[j + 1]:
                j = j + 1
            if temp > l[j]:
                break
            l[i] = l[j]
            i = j
            j = 2 * i + 1
        l[i] = temp

if __name__ == "__main__":
    l = [2, 4, 4, 455, 6, 77, 5, 43]
    sortPy = SortPy()
    sortPy.HeapSort(l)
    print(l)

插入式排序

插入类排序:直接插入排序、希尔排序

简单插入排序

简单插入排序(Insertion Sort)是最简单的排序算法之一,主要思想是保证位置0到第i-1位置上的元素为已排序状态,即插入排序利用这样的事实,从i位置循环进行排序。

void InsertionSort(int array[] , int length ){
    int i,j,temp;
    //Notice1:开始以第一个数据为有序序列,从第二个数据开始排序
    for(i = 1 ; i <length ; i++){
        if(array[i] < array[i-1]){  //Notice2:当当前数据大于前一个时,开始向前插入
            temp = array[i];  //保存此时的值,为前方较大元素空出位置
            for(j = i -1 ; j>=0 && array[j] > temp ; j--){  //向前循环直至下标小于0,或者值比当前值更小
                array[j+1] = array[j];  //依次后移
            }
            array[j+1] = temp;  //此时j位置的元素小于temp的值,所以将保存的temp值赋予其后位j+1
        }
    }
}

插入排序Python实现

# Sort Algorithm Python Version
class SortPy:
    # insertsort
    def InsertSort(self, l):
        for i in range(1,len(l)):
            if l[i] < l[i - 1]:
                j, temp = i - 1, l[i]
                while j >= 0 and temp < l[j]:
                    l[j + 1] = l[j]
                    j = j - 1
                l[j + 1] = temp

if __name__ == "__main__":
    l = [2, 4, 4, 455, 6, 77, 5, 43]
    sortPy = SortPy()
    sortPy.InsertSort(l)
    print(l)

希尔排序

希尔排序(Shell Sort)是冲破二次时间屏障的第一批算法之一。主要思想是:通过比较一定间隔的元素来工作;各趟比较所用的距离(希尔增量)随着算法的进行而逐渐减小,直到比较相元素的最后一趟排序为止。因此,希尔排序也称为缩小增量排序。

void ShellSort(int array[] , int length)
{
    int i,j,temp,gap;
    int judgeCount = 0, changeCount = 0;
    //Notice1:设置希尔增量序列初始值 gap = length/2 ,一直循环值gap=1进行最后一次插入排序
    for(gap = length/2 ; gap >0 ; gap /=2){
    //Notice2:内层嵌套一个直接插入循环
        for(i = gap ; i < length ; i++ ){
            judgeCount++;
            if(array[i] < array[i - gap]){
                temp = array[i];
                for(j = i - gap ; j >= 0 && array[j] > temp ; j -=gap){
                    array[j+gap] = array[j];
                    changeCount++;
                }
                array[j+gap] = temp;
            }
        }
    }
    printf("Judge Count : %d ,Change Count : %d .\n", judgeCount,changeCount);
}

希尔排序Pytho实现

# Sort Algorithm Python Version
class SortPy:
    # shellsort
    def ShellSort(self, l):
        gap = len(l) // 2
        while gap > 0:
            for i in range(gap,len(l)):
                if l[i] < l[i - gap]:
                    j, temp = i - gap, l[i]
                    while j >= 0 and temp < l[j]:
                        l[j + gap] = l [j]
                        j = j - gap
                    l[j + gap] = temp
            gap = gap // 2

if __name__ == "__main__":
    l = [2, 4, 4, 455, 6, 77, 5, 43]
    sortPy = SortPy()
    sortPy.ShellSort(l)
    print(l)

归并式排序

归并类排序:归并排序递归实现与非递归实现。

递归实现

#include<iostream>

//归并排序算法核心思想,对两个有序子列进行归并
void Merge(int array[], int tempArray[], int left, int right, int rEnd){
    //两个有序子列起始分别为left,lEnd,right,rEnd
    int length = rEnd - left + 1;
    int lEnd = right - 1;
    int temp = left;
    while (left <= lEnd && right <= rEnd){
        if(array[left] < array[right])
            tempArray[temp++] = array[left++];
        else
            tempArray[temp++] = array[right++];
    }
    while(left <= lEnd)
        tempArray[temp++] = array[left++];
    while(right <= rEnd)
        tempArray[temp++] = array[right++];
    for(int i = 0; i < length; i++, rEnd--){
        array[rEnd] = tempArray[rEnd];
    }
}

void Merge_Sort(int array[], int tempArray[], int left, int rEnd){
    if(left < rEnd){
        int mid = (left + rEnd)/2;
        //递归调用Merge_Sort
        Merge_Sort(array, tempArray, left, mid);
        Merge_Sort(array, tempArray, mid+1, rEnd);
        Merge(array, tempArray, left, mid+1, rEnd);
    }
}

void MergeSort(int array[], int len){
    int *tempArray = new int[len];
    Merge_Sort(array, tempArray, 0, len-1);
    delete[](tempArray);
}

int main()
{
    int L[] = { 2,4,4,455,6,77,5,43};
    int len = sizeof(L)/sizeof(L[0]);
    MergeSort(L, len);
    for(int i = 0; i < len; i++)
        std::cout << L[i] <<std::endl;
    while(1){}
}

归并排序Python实现:
可使用Python的切片操作来简化代码,在MergeSort函数开始时对待排序数组l进行切片操作,切片之后原待排序数组可以在后续的归并操作中用来贮存排好序的结果

# Sort Algorithm Python Version
class SortPy:
    # mergesort
    def MergeSort(self, l):
        if len(l) <= 1:
            return l
        mid = len(l) // 2
        leftL = l[:mid]
        rightL = l[mid:]
        self.MergeSort(leftL)
        self.MergeSort(rightL)
        # MergeSort`s core part --- merget part
        i, j, k = 0, 0, 0
        while i < len(leftL) and j < len(rightL):
            if leftL[i] < rightL[j]:
                l[k] = leftL[i]
                i += 1
            else:
                l[k] = rightL[j]
                j += 1
            k += 1
        while i < len(leftL):
            l[k] = leftL[i]
            i += 1
            k += 1
        while j < len(rightL):
            l[k] = rightL[j]
            j += 1
            k += 1

if __name__ == "__main__":
    l = [2, 4, 4, 455, 6, 77, 5, 43]
    sortPy = SortPy()
    sortPy.MergeSort(l)
    print(l)

非递归实现

#include<iostream>
#include<algorithm>
using namespace std;

//归并排序算法的核心,对两个有序子列进行归并
void Merge(int array[], int tempArray[], int left, int right, int rEnd){
    int length = rEnd - left + 1;
    int lEnd = right - 1;
    int temp = left;
    while(left <= lEnd && right <= rEnd){
        if(array[left] < array[right])
            tempArray[temp++] = array[left++];
        else
            tempArray[temp++] = array[right++];
    }
    while(left <= lEnd)
        tempArray[temp++] = array[left++];
    while(right <= rEnd)
        tempArray[temp++] = array[right++];
    for(int i = 0; i < length; i++, rEnd--)
        array[rEnd] = tempArray[rEnd];
}

void MergeSortIter(int array[], int length){
    int *tempArray = new int[length];
    int i = 1;
    while(i < length){
        int left = 0;
        while(left < length){
            int right = left + i;
            int rEnd = min(left + 2*i, length-1);
            if(right < rEnd)
                Merge(array, tempArray, left, right, rEnd);
            left += i*2;
        }
        i *= 2;
    }
    delete[](tempArray);
}

int main()
{
    int L[] = { 2,4,4,455,6,77,5,43};
    int len = sizeof(L)/sizeof(L[0]);
    MergeSortIter(L,len);
    for(int i = 0; i < len; i++)
        cout << L[i] << endl;
    while(1){}
}

归并排序非递归python实现:

# Sort Algorithm Python Version
class SortPy:
    # mergesort-non recursive
    def MergeSortIter(self, l):
        tempL = l[:]
        i = 1
        while i < len(l):
            low = 0
            while low < len(l):
                mid = low + i
                high = min(low + 2 * i, len(l) - 1)
                if mid < high:
                    self.MergeIter(l, tempL, low, mid, high)
                low += 2 * i
            i *= 2

    def MergeIter(self, l, tempL, low, mid, high):
        i, j, k = low, mid, low
        while i < mid and j <= high:
            if l[i] < l[j]:
                tempL[k] = l[i]
                i += 1
                k += 1
            else:
                tempL[k] = l[j]
                j += 1
                k += 1
        if i < mid:
            tempL[k:high + 1] = l[i:mid]
        if j <= high:
            tempL[k:high + 1] = l[j:high + 1]
        l[low:high + 1] = tempL[low:high + 1]

if __name__ == "__main__":
    l = [2, 4, 4, 455, 6, 77, 5, 43]
    sortPy = SortPy()
    sortPy.MergeSortIter(l)
    print(l)

REF

书籍:

数据结构与算法分析、大话数据结构

posted @ 2018-07-28 19:15  SylvanYan  阅读(342)  评论(0编辑  收藏  举报
TOP