所有的排序烦恼

来源:互联网 发布:海岛奇兵保险库数据 编辑:程序博客网 时间:2024/04/30 01:27

在计算机方面,学到现在接触到的基本都是数字,字符,最常见的那就是数字。但是对于一串数字,你能干什么,对于程序员来说,最先想到的也许就是排序、最大数、最小数吧!

对于排序也很经典,那么现在我总结了一些排序,希望对你有帮助。

   之前的排序有一部分:http://blog.csdn.net/qq_35256722/article/details/51702532

这里有简单排序:交换排序、冒泡排序、选择排序

           经典排序:插入排序、希尔排序、快速排序、堆排序、归并排序

先来了解一下,各个排序的概念(我自己总结的):

     交换排序:就是拿0和其他下标比较,大的交换,否则,一直往后。下次就是1,....直到数组全部比较完

     冒泡排序:简单来说,就是0-1,1-2 ,2-3....len-2 和len-1.这样子比较,大数后放。第二趟, 0-1,1-2,...len-3  和len-2.以此类推。

     选择排序:先认为第一个数最小,那第一个数和数组里面所有的数进行比较,大的后换。一趟下来,就会找到一个最小的数,及其下标。把它交换到第0的位置。第二趟找到的最小数,放在1的位置.....

      插入排序:让每个数,一次到达他的相对位置,(改进)

红箭头:表示在此位置停下来了。

    希尔排序:先分组-----》组内有序----》整体有序


      快速排序:先把第一个数拿出来存起来,然后开始从右找比他小的,往前方,从左找比他大的往后挪。当左右跑的相同时,就把tmp之前存的值,放回去!(这一趟,让支点以前比他小,以后比他大),在对左半部分进行一次快速排序.....知道整个数组都有序。

      推排序:先把这个顺序表存在类似于树的地方。

      让每个树的顶都是最大数,如果整个树的最大数,在最顶端,那么就交换到最后一位数所在的位置,继续在做让每个树的顶都是最大数。

       归并排序:就是让每个数为一组,开始两两归并,(两两有序),下来四四归并,八八归并....让这个数组有序。

讲完概念

     那就是关键的代码:

     SORT.h

#ifndef _SORT_H_#define _SORT_H_//#include"LINK_STACK.h"typedef void (*pfunc)(int *,int);typedef enum _SORT{CHANGE = 'a',BUBBLE, BUBBLE_EX,SLECT ,INSERT,INSERT_EX,SHELL,QUICK,QUICK_LOOP,HEAP,MEGER}SORT;typedef struct _ELECT{SORT   choice;pfunc  pfunchoice;}Elect;int *ceart_arr(int len);  // 产生一组随机数 ,根据你传的len,产生这么多随机数void choose(int *arr,int len);//表驱动//简单排序void change_sort(int *arr,int len);//交换排序void bubble_sort(int *arr,int len);//冒泡排序void bubble_sort_ex(int *arr,int len);//冒泡排序(改进)void select_sort(int *arr,int len);//选择排序void insert_sort(int *arr,int len); //插入排序void insert_sort_ex(int *arr,int len);//插入排序改进void shell_sort(int *arr,int len);//希尔排序void quick_sort(int *arr,int len);//快速排序(递归)void quick_sort_loop(int *arr,int len);//快速排序(非递归)void heap_sort(int *arr,int len);//堆排序void meger_sort(int *arr,int len);//归并排序void show(int *arr,int len,void pfunc(int *,int ));#endif

  SORT.cpp

