标签:
今天,我们来总结一下排序算法:
排序分为冒泡排序,选择排序,插入排序,希尔排序,合并排序,快速排序,堆排序,基数排序等等,本篇文章我来详细解析冒泡排序,选择排序,直接插入排序。
首先说说最简单的冒泡排序:从老谭那本书就开始认识冒泡排序了,这种方法简单易懂:
这张动图可以解释冒泡排序。
接下来,看代码的实现:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
void BubbleSort(char *p)
{
int i = 0;
int len = strlen(p);
int j = 0;
assert(p);
for (i = 0; i < len - 1; i++)
{
for (j = 0; j < len - 1 - i; j++)
{
if (*(p + j) > *(p + j + 1)) //进行比较交换
{
char tmp = *(p + j);
*(p + j) = *(p + j + 1);
*(p + j + 1) = tmp;
}
}
}
}
int main()
{
char p[] = "174521789";
BubbleSort1(p);
printf("%s\n", p);
system("pause");
return 0;
}
仔细想一想你就会发现冒泡排序的效率非常低,所以我们当然要选择对此进行优化了,
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//冒泡排序第一种优化方式:给标志位,不需要进行对有序的进行冒泡排序。
void BubbleSort1(char *p)
{
int i = 0;
int len = strlen(p);
int j = 0;
int flag = 0; //给一个标志
for (i = 0; i < len - 1; i++)
{
flag = 1; //把标志置1
for (j = 0; j < len - 1 - i; j++)
{
if (*(p + j) > *(p + j + 1))
{
char tmp = *(p + j);
*(p + j) = *(p + j + 1);
*(p + j + 1) = tmp;
flag = 0; //冒泡了以后把标志置0
}
}
if (flag) //判断标志,如果标志为1表示后面的都为有序,所以不需要再冒泡
{
break;
}
}
}
int main()
{
char p[] = "17452198";
BubbleSort2(p);
printf("%s\n", p);
system("pause");
return 0;
}
上述我们通过flag使得最后对于一些有序的避免了排序,但是,作为一个应该精益求精的人,我想我们都应该做到更好,在这,提供另外一种优化的方法:
//冒泡排序第二种优化方式:记住最后排序好的位置,然后就不需要冒泡后续的。
void BubbleSort2(char *p)
{
int i = 0;
int len = strlen(p);
int j = 0;
int k = len-1;
int tmp = 0;
int m = 0; //记录你进行冒泡后最后移动到的位置
int flag = 0; //给一个标志
for (i = 0; i < len - 1; i++)
{
flag = 1; //把标志置1
m = 0;
for (j = 0; j < k; j++) //每次进行排序的只有前一半部分
{
if (*(p + j) > *(p + j + 1))
{
char tmp = *(p + j);
*(p + j) = *(p + j + 1);
*(p + j + 1) = tmp;
flag = 0; //冒泡了以后把标志置0
m = j; //记录每一次的位置
}
}
if (flag) //判断标志,如果标志为1表示后面的都为有序,所以不需要再冒泡
{
break;
}
k = m; //记住最后排序到的位置,后面再排序就直排前面的
}
}
int main()
{
char p[] = "17452198";
BubbleSort2(p);
printf("%s\n", p);
system("pause");
return 0;
}
这里借助临时变量记住最后一次交换的位置,作为内层循环的边界。
上面这张图片就是揭示了插入排序算法的实现过程。在前面为有序的序列,后面为无序序列,把有序序列后的一个每次和有序序列中的元素相比较,插入到它应该出现的位置。
通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
算法步骤:
1)将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
2)从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
void InsertionSort(char *p)
{
assert(p);
int len = strlen(p);
int i = 0;
int j = 0;
for (i = 1; i < len - 1; i++)
{
char tmp = p[i]; //在这里保存有序序列后的一个元素
for (j = i - 1; j >= 0; j--) //进行和有序序列中的元素进行比较
{
if (tmp < p[j]) //比较判断
{
p[j + 1] = p[j]; //进行有序序列元素的移动
}
else
{
break;
}
}
p[j+1] = tmp; //进行元素插入
}
}
int main()
{
char str[] = "17452198";
InsertionSort(str);
printf("%s\n", str);
system("pause");
return 0;
}
这个动图就可以说明选择排序的问题了。
选择排序(Selection sort)也是一种简单直观的排序算法。
算法步骤:
1)首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
2)再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
3)重复第二步,直到所有元素均排序完毕。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<assert.h>
void SelectSort(char *str)
{
assert(str);
int i = 0;
int min = 0;
int j = 0;
int len = strlen(str);
for (i = 1; i < len - 1; i++)
{
min = i + 1; //首先默认无序第一个为最小的
for (j = i + 1; j < len - 1; j++)
{
if (str[min]>str[j])
{
min = j; //进行无序序列中的比较,得到最小的下标
}
}
if (min != i) //把无序序列中最小的元素与有序的元素进行替换
{
char tmp = str[i];
str[i] = str[min];
str[min] = tmp;
}
}
}
int main()
{
char str[] = "17452198";
SelectSort(str);
printf("%s\n", str);
system("pause");
return 0;
}
这次就先描述这三种排序算法,后续依然会有更新
标签:
原文地址:http://blog.csdn.net/qq_26768741/article/details/51559429