2021.1.7寒假打卡Day4

寒假打卡 Day 4

直入主题,瞧瞧昨天的遗留问题:
在这里插入图片描述

Shell Sort🔗

Shell Sort is a generalization of Insertion Sort to arrange a list of n elements A.

 insertionSort(A, n, g)
      for i = g to n-1
          v = A[i]
          j = i - g
          while j >= 0 && A[j] > v
              A[j+g] = A[j]
              j = j - g
              cnt++
          A[j+g] = v

 shellSort(A, n)
     cnt = 0
     m = ?
     G[] = {?, ?,..., ?}
     for i = 0 to m-1
         insertionSort(A, n, G[i])

A function shellSort(A, n) performs a function insertionSort(A, n, g), which considers every g-th elements. Beginning with large values of g, it repeats the insertion sort with smaller g.

Your task is to complete the above program by filling ?. Write a program which reads an integer n and a sequence A, and prints m, Gi(i=0,1,…,m−1) in the pseudo code and the sequence A in ascending order. The output of your program must meet the following requirements:

  • 1≤m≤100
  • 0≤Gi≤n
  • cnt does not exceed ⌈n1.5

Input
In the first line, an integer n is given. In the following n lines, Ai(i=0,1,…,n−1) are given for each line.

Output
In the first line, print an integer m. In the second line, print m integers Gi(i=0,1,…,m-1)separated by single space character in a line.

In the third line, print cnt in a line. In the following n lines, print Ai(i=0,1,…,n−1) respectively.

This problem has multiple solutions and the judge will be performed by a special validator.

Constraints
1 ≤ n ≤ 1,000,000
0 ≤ Ai ≤ 109

Sample Input 1

5
5
1
4
3
2

Sample Output 1

2
4 1
3
1
2
3
4
5

Sample Input 2

3
3
2
1

Sample Output 2

1
1
3
1
2
3

注意:

  • G[1]=1,检查一遍是否顺序
  • 当gn+1=3gn+1时,复杂度能维持在O(n1.25)左右

My code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
long long cnt;
int A[1000000],n;
vector<int> G;

void insertionSort(int A[],int n,int g){
	for (int i = g; i< n;i++){
		int v = A[i];
		int j = i - g;
		while (j >= 0 && A[j] > v){
			A[j+g] = A[j];
			j = j - g;
			cnt++;
		}
		A[j+g] = v;
	}
}

shellsort(int A[],int n){
	for(int i=1;;){
		if(i>n)break;
		G.push_back(i);
		i=3*i+1;
	}
	for(int i =G.size()-1;i>=0;i--){
		insertionSort(A, n, G[i]);
	}
}

int main(){
	cin>>n;
	for(int i=0;i<n;i++) cin>>A[i];
	cnt=0;
	shellsort(A,n);
	cout<<G.size()<<endl;
	for(int i =G.size()-1;i>=0;i--){
		cout<<G[i];
		if(i)cout<<' ';
	}
	cout<<endl<<cnt;
	for(int i=0;i<n;i++) cout<<A[i]<<endl;
	return 0;
}

附上:C++ vector 容器浅析🔗

为何这样排序能更高效呢?

插入排序能快速排序较整齐的数据,而缩小增量法能充分发挥插入排序的这一优点。
希尔排序时间复杂度通常是 O(n1.2~2),空间复杂度为常数阶 O(1)。希尔排序没有时间复杂度为 O(n(logn)) 的快速排序算法快 ,因此对中等大小规模表现良好,但对规模非常大的数据排序不是最优选择,总之比一般 O(n2 ) 复杂度的算法,如冒泡和插入,快得多。

另一种常见的希尔排序:

void ShellSort(int arr[], int left, int right){
    int gap, i, j;
    for (gap = (left + right) / 2; gap > 0; gap /= 2)
        for (i = gap; i <= right; i++)
            for (j = i - gap; j > 0 && arr[j] > arr[j + gap]; j -= gap)
                swap(arr, j, j + gap);
}

洛谷 P1177 快速排序🔗

题目描述
利用快速排序算法将读入的 N 个数从小到大排序后输出。

快速排序是信息学竞赛的必备算法之一。对于快速排序不是很了解的同学可以自行上网查询相关资料,掌握后独立完成。

输入格式
第 1 行为一个正整数 N,第 22 行包含 N 个空格隔开的正整数 ai ,为你需要进行排序的数,数据保证了 Ai 不超过 109

输出格式
将给定的 N 个数从小到大输出,数之间空格隔开,行末换行且无空格。

输入

5
4 2 4 5 1

输出

1 2 4 4 5

说明/提示
对于 20% 的数据,有 N ≤ 103
对于 100% 的数据,有 N ≤ 105

  • 主体思想:找到一个基准数,将比它大的放在它的右边,比它小的放在它的左边。
  • 两个关键:
  1. 基准:一般选左边、右边、中间或随机为基准数。不同选择对执行没有较大的影响。
  2. 分治:j 从右到左找到一个比基准数 k 小的数,让 i 从左到右找到一个比 k 大的数,然后进行交换,直到 i,j 相遇开始分治处理。
