DreamJudge-1106-排序2

1.题目描述

Time Limit: 1000 ms
Memory Limit: 256 mb

编写程序实现直接插入排序、希尔排序(d=5)、直接选择排序、快速排序和二路归并排序算法。

输入输出格式

输入描述:

第一行是待排序数据元素的个数; 待排序的数据元素。

输出描述:

直接插入排序后的结果 一趟希尔排序后的结果 直接选择排序后的结果 快速排序后的结果 一趟二路归并排序后的结果

输入输出样例

输入样例#:

10
50 36 41 19 23 4 20 18 12 22

输出样例#:

4 12 18 19 20 22 23 36 41 50
4 20 18 12 22 50 36 41 19 23
4 12 18 19 20 22 23 36 41 50
4 12 18 19 20 22 23 36 41 50
36 50 19 41 4 23 18 20 12 22

2.题解

2.1 多排序总结

思路

这里一共总结了:
1.插入排序(保证前面的一段有序序列,并不断往后插入),
2.希尔排序(这里的是一次希尔排序,步长d=5, 相当于只进行一次d=5的插排即可,无需将 d = n / 2, d = d / 2 这样迭代步长),
比较新的一种是基于插入排序优化的希尔排序,基于插入排序优化,将原有的插排转换为分组插排,是一种分治思想,由于步长拉大,较小的数据能更快接近前面他应该在的位置,而不用一个一个往前判断,较大的同理。
3.直接选择排序(保证每次遍历最首段的数是最小的),
4.二路快速排序(这里采用分治思想,确定一个基准点,然后比他小的放左边,比他大的放右边,最后将这个数放在left和right重合处,也就是他应该在的地方,这样该数位置确定,左右数列被分区,在更小的数列中进行迭代重复上述操作,每次确定一个基准点位置)

  • 时间复杂度:平均情况 nlog(n)

5.二路归并排序(分治思想,分组再归并,确定一个mid位置,然后分为左右两组,通过递归保证传回来的左右数列都是有序的,然后再合并这两个数列(两个有序合并为一个操作较为简单))

代码

#include<bits/stdc++.h>
using namespace std;

vector<int> a, b, c; 

// 插入排序 
// 保证左侧一个有序数组序列 
void insertSort(vector<int> &a){
	int n = a.size();
	for(int i = 1, j; i < n; i++){
		int num = a[i];
		// 插入排序,如果大于该数,就往后移,为其空出位置;
		// 否则跳出循环,j + 1位放该数 
		for(j = i - 1; j >= 0 && a[j] > num; j--){
			a[j + 1] = a[j];
		} 
		a[j + 1] = num;
	}
}

// 希尔排序
// 希尔排序逻辑上是一组插入排序完再进行另一组的,实际代码中则不是按分组顺序,而是按数组顺序遍历,遇到哪个往前找一个gap 
void shellSort(vector<int>& arr) {
    int n = arr.size();
    // 进行分组,确定gap,且gap不断迭代 
    for (int gap = n / 2; gap > 0; gap /= 2) {
    	// 每一组的具体情况 
        for (int i = gap, j; i < n; ++i) {
            int temp = arr[i];
            // 内层是插入排序,不过间距是gap 
            for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
                arr[j] = arr[j - gap];
            }
            arr[j] = temp;
        }
    }
}

// 一次希尔排序(d = 5) 
void shellSort_d5(vector<int>& arr) {
    int n = arr.size();
    // 进行分组,确定gap,且gap不断迭代 
    int gap = 5;
	// 每一组的具体情况 
    for (int i = gap, j; i < n; ++i) {
        int temp = arr[i];
        // 内层是插入排序,不过间距是gap 
        for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
            arr[j] = arr[j - gap];
        }
        arr[j] = temp;
    } 
}


