排序算法是按照一定的规则,按照递增或者递减的顺序进行排序
冒泡排序
从小到大排序
void BubbleSort(int*a,int len){
for(int i=0;i<len-1;i++){
for(int j=len-1;j>i;j--){
if(a[j-1]>a[j]){
int temp=0;
temp=a[j];
a[j]=a[j-1];
a[j-1]=temp;
}
}
}
}
//传值交换
void swapUseValue(int a, int b) {
int temp= a;
a= b;
b = temp;
return;
}
//传址交换
void swapUseAddress(int *p, int *q) {
int temp= *p;
*p = *q;
*q = temp;
}
//打印
void printArr(int *a,int len){
for (int i=0; i<len; i++) {
printf("%d\n",a[i]);
}
}
void sortBymaopao2(int arr[],int n){
for (int i=0; i<n-1; i++) {
for (int j=0; j<n-1-i; j++) {
if (arr[j]>arr[j+1]) {
swapUseAddress(&arr[j], &arr[j+1]);
}
}
printArr(arr,n);
}
printArr(arr,n);
}
从大到小排序
void BubbleSort(int*a,int len){
for(int i=0;i<len-1;i++){
for(int j=0;j<len-i-1;j++){
if(a[j]<a[j+1]){
int temp=0;
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
}
void sortBymaopao2(int arr[],int n){
for (int i=0; i<n-1; i++) {
for (int j=n-1;j>i; j--) {
if (arr[j-1]<arr[j]) {
swapUseAddress(&arr[j-1], &arr[j]);
}
}
}
printArr(arr,n);
}
选择排序
就是在一轮排序中选择最大或者最小的数,和岗哨进行比较,岗哨移动的过程 可以依次前移或者后移
从小到大排序
1.岗哨从前往后移,找到最小的,和岗哨交换
1)第一轮比较中选择出最小的数
2)选择出的最小数,和数组中的第一个元素进行交换 ,每一轮选择交换,只能确定一个最小的数依次排好.
3)进入下一轮比较,从剩下的数据中进行 选择交换
这个算法的关键是,1>设置岗哨 2>交换最小数和岗哨
//岗哨从前往后移,找到最小的,和岗哨交换
void selectSort(int * a,int len){
for(int i=0;i<len;i++){
//岗哨 a[i]
//保存最小的值的坐标
int k=i;
for(int j=i+1;j<len;j++){
if(a[j]<a[k]){
k=j;
}
}
int temp=a[i];
a[i]=a[k];
a[k]=temp;
}
printArr(a, 10);
}
2.岗哨后往前移,找到最大的,和岗哨交换
//岗哨后往前移,找到最大的,和岗哨交换
void selectSort1(int * a,int len){
for(int i=len-1;i>=0;i--){
//岗哨 a[i]
//保存最大的值的坐标
int k=i;
for(int j=i-1;j>=0;j--){
if(a[j]>a[k]){
k=j;
}
}
int temp=a[i];
a[i]=a[k];
a[k]=temp;
}
printArr(a, 10);
}
从大到小排序
1.岗哨从前往后移,找到最大的,和岗哨交换
岗哨从前往后移,找到最大的,和岗哨交换
void selectSort2(int * a,int len){
for(int i=0;i<len;i++){
//岗哨 a[i]
//保存最大的值的坐标
int k=i;
for(int j=i+1;j<len;j++){
if(a[j]>a[k]){
k=j;
}
}
int temp=a[i];
a[i]=a[k];
a[k]=temp;
}
printArr(a, 10);
}
2.岗哨从后往前移,找到最小的,和岗哨交换
//岗哨从后往前移,找到最小的,和岗哨交换
void selectSort3(int * a,int len){
for(int i=len-1;i>=0;i--){
//岗哨 a[i]
//保存最大的值的坐标
int k=i;
for(int j=i-1;j>=0;j--){
if(a[j]<a[k]){
k=j;
}
}
int temp=a[i];
a[i]=a[k];
a[k]=temp;
}
printArr(a, 10);
}
直接插入排序
就是将数字插入 已经排好的数字序列
比如原数组 28,3,1,5,6,9
某一轮的排序 3, 28, 1,5,6,9 将1 插入到 3之前 3,28,相应的往后移动
从小到大排序
//需要插入的值(岗哨)依次向后移,在已排好序中数组比岗哨值大的元素需要后移
void directInsert(int *arr,int len){
for(int i=1;i<len;i++){
//岗哨
int temp=arr[i];
int j=i-1;
//比插入值大的元素向后移动
while (arr[j]>temp&&j>=0){
arr[j+1]=arr[j];
j--;
}
//插入
arr[j+1]=temp;
}
printArr(arr, 10);
}
从大到小排序
需要插入的值(岗哨)依次向后移,在已排好序中数组比岗哨值小的元素需要后移
void directInsert1(int *arr,int len){
for(int i=1;i<len;i++){
//岗哨
int temp=arr[i];
int j=i-1;
//比插入值大的元素向后移动
while (arr[j]<temp&&j>=0){
arr[j+1]=arr[j];
j--;
}
//插入
arr[j+1]=temp;
}
printArr(arr, 10);
}
希尔排序
希尔排序的实质就是分组插入排序,该方法又称缩小增量排序,因DL.Shell于1959年提出而得名。
该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。
gap=5 分为5组(1A,1B),(2A,2B),(3A,3B),(4A,4B),(5A,5B) 每一组分别进行插入排序
gap=2 分为2组(1A,1B,1C,1D,1E),(2A,2B,2C,2D,2E) 每一组分别进行插入排序
gap=1 分为1组(1A,1B,1C,1D,1E,1F,1G,1H,1I,1J) 直接插入排序
void shellSort(int * a,int len){
//分组 gap 越大,分的组数越小
for(int gap=len/2;gap>=1;gap/=2){
for (int i=gap; i<len; i++) {
int temp=a[i];
int j=i-gap;
while (j>=0&&temp<a[j]) {
a[j+gap]=a[j];
j-=gap;
}
a[j+gap]=temp;
}
}
printArr(a, 10);
}
快速排序
排序算法(Sorting algorithm)是计算机科学最古老、最基本的课题之一。要想成为合格的程序员,就必须理解和掌握各种排序算法。目前,最常见的排序算法大概有七八种,其中"快速排序"(Quicksort)使用得最广泛,速度也较快。它是图灵奖得主C. A. R. Hoare(1934--)于1960时提出来的。
"快速排序"的思想很简单,整个排序过程只需要三步:
(1)在数据集之中,选择一个元素作为"基准"(pivot)。
(2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。
(3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。
66 13 51 76 81 26 57 69 23,以66为基准,升序排序的话,比66小的放左边,比66大的放右边, 类似这种情况 13 。。。 66。。。69
具体快速排序的规则一般如下:
从右边开始查找比66小的数,找到的时候先等一下,再从左边开始找比66大的数,将这两个数借助66互换一下位置,继续这个过程直到两次查找过程碰头。例子中:
66 13 51 76 81 26 57 69 23
从右边找到23比66小,互换
23 13 51 76 81 26 57 69 66
从左边找到76比66大,互换
23 13 51 66 81 26 57 69 76
继续从右边找到57比66小,互换
23 13 51 57 81 26 66 69 76
从左边查找,81比66大,互换
23 13 51 57 66 26 81 69 76
从右边开始查找26比66小,互换
23 13 51 57 26 66 81 69 76
从左边开始查找,发现已经跟右边查找碰头了,结束,第一堂排序结束
以66作为分界点
左半部分和右半部分别 执行和上面的同样的过程
所以整个过过程是递归的
void quickSort(int *a, int left, int right)
{
if(left >= right)/*如果左边索引大于或者等于右边的索引就代表已经整理完成一个组了*/
{
return ;
}
int i = left;
int j = right;
int key = a[left];
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回归*/
quickSort(a, left, i - 1);/*最后用同样的方式对分出来的左边的小组进行同上的做法*/
quickSort(a, i + 1, right);/*用同样的方式对分出来的右边的小组进行同上的做法*/
/*当然最后可能会出现很多分左右,直到每一组的i = j 为止*/
}