数据结构实验16-排序1

A. DS排序--希尔排序

题目描述

给出一个数据序列,使用希尔排序算法进行降序排序。

间隔gap使用序列长度循环除2直到1

输入

第一行输入t,表示有t个测试示例
第二行输入n,表示第一个示例有n个数据(n>1)
第三行输入n个数据,都是正整数,数据之间用空格隔开

2
6
111 22 6 444 333 55
8
77 555 33 1 444 77 666 2222
以此类推

输出

对每组测试数据,输出每趟排序结果。不同组测试数据间用空行分隔。

444 333 55 111 22 6
444 333 111 55 22 6

444 555 666 2222 77 77 33 1
666 2222 444 555 77 77 33 1
2222 666 555 444 77 77 33 1
解析:希尔排序是什么?

希尔排序原理:
希尔排序属于插入类排序,是 将整个有序序列分割成若干小的子序列 分别进行 插入排序。
具体原理可看下图:
按照一定的规则,将数组分为多个组,然后每个组分别进行插入排序

在这里插入图片描述

 

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
    int t;
    cin>>t;
    while (t--){
        int n;
        cin>>n;
        int arr[100];
        for (int i = 0; i < n; ++i) {
            cin>>arr[i];
        }
        int gap=n/2;
        while (gap>=1){
            for (int i = 0; i < n; ++i) {
                int ii=i;vector<int>v;
                if(ii+gap<n){
                    while (ii<n){
                        v.push_back(arr[ii]);
                        ii+=gap;
                    }
                    sort(v.rbegin(),v.rend());ii-=gap;
                    while (!v.empty()){
                        arr[ii]=v.back();
                        v.pop_back();
                        ii-=gap;
                    }
                }
            }
            for (int i = 0; i < n-1; ++i) {
                cout<<arr[i]<<" ";
            }cout<<arr[n-1]<<endl;
            gap/=2;
        }cout<<endl;
    }
}

B. DS排序--直接插入排序

题目描述

给出一个数据序列,使用直接插入排序算法进行升序排序。

输入

第一行输入t,表示有t个测试示例

第二行输入n,表示第一个示例有n个数据(n>1)

第三行输入n个数据,都是正整数,数据之间用空格隔开

以此类推

2
5
111 22 6 444 333
6
21 25 49 25 16 8

输出

对每组测试数据,输出每趟排序结果。不同组测试数据间用空行分隔。

22 111 6 444 333
6 22 111 444 333
6 22 111 444 333
6 22 111 333 444

21 25 49 25 16 8
21 25 49 25 16 8
21 25 25 49 16 8
16 21 25 25 49 8
8 16 21 25 25 49

解析:直接插入排序(Straight Insertion Sort)是一种最简单的排序方法,其基本操作是将一条记录插入到已排好的有序表中,从而得到一个新的、记录数量增1的有序表。

每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。第一趟比较前两个数,然后把第二个数按大小插入到有序表中; 第二趟把第三个数据与前两个数从后向前扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。(此处没设置哨兵)

时间复杂度为:O(n²)
 


#include <iostream> 
using namespace std;
void Print(int array[], int length) {	//自定义输出函数,每执行一次打印一次序列 
	for (int i = 0; i < length; i++) {
		cout << array[i];
		if (i!=length - 1)
		{
			cout << " ";
		}
	}
	cout << endl;
}
void InsertSort(int array[], int length) {
	for (int i = 1; i < length; i++) {		//第1个数是有序的,所以从第2个数开始遍历,依次插入
		int j = i - 1;					//前i-1个数都是有序序列(由小到大),只要a[j]比temp大,就将此数后移
		int temp = array[i];
		for (j = i - 1; j >= 0 && array[j] > temp; j--) {//a[j]小于 temp 时循环结束,结束后应将 temp 赋值给a[j+1]
			array[j + 1] = array[j];	//将 a[j] 后移一位 
		}
		array[j + 1] = temp;			//将 temp 赋值给a[j+1]
		Print(array, length);
	}
}
int main() {
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		cin >> n;
		int* array = new int[n];
		for (int i = 0; i < n; i++)
		{
			cin >> array[i];
		}
		//Print(array, n);			//先打印原始序列 
		InsertSort(array, n);
		cout << endl;
	}
	return 0;
}

C. DS内排—直插排序

题目描述

给定一组数据,使用直插排序完成数据的升序排序

--程序要求--

若使用C++只能include一个头文件iostream;若使用C语言只能include一个头文件stdio

程序中若include多过一个头文件,不看代码,作0分处理

不允许使用第三方对象或函数实现本题的要求

输入

数据个数n,n个数据

7 34 23 677 2 1 453 3

输出

直插排序的每一趟排序结果

23 34 677 2 1 453 3
23 34 677 2 1 453 3
2 23 34 677 1 453 3
1 2 23 34 677 453 3
1 2 23 34 453 677 3
1 2 3 23 34 453 677
 


#include <iostream> 
using namespace std;
void Print(int array[], int length) {	//自定义输出函数,每执行一次打印一次序列 
	for (int i = 0; i < length; i++) {
		cout << array[i];
		if (i!=length - 1)
		{
			cout << " ";
		}
	}
	cout << endl;
}
void InsertSort(int array[], int length) {
	for (int i = 1; i < length; i++) {		//第1个数是有序的,所以从第2个数开始遍历,依次插入
		int j = i - 1;					//前i-1个数都是有序序列(由小到大),只要a[j]比temp大,就将此数后移
		int temp = array[i];
		for (j = i - 1; j >= 0 && array[j] > temp; j--) {//a[j]小于 temp 时循环结束,结束后应将 temp 赋值给a[j+1]
			array[j + 1] = array[j];	//将 a[j] 后移一位 
		}
		array[j + 1] = temp;			//将 temp 赋值给a[j+1]
		Print(array, length);
	}
}
int main() {

		int n;
		cin >> n;
		int* array = new int[n];
		for (int i = 0; i < n; i++)
		{
			cin >> array[i];
		}
		//Print(array, n);			//先打印原始序列 
		InsertSort(array, n);
		cout << endl;
	return 0;
}

