您的位置:首页 > 编程语言 > C语言/C++

排序与查找算法(C语言描述)

2017-04-10 15:11 316 查看
排序算法
选择排序

冒泡排序

快速排序

归并排序

C++自带的algorithm库函数中提供了排序算法。

自带排序算法的一般形式为:

sort(arr+m,arr+n);//将数组arr的下标为m的元素到下标为n-1的元素进行从小到大排序

sort(arr+m,arr+n,comp);//与sort(arr+m,arr+n)相比,这个写法可以自己定义排序的规则,其中,comp为自定义的函数

排序算法

选择排序

基本思想:

选择排序(从小到大)的基本思想是,首先,选出最小的数,放在第一个位置;然后,选出第二小的数,放在第二个位置;以此类推,直到所有的数从小到大排序。

在实现上,我们通常是先确定第i小的数所在的位置,然后,将其与第i个数进行交换。

评价:

注意:选择排序是一种不稳定的排序算法,可能会打乱两个相同数字的原有顺序。

例如,序列 5 8 5 2 9, 按照从小到大排序,第一轮会将第1个数字5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序是一种不稳定的排序算法。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const int MAXN = 10;

int main (void)
{
int a[MAXN] = {0};
int i = 0;
int j = 0;

srand( (unsigned)time(NULL) );//rand()函数产生的是伪随机数(产生原理是 F(种子值),也就是关于一个固定值的固定公式;
//也就是程序运行第一次和第二次产生的随机数是一样的,所以我们要利用srand()进行播种;srand(unsigned seed)
for (int k = 0; k < MAXN; k++) {
a[k] = rand()%100 + 1;
}

printf("初始化数组:");
for (i = 0; i < MAXN; i++) {
printf("%-2d ", a[i]);
}
printf("\n");

/*----------*/
//选择排序原理:
//1、从第一个数开始(a[0]),找到数组中最小的数的位置,然后交换第一个数和最小数
//2、从第二个数开始(a[1]),找到剩余数中最小数的位置(对应整个数组第二小的数),然后交换第二个数和最小数
//......
//N-1、从第N-1个数开始(a[MAXN-1]))、最后一次,比较最后两数了。

//外循环:对应找第一个位置上的最小数,第二个,...,当前N-1个都找好了,最后一个自然不用找了,
//        故边界条件为 0 ~ MAXN-1 ,共 N-1次;
//内循环:要完成的任务是:遍历数组元素找到最小值;交换该位置数和最小值所在位置数,如果是本身就不用交换;
//        起点对应第一小的数放在第一个位置,第一个数也要遍历到;
//        但是我是用第一个数最为参照进行比较的,所以起点i = j + 1,直接与下一个数进行比较即可,一直到最后一个数;
//交换数:采用位运算中的异或运算交换两个不同的数;
//        原理:a^b^b = a;

/*-------  -*/
for (j = 0; j < MAXN - 1; j++) {
int min_index = j;
for (i = j + 1; i < MAXN; i++) {
if (a[min_index] > a[i]) {
min_index = i;
}
}
if (j != min_index) {
a[j] = a[j] ^ a[min_index];
a[min_index] = a[j] ^ a[min_index];
a[j] = a[j] ^ a[min_index];
}
}

printf("排序后数组:");
for (i = 0; i < MAXN; i++) {
printf("%-2d ", a[i]);
}
putchar('\n');

return 0;
}


#include <cstdio>
#include <cstdlib>
#include <ctime>
const int size = 10;

void select_sort(int a[], int MAXN) {

printf("初始化数组:");
for (int i = 0; i < size; i++) {
printf("%-2d ", a[i]);
}
printf("\n");

//核心部分
for (int j = 0; j < MAXN - 1; j++) {
int min_index = j;
for (int i = j + 1; i < MAXN; i++) {
if (a[min_index] > a[i]) {
min_index = i;
}
}
if (j != min_index) {
a[j] = a[j] ^ a[min_index];
a[min_index] = a[j] ^ a[min_index];
a[j] = a[j] ^ a[min_index];
}
}

printf("排序后数组:");
for (int i = 0; i < size; i++) {
printf("%-2d ", a[i]);
}
putchar('\n');
}

int main (void)
{
int a[size];
//初始化数组
srand( (unsigned)time(NULL) );
for (int k = 0; k < size; k++) {
a[k] = rand()%100 + 1;
}
select_sort(a, size);//排序
return 0;
}


冒泡排序

基本思想

冒泡排序(从小到大)的基本思想是,不断比较相邻的两个数,让较大的元素不断的往后移,经过一轮比较,就选出最大的数;经过第二轮比较就选出次大的数,以此类推。

一般实现

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <ctime>
const int size = 10;

void select_sort(int a[], int MAXN) {
int i;

printf("初始化数组:");
for (i = 0; i < size; i++) {
printf("%-2d ", a[i]);
}
printf("\n");

/*--------*/
//基本思想:第一轮,比较a[0]和a[1],如果a[0]>a[1],则交换两数,接着比较a[1]和a[2],......最后一次为a[N-2]和a[N-1]的比较,至此,a[N-1]为最大数
//          第二轮,比较a[0]和a[1], ......最后一次为a[N-3]和a[N-2]的比较
//          .......
//          第N-1轮,比较a[0]和a[1],结束排序
// 外循环: 0~szie-1 共 N -1 轮
// 内循环: 总是从0和1开始比较的,故初始值j=0开始,比较到size - 1 - i;
//
//两轮循环的循环变量的意义不同,一个是轮数,一个数数组元素下表  注意理解二者的区别和联系
/*--------*/
for (i = 0; i < size - 1; i++) {
for (int j = 0; j < size - 1 - i; j++) {
if (a[j] > a[j+1]) {
a[j]   = a[j] ^ a[j+1];
a[j+1] = a[j] ^ a[j+1];
a[j]   = a[j] ^ a[j+1];
}
}
}

printf("排序后数组:");
for (i = 0; i < size; i++) {
printf("%-2d ", a[i]);
}
putchar('\n');
}

int main (void)
{
int a[size];
//初始化数组
//srand( (unsigned)time(NULL) );
for (int k = 0; k < size; k++) {
a[k] = rand()%100 + 1;
}

select_sort(a, size);//排序

return 0;
}


优化实现

for (i = 0; i < size - 1; i++) {
bool isSorted = true; //
for (int j = 0; j < size - 1 - i; j++) {
if (a[j] > a[j+1]) {
isSorted = false; //
a[j]   = a[j] ^ a[j+1];
a[j+1] = a[j] ^ a[j+1];
a[j]   = a[j] ^ a[j+1];
}
}
if (isSorted) {
break; // 本轮冒泡没用进行交换,代表已经排序完成,不用再继续冒泡了。
}
}


评价

优点:稳定;

缺点:慢,每次只能移动相邻两个数据。

快速排序

归并排序

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: