排序问题:粗讲sort函数

什么是排序问题?

排序问题即把一些无序的数字,字符,字符串等等具有大小比较性的变量排列成一个有序的序列。

方法:

1.选择排序:

原理:

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

代码实现:

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

void select_sort(int *array, int length)
{
	int max, ind;
	for(int i = 0; i < length; i++)
	{
		max = -1;
		for(int j = i; j < length; j++)
		{
			if(array[j] > max)
				max = array[j], ind = j;
		}
		int tmp = array[i];array[i] = array[ind];array[ind] = tmp;
	}
}
int main()
{
	int a[10] = {5, 3, 1, 8, 4, 2, 6, 9, 7, 0};
	select_sort(a, 10);
	for(int i = 0; i < 10; i++)
		printf("%d ", a[i]);
}

时间复杂度

  • 最坏时间复杂度 O(n2)
  • 最优时间复杂度 O(n2)
  • 平均时间复杂度 O(n2)

 

2.Bubble Sort(冒泡排序):

原理:

重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

初学者接触比较多的排序算法,原理也很简单。

代码实现:

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

void Bubble_Sort(int *array, int length)
{
	for(int i = 0; i < length-1; i++)
	{
		for(int j = 0; j < length-1; j++)
		{
			if(array[j+1] > array[j])
			{
				int tmp = array[j];
				array[j] = array[j+1];
				array[j+1] = tmp;
			}
		}
	}
}
int main()
{
	int a[10] = {5, 3, 1, 8, 4, 2, 6, 9, 7, 0};
	Bubble_Sort(a, 10);
	for(int i = 0; i < 10; i++)
		printf("%d ", a[i]);
}

时间复杂度

  • 最坏时间复杂度 O(n2)
  • 最优时间复杂度O(n)
  • 平均时间复杂度 O(n2)

3.插入排序:

原理

插入排序的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

代码实现:略。

这里需要讲的是插入排序的一个优化:希尔排序, 复杂度还是有很大改进的。

4.快速排序:

算法

快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。

步骤为:

  1. 从数列中挑出一个元素,称为"基准"(pivot),
  2. 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。
  4. 递归到最底部时,数列的大小是零或一,也就是已经排序好了。这个算法一定会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

代码实现:

void Quick_Sort(int *array, int l, int r)
{
	int mid = a[(l + r) >> 1];//规定基准 
	int i = l, j = r;
	do
    {
        while(a[i] < mid)//在左半部分寻找比中间大的数 
            i++;
        while(a[j] > mid)//在右半部分寻找比中间小的数 
            j--;
        if(i< = j)
        {
            swap(a[i], a[j]);
            i++, j--;//继续找。 
        }
    }while(i <= j);
    if(l < j)//若未到边界,继续找。 
        Quick_Sort(a, l, j);
    if(i < r)
        Quick_Sort(a, i, r);		
} 

比赛中也要手打一遍快排?不存在的,接下来说说C++ sort函数

1.头文件:algorithm

2.常见数组排序

例题:HDU1425

Problem Description

给你n个整数,请按从大到小的顺序输出其中前m大的数。

 

 

Input

每组测试数据有两行,第一行有两个数n,m(0<n,m<1000000),第二行包含n个各不相同,且都处于区间[-500000,500000]的整数。

 

 

Output

对每组测试数据按从大到小的顺序输出前m大的数。

 

 

Sample Input

 

5 3 3 -35 92 213 -644

 

 

Sample Output

 

213 92 3

 

代码实现:

#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 1e6+5;
int a[maxn];

int cmp(int a, int b)
{
	return a > b;
}
int main()
{
	int n, m, i;
	while(cin >> n >> m)
	{
		for(i = 0; i < n; i++)
			scanf("%d", &a[i]);
		sort(a, a+n, cmp);
		printf("%d", a[0]);
		for(i = 1; i < m; i++)
		{
			printf(" %d", a[i]);
		}
		printf("\n");
	}
}