// 直接选择排序
// 保证每次最左侧的都是最小的 
void selectionSort(vector<int>& arr){
	// 表示遍历次数 
	int n = arr.size();
	for(int i = 1; i < n; i++){
		for(int j = i; j < n; j++){
			if(arr[j] < arr[i-1]){
				swap(arr[j], arr[i-1]);	
			}
		}
	}
}

// 双路快速排序 
// 分治算法 
int Paritition(vector<int>&arr, int low, int high){
	int pivot = arr[low]; // 将arr[low]作为基准点
	while(low < high){
		while(low < high && arr[high] > pivot){
			high--;
		}
		arr[low] = arr[high];
		while(low < high && arr[low] < pivot){
			low++;
		}
		arr[high] = arr[low];
	} 
	arr[low] = pivot;
	return low;
} 
// 迭代函数 
void quickSort(vector<int>& arr, int low, int high){
	// 分组 
	if(low >= high) return; // 不要忘记迭代终止条件 
	int medium = Paritition(arr, low, high);
	// 继续快排(medium位置已经确定,无需继续参与) 
	quickSort(arr, low, medium - 1);
	quickSort(arr, medium + 1, high); 
} 
void quickSort(vector<int>& arr){
	int n = arr.size();
	quickSort(arr, 0, n - 1); 
} 

// 二路归并排序
// 分治算法 
vector<int> t;
void mergeSort(vector<int>& arr, int low, int high){
	// 终止条件 
	if(low >= high) return;
	// 分治 (确保两侧都是有序的)
	int mid = (low + high) >> 1; 
	mergeSort(arr, low, mid);
	mergeSort(arr, mid + 1, high);
	// 合并 
	int cnt = 0; // 用来记录这一轮合并的个数并用作下标 
	int l = low, r = mid + 1;
	while(l <= mid && r <= high){
		if(arr[l] < arr[r]) t[cnt++] = arr[l++];
		else t[cnt++] = arr[r++]; 
	}
	// 清理剩余部分 
	while(l <= mid) t[cnt++] = arr[l++];
	while(r <= high) t[cnt++] = arr[r++];
	// 更新数组 
	for(int i = 0; i < cnt; i++){
		arr[low + i] = t[i]; 
	}
} 
// 一次归并排序(只进行最内层两个两个的排序) 
void mergeSort_once(vector<int>& arr){
	int n = arr.size();
    if(n%2==0){
        for(int i=0;i<n-1;i=i+2){
            if(a[i]>a[i+1]){
                swap(a[i],a[i+1]);
            }
        }
    }
    else{
        for(int i=0;i<n-2;i=i+2){
            if(a[i]>a[i+1]){
                swap(a[i],a[i+1]);
            }
        }        
    }
} 

// 归并排序 
void mergeSort(vector<int>& arr){
	int n = arr.size();
	t.resize(n);
//	mergeSort(arr, 0, n - 1);
	mergeSort_once(arr);
}


// 打印数组 
void printArr(vector<int> &x){
	for(int num : x){
		cout << num << " "; 
	}
	cout << endl;
}

int main(){
	int n;
	cin >> n;
	for(int i = 0; i < n; i++){
		int num;
		cin >> num;
		a.push_back(num);
	}
	b.resize(a.size());
	copy(a.begin(), a.end(), b.begin());
	
	// 插入排序 
	insertSort(a);
	printArr(a);
	// 希尔排序 
	copy(b.begin(), b.end(), a.begin());
	shellSort_d5(a);
	printArr(a);	
	// 直接选择排序 
	copy(b.begin(), b.end(), a.begin());
	selectionSort(a); 
	printArr(a);
	// 双路快速排序 
	copy(b.begin(), b.end(), a.begin());
	quickSort(a); 
	printArr(a);
	// 一次二路归并排序 
	copy(b.begin(), b.end(), a.begin());
	mergeSort(a); 
	printArr(a);

	return 0;
} 
posted @ 2024-06-14 17:19  DawnTraveler  阅读(3)  评论(0编辑  收藏  举报