D. 冒泡排序

题目描述

给定一个包含从0到n-1各一次的数组,若使用冒泡排序将其排为升序,问其中需要进行多少次交换

输入

测试数据有多组,

每组由两行组成:第一行包含正整数n(n <= 5000); 下一行包含从0到n-1的n个整数的序列。

10
1 3 6 9 0 8 5 7 4 2

输出

对于每组测试数据,

输出交换次数

22

解析:

AC代码

#include <iostream>
#include <cstdio>
using namespace std;
void bubble_sort(int * arr, int len) 
{
    int i, j;
    int k = 0;
    for (i = 0; i < len - 1; i++)
        for (j = 0; j < len - 1 - i; j++)
            if (arr[j] > arr[j + 1])
            {
                swap(arr[j], arr[j + 1]);
                k++;
            }
    cout << k << endl;
}
int main() {
    int t;
    while(scanf("%d",&t)!=EOF)
    {
      
    int* arr = new int[t];
    for (int i = 0; i < t; i++)
    {
        cin >> arr[i];
    }
    bubble_sort(arr, t);
    }
}

E. DS排序—快速排序

题目描述

输入一组数据,用快速排序进行升序排序。

输入

测试次数t

每组测试数据为:

数据个数n,n个数字

输出

对每组测试数据,输出快速排序每趟排好的数字及位置(位置从1开始)。不同组测试数据的输出以空行分隔。

快排板子

#include <iostream>

using namespace std;

void quick_sort(int *arry,int low,int high)
{
	if(low>=high)
	return;
	
	int i=low-1,j=high+1,x=arry[low+high>>1];
	
	while(i<j)
	{
		do i++;while(arry[i]<x);
		do j--;while(arry[j]>x);
		
		if(i<j) swap(arry[i],arry[j]);
	} 
	
	quick_sort(arry,low,j);
	quick_sort(arry,j+1,high);
}
int main()
{
	int num[10]={12,56,96,1,-1,32,56,4,89,5};
	quick_sort(num,0,9);
	
	for(int i=0;i<10;i++)
	printf("%d ",num[i]);
}

AC代码

#include <iostream>

using namespace std;
int n;

int Partition(int *a, int low, int high) {
    int pivot = a[low];
    while (low < high) {
        while (low < high && a[high] >= pivot)
            high--;
        a[low] = a[high];
        while (low < high && a[low] < pivot)
            low++;
        a[high] = a[low];
    }
    a[high] = pivot;

    cout << pivot << ' ' << high << endl;
    return high;
}

void QuickSort(int *a, int low, int high) {
    if (low <= high) {
        int pivotpos = Partition(a, low, high);
        QuickSort(a, low, pivotpos - 1);
        QuickSort(a, pivotpos + 1, high);
    }
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        cin >> n;
        int *a = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
        }
        QuickSort(a, 1, n);
        cout << endl;
        delete[]a;

    }
    cout << endl;

    return 0;
}

F. 快速排序

题目描述

给出一个数据序列,使用快速排序算法进行从小到大的排序

--程序要求--

若使用C++只能include一个头文件iostream;若使用C语言只能include一个头文件stdio

程序中若include多过一个头文件,不看代码,作0分处理

不允许使用第三方对象或函数实现本题的要求

输入

第一行输入t,表示有t个测试示例
第二行输入n,表示第一个示例有n个数据
第三行输入n个数据,都是正整数,数据之间用空格隔开

2
6
111 22 6 444 333 55
8
77 555 33 1 444 77 666 2222

以此类推

输出

每组测试数据,输出每趟快排的结果,即每次排好一个数字结果(长度为1的子序列,不用排,不用输出)。不同测试数据间用空行分隔。

55 22 6 111 333 444
6 22 55 111 333 444
6 22 55 111 333 444
6 22 55 111 333 444

1 33 77 555 444 77 666 2222
1 33 77 555 444 77 666 2222
1 33 77 77 444 555 666 2222
1 33 77 77 444 555 666 2222
1 33 77 77 444 555 666 2222
 

#include<iostream>
using namespace std;
int n;
int Partition(int * &array, int low, int high){
     int mid_key= array[low];//记录枢轴的值
 
     while(low< high){
        while(low< high&&array[high]>= mid_key )
          high--;
        array[low]= array[high];//大于枢轴的值前移
                    
        while(low< high&&array[low]<= mid_key)
          low++;
        array[high]= array[low];  //小于枢轴的值后移    
     }
     array[low]= mid_key;//最后才将枢轴的值记录到位
     return low;  //返回枢轴的位置
}
void print(int * &array){//打印输出
         
        for(int i= 1; i<= n; i++){
            cout<<array[i];
            if(i!= n)
              cout<<' ';
             else
               cout<<endl; 
        }   
}
void Qsort(int* &array, int low, int high){//快速排序
    if(low< high){
        int mid= Partition(array, low, high);
        print(array);
        Qsort(array, low, mid- 1);//将数组分成[low,mid-1]和[mid,high]两个区间
        Qsort(array, mid+ 1, high);//
 
    }
}
 
int main(){
    int t;
    cin>>t;
    while(t--){
        cin>>n;
        int *array= new int [n+ 5];
        for(int i= 1; i<= n; i++)
          cin>>array[i];
         
        int low= 1;
        int high= n;
        Qsort(array, low, high);
         
         
        delete []array;
        cout<<endl;
    }
    return 0;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值