这里简单总结一下常用的排序算法:
1、冒泡排序:两个数比较大小,较大的数下沉,较小的数冒起来。
- 比较相邻的两个数据,如果第二个数小,就交换位置。
- 从后向前两两比较,一直到比较最前两个数据。最终最小数被交换到起始的位置,这样第一个最小数的位置就排好了。
- 继续重复上述过程,依次将第2.3...n-1个最小数排好位置。
比如对这个数组进行排序
第一次循环换呢4和5进行比较
[4,5],7,3,2,1 不用交换
4,[5,7],3,2,1 不用交换
4,5,[7,3],2,1 7比3大,交换
4,5,3,[7,2],1 7比2大,交换
4,5,3,2,[7,1] 7比1大,交换
4,5,3,2,1,7 进行了一次循环,吧最大的进行了排序
进行数组大小-1次循环就完成了排序
void bubble(int *arr,int n){
int temp = 0;
for (int i = 0; i < n-1; i++)
{
for (int j = 0; j < n-i-1; j++)
{
if(arr[j] > arr[j+1]){
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
/*拆开写或许更容易理解*/
void bubble(int arr[],int n){
for(int i = 0;i < n - 1;i++){
if(arr[i] > arr[i+1]){
arr[i] = arr[i] ^ arr[i+1];
arr[i+1] = arr[i] ^ arr[i+1];
arr[i] = arr[i] ^ arr[i+1];
}
}
}
void bubble_sort(int arr[],int n){
for(int i = n;i > 1;i--){
bubble(arr,i);
}
}
2、选择排序
将数组中最大的元素位置找出来,和最后一个元素进行交换。
然后再从前面n-1个元素中找出最大的元素,和倒数第二个进行交换,以此类推。(这里在交换元素的时候不能使用异或的交换算法,如果最大值恰好是自己的话,就会出现错误)
int find_max_pos(int arr[],int n){
int max = arr[0];
int pos = 0;
for(int i = 0;i < n;i++){
if(arr[i] > max){
max = arr[i];
pos = i;
}
}
return pos;
}
void select_sort(int arr[],int n){
int pos;
for(int i = 0;i < n-1;i++ ){
pos = find_max_pos(arr,n-i);
int tmp = arr[pos];
arr[pos] = arr[n-1-i];
arr[n-1-i] = tmp;
}
}
3、插入排序
第一个肯定是已经拍好顺序的,从数组的第二个开始依次向前面进行插入,知道最后。
void insert(int arr[],int n){
int key = arr[n];
int i = n;
while (arr[i-1] > key)
{
arr[i] = arr[i-1];
i--;
if(i == 0)break;
}
arr[i] = key;
}
void insert_sort(int arr[],int n){
for(int i = 1;i < n;i++){
insert(arr,i);
}
}
上面三种的平均时间复杂度都是一样的:下面讲解一一下时间复杂度低的;
4、快速排序
- 先从数列中取出一个数作为key值;
- 将比这个数小的数全部放在它的左边,大于或等于它的数全部放在它的右边;
- 对左右两个小数列重复第二步,直至各区间只有1个数
void quick_sort(int *p_val,int n){
int base = *p_val;
int *p_head = NULL,*p_tail = NULL;
if(n <= 1) return ; //如果数组小于等于1就是已经拍好顺序的,直接返回
p_head = p_val; //指向第一个存储区
p_tail = p_val + n - 1; //执向最后一个存储区
while(p_head < p_tail){ //两个指针没有相遇,就还需要进行
//一次先对尾指针进行比较
while( (p_head < p_tail) && (*p_tail >= base)){
p_tail--;
}
if(*p_tail < base){
*p_head = *p_tail;
p_head++;
}
while ((p_head < p_tail) && (*p_head <= base))
{
p_head++;
}
if(*p_head > base){
*p_tail = *p_head;
p_tail--;
}
}
*p_head = base; //最后对共同的指针进行复制
quick_sort(p_val,p_head-p_val);
quick_sort(p_head+1,n-(p_head - p_val)-1);
}
对于快去排序,C库中有写好的函数,我们可以直接去进行使用,下面介绍一下C语言库函数怎么使用快速排序。这样是不是快多了呢。
/*函数原型,这个函数的功能是对一个数组进行排序。
void qsort (void* base, size_t num, size_t size,int (*compar)(const void*,const void*));
base:是数组的首地址
num:数组的元素个数
size:每个元素所占的字节数
compare:函数指针
返回值 含义
<0 元素P1排在P2前面
0 不动
>0 元素P1排在P2后面*/
//使用方式:
#define ARR_SZIE(arr) (sizeof(arr)/sizeof(arr[0]))
#define ARR_ELE_SZIE(arr) (sizeof(arr[0]))
int compare(const void *p1,const void *p2){
return (* (int *)p1 - *(int *)p2); //如果想从大到小进行排序,就倒过来减
}
int main(){
int arr[10] = {4,8,6,2,8,3,6,8,1,6};
qsort(arr,ARR_SZIE(arr),ARR_ELE_SZIE(arr),compare);
for (int i = 0; i < 10; i++)
{
printf("%d\t",arr[i]);
}
}
//与之相对应的还以有一个查找函数,在这里就一并介绍了
//void* bsearch (const void* key, const void* base,size_t num, size_t size,
// int (*compar)(const void*,const void*));
//在使用这个函数之前的数组必须是已经排好顺序的。
//指向数组中与搜索键匹配的条目的指针。如果有多个匹配元素(即compar将返回0的元素),则可以指向
//它们中的任何一个(不一定是第一个)。 如果找不到键,则返回空指针。
int key = 2;
int *p = bsearch(&key,arr,ARR_SZIE(arr),ARR_ELE_SZIE(arr),compare);