选择类排序:
1.简单选择排序:
直接从数组中选择最小的记录和第一个记录交换位置,循环.
示例代码如下:
void SelectSort(int r[], int b){int i, j, k;int x;for(i = 1; i < n; i++){k = i;for(j = i+1; j <= n; j++){if(r[j] < r[k])//选择最小的记录,得到在数组中的位置 k = j;}if(k != i){x = r[i];r[i] = r[k];r[k] = x;}//交换位置 }
}
时间复杂度:O(n^2).
2.树形选择排序(锦标赛排序):
与简单选择排序不同点是,占用空间更多,保留了之前的比较结果
每一个记录看作叶子节点,两两比较,选出最小的为双亲,进一步递归向上,找出根,比较成功后,该记录对应的叶子节点置为无穷;
进一步两两比较重复上述过程,直到记录全部输出
时间复杂度:O(nlog2(n)).
3.堆排序:
排序过程中把向量中储存的数据看作一颗完全二叉树来进行操作
重建堆:
大堆,筛选最大的元素出去,然后最后的元素补根节点,调整堆使最大的元素在最上面
算法如下:
void sift(Type r[], int k, int m){//r[k...m]是以r[k]为根的完全二叉树,调整r[k]使之满足堆的性质 int i, j, t, x;t = r[k];x = r[k].key; i = k;j = 2 * k;//j指向t的左孩子bool finished = false;while(j <= m && !finished){if(j + 1 <= m && r[j].key < r[j+1].key){j++;}//得到左右孩子中记录关键字较大的位置坐标 if(x >= r[j].key) //如果满足堆的性质,上面的比孩子大 finished = true;else{r[i] = r[j];i = j;j = 2 * i;}} r[i] = t;
} 建初堆:
void crt_heap(Type r[], int n)
{//对r[]建立堆, n为数组长度int i;for(i = n / 2; i >= 1; i--)//i指向最后一个非叶子节点 sift(r, i, n); } 堆排序算法:
void HeapSort(Type r[], int n)
{crt_heap(r, n);for(i = n; i>= 2 ;--i){r[0] = r[1];r[1] = r[i];r[i] = r[0];//最后一个元素和第一个元素交换位置,把最大的换到最后面去,以此达到升序排列x sift(r, 1, i-1);}} 时间复杂度:O(nlog2(n)).
算法是不稳定的, 空间复杂度O(1) .
归并类排序:将两个或两个以上的有序表合并成一个表
两个有序子序列合并算法:
void Merge(Type r1[], int low, int mid, int high, Type r2[])
{//r1[low...mid]和r1[mid+1,..high]分别按照关键字有序排列 ,合并存放在r2[]中int i, j, k;i = low;j = mid + 1;k = low;while(i <= mid && j <= high){if(r1[i].key <= r1[j].key)r2[k++] = r[i++];elser2[k++] = r[j++];}while(i <= mid){r2[k++] = r1[i++];}while(j <= high){r2[k++] = r1[j++];}} 路归并排序的递归算法:
void MSort(Type r1[], int low, int high, Type r3[])
{//r1[low...high]排序后放在r3[low...high] 中, r2为辅助空间Type *r2;int mid;r2 = (Type *)malloc(sizeof(Type) * (high - low + 1));if(low == high) r3[low] = r1[low];//这个是递归最终退出条件else{//r1前半段放到r2前半段中,同理对于后半段,再将r2合并排序 mid = (low + high) / 2;MSort(r1, low, mid, r2);MSort(r1, mid + 1, high, r2); Merge(r2, low, mid, high, r3);} free(r2);} 调用:
void MergeSort(Type r[], int n){MSort(r, 1, n, r);
}