#include<iostream>
using namespace std;
int n,a[1000005];

void qsort(int l,int r){
    int k=a[(l+r)/2];
    int i=l,j=r;
    do{
        while(a[i]<k) i++;
        while(a[j]>k) j--;
        if(i<=j){
            swap(a[i],a[j]);
            i++;
            j--;
        }
    }while(i<=j);
    if(l<j) qsort(l,j);
    if(i<r) qsort(i,r);
}

int main(){
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    qsort(1,n);
    for(int i=1;i<=n;i++) cout<<a[i]<<" ";
}

补充练习:洛谷 P5143 攀爬者🔗

题目背景
HKE考完GDOI之后跟他的神犇小伙伴们一起去爬山。

题目描述
他在地形图上标记了 N 个点,每个点 Pi 都有一个坐标(xi, yi, zi)。所有点对中,高度值 z 不会相等。HKE准备从最低的点爬到最高的点,他的攀爬满足以下条件:

  1. 经过他标记的每一个点;
  2. 从第二个点开始,他经过的每一个点高度 z 都比上一个点高;
  3. HKE会飞,他从一个点 Pi 爬到 Pj 的距离为两个点的欧几里得距离。即,√(Xi-Xj)2+(Yi-Yj)2+(Zi-Zj)2

现在,HKE希望你能求出他攀爬的总距离。

输入格式
第一行,一个整数 N 表示地图上的点数。

接下来 N 行,三个整数 xi, yi, zi 表示第 i 个点的坐标。

输出格式
一个实数,表示HKE需要攀爬的总距离(保留三位小数)

输入

5
2 2 2
1 1 1
4 4 4
3 3 3
5 5 5

输出

6.928

说明/提示
对于100%的数据,500001≤N≤50000,答案的范围在double范围内。

结构体排序🔗+欧几里得公式

#include<bits/stdc++.h>

struct node{
    int x,y,z;
}p[50005];
bool cmp(node a,node b){
    return a.z<b.z; 
}

int main(){
	int n;
	double ans=0;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>p[i].x>>p[i].y>>p[i].z;
	sort(p+1,p+n+1,cmp);
	for(int i=1;i<n;i++) ans+=sqrt(0.000+(a[i].x-a[i+1].x)*(a[i].x-a[i+1].x)+(a[i].y-a[i+1].y)*(a[i].y-a[i+1].y)+(a[i].z-a[i+1].z)*(a[i].z-a[i+1].z));
	printf("%.3lf",ans);
	return 0;
}

数据结构

数据结构是一种在程序中系统化管理数据集合的形式。
组成部分:

  • 数据集合:通过数据本体储存数据集合
  • 规则:保证数据集合按一定规则操作、管理、保存
  • 操作:对数据集合的处理方式

栈🔗

规则:先进后出,后进先出
操作:

push(x)		//栈顶添加x
pop()		//从栈顶取出元素
isEmpty()	//检查栈是否空
isFull		//检查栈是否满

Stack🔗

Reverse Polish notation is a notation where every operator follows all of its operands. For example, an expression (1+2)*(5+4) in the conventional Polish notation can be represented as 1 2 + 5 4 + * in the Reverse Polish notation. One of advantages of the Reverse Polish notation is that it is parenthesis-free.

Write a program which reads an expression in the Reverse Polish notation and prints the computational result.

An expression in the Reverse Polish notation is calculated using a stack. To evaluate the expression, the program should read symbols in order. If the symbol is an operand, the corresponding value should be pushed into the stack. On the other hand, if the symbols is an operator, the program should pop two elements from the stack, perform the corresponding operations, then push the result in to the stack. The program should repeat this operations.

Input
An expression is given in a line. Two consequtive symbols (operand or operator) are separated by a space character.

You can assume that +, - and * are given as the operator and an operand is a positive integer less than 106

Output
Print the computational result in a line.

Constraints
2 ≤ the number of operands in the expression ≤ 100
1 ≤ the number of operators in the expression ≤ 99
-1 × 109 ≤ values in the stack ≤ 109

Sample Input 1

1 2 +

Sample Output 1

3

Sample Input 2

1 2 + 3 4 - *

Sample Output 2

-3

Notes
Template in C

My code

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int top,stack[1005];

void push(int x){
	stack[++top]=x;
}

int pop(){
	return stack[top--];
}

int main(){
	char s[105];
	top=0;
	int a,b;
	while(scanf("%s",&s)!=EOF){
		if(s[0]=='+'){
		a=pop();b=pop();
		push(a+b);
		}
		else if(s[0]=='-'){
		a=pop();b=pop();
		push(a-b);
		}
		else if(s[0]=='*'){
		a=pop();b=pop();
		push(a*b);
		}
		else push(atoi(s));
	}
	printf("%s",pop());
}

好啦,明天再看剩余的数据结构吧。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值