排序

快速排序

  • 平均时间复杂度O(nlogn),最坏时间复杂度O(n^2),时间开销与待排数组初始状态有关,当待排数组有序时,效率最低。
  • 空间复杂度最坏O(n),最好O(logn)
int partition(int a[], int low, int high){
    int pivot = a[low];         //表中第一个元素作为枢轴进行划分
    int i = low, j = high;
    while(i < j){
        while(i < j && a[j] >= pivot)
            --j;
        a[i] = a[j];    //比枢轴小的元素移到左边       
        while(i < j && a[i] <= pivot)
            ++i;
        a[j] = a[i];    //比枢轴大的元素移到右边
    }
    a[i] = pivot;       //枢轴元素存放位置
    return i;           //返回划分的枢轴位置
}

void quickSort(int a[], int low, int high){
    if(low < high){        //递归条件
        int pos = partition(a, low, high);      //划分左右子表
        quickSort(a, low, pos-1);           //左子表递归
        quickSort(a, pos+1, high);          //右子表递归
    }
}

归并排序

  • 时间复杂度为O(nlogn),与初始状态无关
  • 空间复杂度O(n),需要辅助数组b
//a[low...mid],a[mid+1...high]为有序的两个子表,将其归并成a[low...high]有序的表
void merge(int a[], int low, int mid, int high){
    int i, j, k;
    int *b = (int *)malloc(sizeof(int) * (high-low+1));  //辅助数组
    i = low, j = mid+1, k = 0;
    while(i <= mid && j <= high){   //较小者加入a
        if(a[i] <= a[j]){
            b[k++] = a[i++];
        }
        else{
            b[k++] = a[j++];
        }
    }
    while(i <= mid){        //前表有剩余,直接加入归并表
        b[k++] = a[i++];
    }
    while(j <= high){       //后表有剩余,直接加入归并表
        b[k++] = a[j++];
    }

    //b中存放归并好的表,写回a中即可,注意a中数据位置要相对low偏移    
    for(i = 0; i < k; ++i){
        a[i+low] = b[i];
    }
}

void mergeSort(int a[], int low, int high){
    if(low < high){
        int mid = (low + high) / 2;         //中间划分两个子表
        mergeSort(a, low, mid);             //左子表递归排序
        mergeSort(a, mid + 1, high);    //右子表递归排序
        merge(a, low, mid, high);           //归并左右子表
    }
}

堆排序

  • 时间复杂度O(nlogn),与初始状态无关
  • 空间复杂度O(1)
//k为待调整子树的根节点
void heapAdjust(int a[], int k, int n){
    int i;
    a[0] = a[k];    //a[0]暂存子树根节点
    for(i = 2*k; i <= n; i*=2){
        if(i+1 <= n && a[i+1]>a[i])    //i指向左右孩子key较大者(右孩子存在的前提下)
            i++;
        if(a[0] >= a[i])    //根>=左右孩子,则调整完成
            break;
        else{
            a[k] = a[i];    //左右孩子较大者上移到父节点位置
            k = i;          //根节点尝试"下坠",继续向下筛选
        }
    }
    a[k] = a[0];    //根节点最终应该存放的位置k
}

//建立大根堆
void buildMaxHeap(int a[], int n){
    int i;
    for(i = n/2; i >= 1; --i){      //从第一个非叶子节点a[n/2]开始调整堆
        heapAdjust(a, i, n);
    }
}

//堆排序:①建堆;②堆顶堆底元素交换,调整堆
void heapSort(int a[], int n){
    buildMaxHeap(a, n);
    int i, temp;
    for(i = n; i > 1; --i){     //n-1趟调整建堆过程
        //堆顶元素和堆底元素交换,堆底为有序
        //swap(a[i], a[1]);
        temp = a[i];
        a[i] = a[1];
        a[1] = temp;
        heapAdjust(a, 1, i-1);      //调整,把剩余的i-1个元素整理成堆
    }
}
posted @ 2022-12-31 08:35  dctwan  阅读(13)  评论(0编辑  收藏  举报