#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#include<time.h>#include<assert.h>#include"SORT.h"#include"LINK_STACK.h"int *ceart_arr(int len){if(len <= 0){return NULL;}srand(100);  //种子,为了让每次的随机数一样    int *arr = (int *)malloc(sizeof(int) * len);assert(arr != NULL);for(int i = 0;i < len;i ++){arr[i] = rand();}return arr;}static void swap(int *p,int *s){int tmp ;tmp = *p;*p = *s;*s = tmp;}void change_sort(int *arr,int len)  //两两比较,大的后换{if(arr == NULL|| len <= 0){return ;}for(int i = 0;i < len-1;i ++){for(int j = i+1;j <len;j ++){            if(arr[i] > arr[j])//0 和 所有比{swap(&arr[i],&arr[j]);}}}}void show(int *arr,int len,void pfunc(int *,int )){if(arr == NULL){return ;}pfunc(arr,len);}void bubble_sort(int *arr,int len) //冒泡排序,{if(arr == NULL|| len <= 0){return ;}for(int i = 0;i < len-1;i ++){for(int j = 0;j < len-1-i;j ++){if(arr[j] > arr[j + 1])//相邻两两比较{swap(&arr[j],&arr[j+1]);}}}}// 在改进的冒泡排序中,如果你第一堂没动,那就说明这个数组有序,不用在找第二大void bubble_sort_ex(int *arr,int len){bool flag = true;if(arr == NULL|| len <= 0){return ;}for(int i = 0;i < len-1 && flag;i ++){for(int j = 0;j < len-1-i;j ++){if(arr[j] > arr[j + 1]){swap(&arr[j],&arr[j+1]);flag = false;}}if(flag)  //一趟排序玩了以后,没有比较,这组数比较有序,直接跳出{break;}flag = true;}}void select_sort(int *arr,int len){bool flag = true;int min = arr[0]; //认为第一个数最小,下标最小int min_index = 0;int j = 0;if(arr == NULL|| len <= 0){return ;}for(int i = 0;i < len-1;i ++){min = arr[i];min_index = i;        for(j = i+1;j < len; j ++)    {    if(min > arr[j])//谁比最小还小,那就记录下来    {    min = arr[j];    min_index = j;    }    }if(min_index != i){swap(&arr[min_index],&arr[i]);}}}void insert_sort(int *arr,int len){int tmp ;if(arr == NULL|| len <= 0){return ;}for(int i = 1;i < len ; i ++)//多少趟{tmp = arr[i]; //不用比较,就一个值,不用比,直接入数组for(int j = 0;j < i; j ++)//一趟{             if(tmp < arr[j])  //一趟过程中发现,有第一个数小的那么,, { for(int k = i;k > j;k --)  //将后面的数,全部后移动。给这个数腾位置 {                     arr[k] = arr[k-1]; } arr[j] = tmp;  break; }}}}/*    未改进的插入,在每次进行数字恰当定位的时候,你就会发现大量数字进行移动,费时间改进后:    从右找,(因为在你没插入这个数的时候,人家的数组有序),如果你大那就直接往后挪,优点:这样子不是想未改进的,那样先找到,然后在整体该,太浪费时间*/void insert_sort_ex(int *arr,int len){int tmp ;int j = 0;if(arr == NULL|| len <= 0){return ;}for(int i = 1;i < len ; i ++){tmp = arr[i];for(j = i-1;j >= 0; j --){if(tmp > arr[j]){arr[j+1] = tmp;break;}arr[j+1] = arr[j]; //比它大,往后移动,直接就定位了}arr[j+1] = tmp;}}void shell_sort(int *arr,int len)//gas = 3{int tmp;int j = 0;int gas = 3;if(arr == NULL|| len <= 0){return ;}for(int i = gas;i<len ;i ++ )//整体在让每组有序{tmp = arr[i];for(j = i-gas;j >= 0; j = j - gas){if(tmp > arr[j]){arr[j+gas] = tmp;break;}arr[j+gas] = arr[j];}arr[j+gas] = tmp;}insert_sort_ex(arr,len);//再让整体有序}static int  partition(int *arr,int left,int right){int tmp = arr[left];while(left < right){while(arr[right] >= tmp && left < right )//在右边找到小的往前换{right --;}arr[left] = arr[right];while(arr[left] <= tmp && left < right )//在左边找到大的往后换{left ++;}arr[right] = arr[left];}arr[left] = tmp;return left;  //当你的左右相等时,就将这个值,赋值进去}static void quick(int *arr,int left,int right){int base;if(left < right){ base = partition(arr,left,right);//找到的支点所在的位置 quick(arr,left,base-1);//把支点左边的,以第一个数尾支点在做一次 quick(arr,base + 1,right);}}void quick_sort(int *arr,int len)//递归版本的快速排序{if(arr == NULL|| len <= 0){return ;}quick(arr,0,len-1);}void quick_sort_loop(int *arr,int len){int left = 0;int right = 0;int base;if(arr == NULL|| len <= 0){return ;}LINKSTACH *stack = init_stack();push(stack,0);//先将0入栈,再将len-1入栈,根据栈的性质先进后出push(stack ,len-1);while(!is_empty(stack)){         pop(stack,&right);//right = len-1  这里应该先出right,再出left pop(stack,&left);//left = 0;     //left 和right都已经有正确的值,相当于给right 和left已经复制 base = partition(arr,left,right); if(left < base-1) { push(stack,left); push(stack,base-1); } if(right > base + 1) { push(stack,base+1); push(stack,right); }}destroy_stack(stack);}static void heap_adjust(int *arr,int start,int end){int i = 2*start+1;//左孩子的计算公式  ----作用:记录左右孩子中最大的int tmp = arr[start];while(i < end)//判断是否存在左孩子----只要2*start+1在len的范围内就存在{/*     判断有没有右孩子----当你没有右孩子 根据&& 的性质就直接不走后面的比较                     ----当你有右孩子 根据&& 的性质,才能做后面的比较     也就是当你的有孩子大,那么i就停在有孩子身上*/if(i+1 < end && arr[i+1] > arr[i]){                              i ++;}if(arr[i] > tmp)//拿到最大值那就需要和tmp,也就是父跟点比一下{arr[start] = arr[i];}else{break;}start = i;//让start 记录父结点i = 2*start+1;}arr[start] = tmp;}void heap_sort(int *arr,int len){int start = len/2 -1;if(arr == NULL|| len <= 0){return ;}for(start = len/2 -1;start >= 0;start --){heap_adjust(arr,start,len);}swap(&arr[0],&arr[len-1]);for(int i = len-1;i > 0;i --){heap_adjust(arr,0,i);swap(&arr[0],&arr[i-1]);}}void meger(int *arr,int len,int gap){int L1 = 0;int H1 = L1+gap-1<len? L1+gap-1:len-1;int L2 = H1 + 1;int H2 = L2+gap-1<len? L2+gap-1:len-1;int k = 0;int *buff = (int *)malloc(sizeof(int) * len);assert(buff != NULL);/* 注:在归并的过程中,有可能出现的所有情况:    1.当L1都已经越界                ----- 没有元素了,该结束了--直接结束2.当L1存在的不完全的时候,L2没有 ---- 有元素,只存在在L1,--直接将L1下放到buff。3.当L2存在, -----------------------这个循环不用跳出,应该继续比较并赋值buff。*/ while(L1 < len && L1 <= H1)//当L2存在 { while(L2 < len  && L1 <= H1 && L2 <= H2  )// { if(arr[L1] <= arr[L2]) { buff[k++] = arr[L1 ++]; } else   { buff[k ++] = arr[L2 ++]; } } while( L1 < len && H1 < len && L1 <= H1 )//L1这个段中有数据 { buff[k++] = arr[L1 ++]; } while( L2 < len && H2 < len && L2 <= H2)  { buff[k++] = arr[L2 ++]; } L1 = H2 + 1; H1 = L1+gap-1< len ? L1+gap-1:len-1; L2 = H1 +1; H2 = L2+gap-1; }for(int i = 0;i < len ;i ++)//将buff里面的值全都倒回arr{arr[i] = buff[i];}    free(buff);}void meger_sort(int *arr,int len){if(arr == NULL || len <= 0){return ;}for(int i = 1;i < len; i = 2 * i){meger(arr,len,i);}}static char sort_menu(){printf("\n");printf("****************************\n");printf("******** 排序清单 **********\n");printf("********a.交换排序**********\n");printf("********b.冒泡排序**********\n");printf("******c.冒泡改进排序********\n");printf("********d选择排序***********\n");printf("********e.插入排序**********\n");printf("******f.插入改进排序********\n");printf("********g.希尔排序**********\n");printf("******h.快速排序(递归)****\n");printf("******i.快速排序(循环)****\n");printf("********j.堆排序************\n");printf("********k.归并排序************\n");printf("请输入你想要选择的排序:\n");char ch = 0;scanf("%c",&ch);fflush(stdin);return ch;}void print_int(int *arr,int len){for(int i = 0;i < len ;i ++){printf("%d ",arr[i]);}printf("\n");}void choose(int *arr,int len){char ch;Elect choose_way[]={{CHANGE ,change_sort},{BUBBLE, bubble_sort},{BUBBLE_EX,bubble_sort_ex},{SLECT ,select_sort},{INSERT,insert_sort},{INSERT_EX,insert_sort_ex},{SHELL,shell_sort},{QUICK,quick_sort},{QUICK_LOOP,quick_sort_loop},{HEAP  ,heap_sort},{MEGER ,meger_sort}};int len1 = sizeof(choose_way)/sizeof(choose_way[0]);while(1){ch = sort_menu();for(int i = 0;i < len1 ;i ++){if(choose_way[i].choice == ch){choose_way[i].pfunchoice(arr,len);}}show(arr,len,print_int);}}

MAIN.cpp

#include<stdio.h>#include<stdlib.h>#include<time.h>#include<vld.h>#include"SORT.h"int main(){int arr[] = {12,3,23,90,30,0,5,16,7,20,9};int len = sizeof(arr)/sizeof(arr[0]);//int *arr = ceart_arr(100000);//int len = 100000;choose(arr,len);return 0;}


在此外,还有快速排序,非递归的时候,用到链式栈,用到了栈。得取引进栈。http://blog.csdn.net/qq_35256722/article/details/52915814





0 0
原创粉丝点击