简单选择排序
是一种简单直观的排序算法,他的基本原理是:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将记录与第一个记录的位置进行交换;
接着对不包括第一个记录以外的其他记录进行第二轮排序,得到最小的记录并与第二个记录进行位置交换;重负该过程,直到进行比较的记录只有一个为止。
#include <stdio.h>
int main()
{
int a[10]={34,56,7,89,9,9,56,34,78,65};
int no;
int t;
int i;
int j;
for(j=0;j<9;j++) //控制循环9次
{
//---------------重复执行的代码段
no=j;
for(i=j+1;i<10;i++)
{
if(a[i]>a[no])
{
no=i;
}
}
t=a[j];
a[j]=a[no];
a[no]=t;
//-----------------
}
//输出数组里的元素
for(i=0;i<10;i++)
{
printf("%d ",a[i]);
}
printf(" ");
}
直接插入排序
对于给定的一组记录,初始时假定第一个记录自成一个有序的序列,其余的记录为无序序列;接着从第二个记录开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中,直至最后一个记录插入到有序序列为止。
#include <stdio.h>
void InsertSort(int a[],int len)
{
int i,j;
int tmp;
for(i = 1;i < len;i++)
{
tmp = a[i];
for(j = i - 1;j >= 0;j--)
{
if(tmp < a[j])
a[j + 1] = a[j];
else
break;
}
a[j + 1] = tmp;
}
}
int main()
{
int i,length;
int a[6] = {0};
printf("enter 6 num...");
for(i = 0;i < 6;i++)
scanf("%d",&a[i]);
length = sizeof(a)/sizeof(int);
InsertSort(a,length);
for(i = 0;i < 6;i++)
printf("%d ",a[i]);
printf("\n");
return 0;
}
希尔排序
希尔排序也称为“缩小增量排序”,基本原理是:首先将待排序的元素分为多个子序列,使得每个子序的元素个数相对较少,对各个子序分别进行直接插入排序,待整个待排序序列“基本有序后”,再对所有元素进行一次直接插入排序。
#include <stdio.h>
void ShellSort(int a[],int len)
{
int tmp;
int i,j;
int gap = len / 2;
do
{
gap = gap / 2;
for(i = gap;i < len;i++)
{
if(a[i] < a[i - gap])
{
tmp = a[i];
for(j = i - gap;a[j] > tmp && j>= 0 ;j--)
{
a[j + gap] = a[j];
}
a[j + gap] = tmp;
}
}
}while(gap > 1);
}
int main()
{
int a[6] = {2,6,3,9,5,1};
int length,i;
length = sizeof(a) / sizeof(int);
ShellSort(a,length);
for(i = 0;i < 6;i++)
{
printf("%d ",a[i]);
}
printf("\n");
return 0;
}
快速排序
快速排序是一种非常高效的排序方法,采用“分而治之”的思想,把大的拆分为小的,小的在拆分为更小的。
原理是:对于一组给定的记录,通过一趟排序后,将原序列分为两部分,其中前部分的所有记录均比后部分的所有记录小,然后再依次对前后两部分的记录进行快速排序,递归该过程,直到序列中的所有记录均为有序为止。
#include <stdio.h>
void sort(int *a, int left, int right)
{
int i = left;
int j = right;
int key = a[left];
if(left >= right)/*如果左边索引大于或者等于右边的索引就代表已经整理完成一个组了*/
{
return ;
}
while(i < j) /*控制在当组内寻找一遍*/
{
while(i < j && key <= a[j])
/*而寻找结束的条件就是,1,找到一个小于或者大于key的数(大于或小于取决于你想升
序还是降序)2,没有符合条件1的,并且i与j的大小没有反转*/
{
j--;/*向前寻找*/
}
a[i] = a[j];
/*找到一个这样的数后就把它赋给前面的被拿走的i的值(如果第一次循环且key是
a[left],那么就是给key)*/
while(i < j && key >= a[i])
/*这是i在当组内向前寻找,同上,不过注意与key的大小关系停止循环和上面相反,
因为排序思想是把数往两边扔,所以左右两边的数大小与key的关系相反*/
{
i++;
}
a[j] = a[i];
}
a[i] = key;/*当在当组内找完一遍以后就把中间数key回归*/
sort(a, left, i - 1);/*最后用同样的方式对分出来的左边的小组进行同上的做法*/
sort(a, i + 1, right);/*用同样的方式对分出来的右边的小组进行同上的做法*/
/*当然最后可能会出现很多分左右,直到每一组的i = j 为止*/
}
int main()
{
int i,length;
int a[6] = {2,7,1,5,3,0};
sort(a,0,5);
for(i = 0;i < 6;i++)
printf("%d ",a[i]);
printf("\n");
return 0;
}
堆排序
堆排序是一种特殊的树形数据结构,其每个节点都有一个值,通常提到的堆都是指一棵完全二叉树,根节点的值小于(或大于)两个子节点的值,同时根节点的两个子树也分别是一个堆。堆排序主要包括两个过程:一是构建堆, 二是交换堆顶元素与最后一个元素的位置。
堆排序思想:
1. 将序列构造成一棵完全二叉树 ;
2. 把这棵普通的完全二叉树改造成堆,便可获取最小值 ;
3. 输出最小值 ;
4. 删除根结点,继续改造剩余树成堆,便可获取次小值 ;
5. 输出次小值 ;
6. 重复改造,输出次次小值、次次次小值,直至所有结点均输出,便得到一个排序 。
#include <stdio.h>
//array是待调整的堆数组,i是待调整的数组元素的位置,nlength是数组的长度
//本函数功能是:根据数组array构建大根堆
void HeapAdjust(int array[],int i,int nLength)
{
int nChild;
int nTemp;
for(;2*i+1<nLength;i=nChild)
{
//子结点的位置=2*(父结点位置)+1
nChild=2*i+1;
//得到子结点中较大的结点
if(nChild<nLength-1&&array[nChild+1]>array[nChild])++nChild;
//如果较大的子结点大于父结点那么把较大的子结点往上移动,替换它的父结点
if(array[i]<array[nChild])
{
nTemp=array[i];
array[i]=array[nChild];
array[nChild]=nTemp;
}
else break; //否则退出循环
}
}
//堆排序算法
void HeapSort(int array[],int length)
{
int i;
//调整序列的前半部分元素,调整完之后第一个元素是序列的最大的元素
//length/2-1是最后一个非叶节点,此处"/"为整除
for(i=length/2-1;i>=0;--i)
HeapAdjust(array,i,length);
//从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
for(i=length-1;i>0;--i)
{
//把第一个元素和当前的最后一个元素交换,
//保证当前的最后一个位置的元素都是在现在的这个序列之中最大的
array[i]=array[0]^array[i];
array[0]=array[0]^array[i];
array[i]=array[0]^array[i];
//不断缩小调整heap的范围,每一次调整完毕保证第一个元素是当前序列的最大值
HeapAdjust(array,0,i);
}
}
int main()
{
int i;
int num[]={9,8,7,6,5,4,3,2,1,0};
HeapSort(num,sizeof(num)/sizeof(int));
for(i=0;i<sizeof(num)/sizeof(int);i++)
{
printf("%d ",num[i]);
}
printf("\nok\n");
return 0;
}
C语言
归并排序
合并排序(MERGE SORT)是又一类不同的排序方法,合并的含义就是将两个或两个以上的有序数据序列合并成一个新的有序数据序列,因此它又叫归并算法。它的基本思想就是假设数组A有N个元素,那么可以看成数组A是又N个有序的子序列组成,每个子序列的长度为1,然后再两两合并,得到了一个 N/2 个长度为2或1的有序子序列,再两两合并,如此重复,值得得到一个长度为N的有序数据序列为止,这种排序方法称为2—路合并排序。
例如数组A有7个数据,分别是: 49 38 65 97 76 13 27,那么采用归并排序算法的操作过程如图7所示:
初始值 [49] [38] [65] [97] [76] [13] [27]
看成由长度为1的7个子序列组成
第一次合并之后 [38 49] [65 97] [13 76] [27]
看成由长度为1或2的4个子序列组成
第二次合并之后 [38 49 65 97] [13 27 76]
看成由长度为4或3的2个子序列组成
第三次合并之后 [13 27 38 49 65 76 97]
合并算法的核心操作就是将一维数组中前后相邻的两个两个有序序列合并成一个有序序列。合并算法也可以采用递归算法来实现,形式上较为简单,但实用性很差。合并算法的合并次数是一个非常重要的量,根据计算当数组中有3到4个元素时,合并次数是2次,当有5到8个元素时,合并次数是3次,当有9到16个元素时,合并次数是4次,按照这一规律,当有N个子序列时可以推断出合并的次数是X(2 >=N,符合此条件的最小那个X)。
其时间复杂度为:O(nlogn).所需辅助存储空间为:O(n)
/*****************************************************
> File name: a.c
> Author: Mr.YUAN
> 鏃ユ湡: 2017-11-30 17:14
*****************************************************/
#include <stdio.h>
#include<stdlib.h>
void merging(int a[],int begin,int mid,int end)
{
int *tmp = (int *)malloc(sizeof(int)*(end - begin + 1));
int i,j,k;
i = begin;
j = mid + 1;
k = 0;
while(i <= mid && j <=end)
{
if(a[i] < a[j])
tmp[k++] = a[i++];
else
tmp[k++] = a[j++];
}
while(i <= mid)
tmp[k++] = a[i++];
while(j <= end)
tmp[k++] = a[j++];
for(i = 0;i < k;i++)
{
a[begin + i] = tmp[i];
}
free(tmp);
}
void merge_sort(int a[],int begin,int end)
{
int mid;
if(a == NULL || begin >= end)
return;
mid = (begin + end) / 2;
merge_sort(a,begin,mid);
merge_sort(a,mid + 1,end);
merging(a,begin,mid,end);
}
int main()
{
int i,length;
int a[10] = {0};
printf("enter 10 num...\n");
for(i = 0;i < 10;i++)
{
scanf("%d",&a[i]);
}
length = sizeof(a)/sizeof(int);
merge_sort(a,0,length - 1);
for(i = 0;i < length;i++)
{
printf("%d ",a[i]);
}
return 0;
}