2.结构体排序:

例题:PAT (Basic Level) Practice 1015 德才论

输入格式:

输入第1行给出3个正整数,分别为:N(<=10^5^),即考生总数;L(>=60),为录取最低分数线,即德分和才分均不低于L的考生才有资格被考虑录取;H(<100),为优先录取线——德分和才分均不低于此线的被定义为“才德全尽”,此类考生按德才总分从高到低排序;才分不到但德分到线的一类考生属于“德胜才”,也按总分排序,但排在第一类考生之后;德才分均低于H,但是德分不低于才分的考生属于“才德兼亡”但尚有“德胜才”者,按总分排序,但排在第二类考生之后;其他达到最低线L的考生也按总分排序,但排在第三类考生之后。

随后N行,每行给出一位考生的信息,包括:准考证号、德分、才分,其中准考证号为8位整数,德才分为区间[0, 100]内的整数。数字间以空格分隔。

输出格式:

输出第1行首先给出达到最低分数线的考生人数M,随后M行,每行按照输入格式输出一位考生的信息,考生按输入中说明的规则从高到低排序。当某类考生中有多人总分相同时,按其德分降序排列;若德分也并列,则按准考证号的升序输出。

代码实现 :

#include <bits/stdc++.h>
using namespace std;
struct student {
	char num[10];
	int s1, s2;
	int rank;
}stu[100005];

int cmp(student a, student b)
{
	if(a.rank != b.rank)
		return a.rank < b.rank;
	else if(a.s1+a.s2 != b.s1+b.s2)
		return (a.s1+a.s2) > (b.s1+b.s2);
	else if(a.s1 != b.s1)
		return a.s1 > b.s1;
	else
		return strcmp(a.num, b.num) < 0;
}
int main()
{
	int n, l, h, i, laji = 0;
	cin >> n >> l >> h;
	for(i = 0; i < n; i++)
	{
		scanf("%s %d %d", stu[i].num, &stu[i].s1, &stu[i].s2);
		if(stu[i].s1 >= h && stu[i].s2 >= h)
			stu[i].rank = 1;
		else if(stu[i].s1 >= l && stu[i].s2 >= l)
		{
			if(stu[i].s1 >= h)
				stu[i].rank = 2;
			else if(stu[i].s1 >= stu[i].s2)
				stu[i].rank = 3;
			else
				stu[i].rank = 4;
		}		
		else
		{
			laji++;
			stu[i].rank = 5;
		}				
	}
	sort(stu, stu+n, cmp);
	cout << n-laji << endl;
	for(i = 0; i < n-laji; i++)
	{
		printf("%s %d %d\n", stu[i].num, stu[i].s1, stu[i].s2);
	}
}

3.字符串排序:

例题:洛谷P1781宇宙总统

问题描述:找出N个数里最大的那个,N <= 10^100.

代码实现:

#include <bits/stdc++.h>
using namespace std;
struct node{
	string s;
	int len;
	int num;
}N[25];

int cmp(node a, node b)
{
	if(a.len == b.len)//长度一样就直接字符串比较 
		return a.s > b.s;
	else	return a.len > b.len;//不一样比谁长^.^ 
}
int main()
{
	int n, i;
	cin >> n;
	for(i = 1; i <= n; i++)
	{
		cin >> N[i].s;
		N[i].len = N[i].s.length();//记录一下长度 
		N[i].num = i;
	}
	sort(N+1, N+n+1, cmp);
	cout << N[1].num << endl;
	cout << N[1].s;
}

大概就那么几个种类吧,题目很简单,但是排序最难的就是时间复杂度的优化,不然很容易会超时,sort函数也不是万能的,这里我还没有涉及归并排序,原因在于,若是只考虑排序,归并排序并不是一个实用的排序算法,但是有时候,如果遇到多重排序,可能需要归并排序大显身手了,好吧,我就讲那么多,希望对你们有用吧!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值