内部排序
- 这里先介绍一个概念,算法稳定性
- 算法稳定性 -- 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的!
| |
| void bubble_sort(int * arr,size_t n){ |
| bool sort =false; |
| for(int i=0;i<n;++i){ |
| for(int j=1;j<n-i;++j){ |
| if(arr[j]<arr[j-1]){ |
| swap...; |
| sort=true; |
| } |
| if(!sort) break; |
| } |
| } |
| } |
| |
| |
| |
| void insert_sort(int * arr,size_t n){ |
| for(int i=1;i<n;++i){ |
| int key = arr[i]; |
| for(int j=i;j>0 && key<arr[j];--j) |
| arr[j+1] = arr[j]; |
| if(j+1 != i) arr[j+1] = key; |
| } |
| } |
| |
| void bin_insert_sort(int * arr,size_t n){ |
| for(int i=1;i<n;++i){ |
| int L,R=i-1,key = arr[i]; |
| while(L<R){ |
| int mid = L + R >> 1; |
| if(arr[mid] <= key) L = mid+1; |
| else R = mid-1; |
| } |
| for(int j=j-1;j>L;--j) arr[j+i] = arr[j]; |
| arr[L] = key; |
| } |
| } |
| |
| void two_road_insert_sort(int * arr,size_t n){ |
| |
| } |
| |
| |
| |
| |
| |
| |
| |
| void shell_insert_sort(int * arr,size_t n){ |
| int i,j,gap; |
| for(gap=n/2;gap>0;gap/=2){ |
| for(i=gap;i<n;++i){ |
| int key =arr[i]; |
| |
| for(j=i-gap;j>=0&&key<arr[j];j-=gap) arr[j+gap] = arr[j]; |
| if(j+gap!=i) arr[j+gap]=key; |
| } |
| } |
| } |
| |
| |
| |
| void select_sort(int *arr, size_t n){ |
| int i; |
| int j; |
| int min; |
| for(i=0; i<n; i++){ |
| min=i; |
| |
| for(j=i+1; j<n && arr[j]<arr[min]; j++) min=j; |
| |
| |
| if(min!=i) swap(arr[i], arr[min]); |
| } |
| } |
| |
| |
| |
| |
| |
| void quick_sort(int * arr,size_t n){ |
| if(n<=1) return; |
| int ket= arr[0]; |
| int L=0,R=n-1; |
| while(L<R){ |
| while(L<R && key<=arr[R]) --R; |
| if(L<R) arr[L++]=arr[R]; |
| while(L<R && arr[L]<=key) ++L; |
| arr[R]=arr[L]; |
| if(L<R) arr[R--]=arr[L]; |
| } |
| arr[L] = key; |
| |
| if(L>1) quick_sort(arr,L); |
| |
| if(L+1<n) quick_sort(arr+L+1,n-L-1); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| void reheap(int * arr,int pos,size_t n){ |
| |
| int key = arr[pos]; |
| int child = 2*pos +1; |
| while(child < n){ |
| |
| if(child+1<n && arr[child]<arr[child+1]) ++child; |
| if(key < arr[child]){ |
| arr[pos] = arr[child]; |
| pos = child; |
| child = 2*pos +1; |
| }else break; |
| } |
| arr[pos] = key; |
| } |
| void heap_sort(int * arr,size_t n){ |
| int i; |
| |
| for(i=n/2-1;i>=0;--i) reheap(arr,i,n); |
| for(i=n-1;i>0;--i){ |
| |
| swap(arr[0],arr[i]); |
| |
| reheap(arr,0,i); |
| } |
| } |
| |
| |
| void cocktail_sort(int * arr,size_t n){ |
| int i,j; |
| for(i=0;i<n/2;++i){ |
| int minIndex = i; |
| int maxIndex = i; |
| for(j=i+1;j<n-i;++j){ |
| if(arr[j]<arr[minIndex]) minIndex = j; |
| else if(arr[maxIndex] < arr[j]) maxIndex = j; |
| } |
| int tmp = 0; |
| if(minIndex != i){ |
| tmp = arr[minIndex]; |
| arr[minIndex] = arr[i]; |
| arr[i] = tmp; |
| } |
| if(maxIndex == i) maxIndex = minIndex; |
| if(maxIndex != n-i-1){ |
| tmp = arr[maxIndex]; |
| arr[maxIndex] = arr[n-i-1]; |
| arr[n-i-1] = tmp; |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| void merge_part_sort(int * arr,size_t n){ |
| const int mid = n/2; |
| int brr[mid]; |
| int i,j,k; |
| for(i=0;i<mid;++i) brr[i] = arr[i]; |
| |
| i=0,j=0,k=mid; |
| while(j<mid && k<n){ |
| if(brr[j] < arr[k]) arr[i++] = brr[j++]; |
| else arr[i++] = arr[k++]; |
| } |
| while(j<mid) arr[i++] = brr[j++]; |
| |
| } |
| void merge_sort(int * arr,size_t n){ |
| if(arr==NULL || n<=1) return; |
| int mid = n/2; |
| merge_sort(arr,mid); |
| merge_sort(arr+mid,n-mid); |
| merge_part_sort(arr,n); |
| } |
| |
| |
| |
| |
| |
| |
| void bucketSort(int * arr, size_t n, int max) |
| { |
| if (arr==NULL || n<1 || max<1) return ; |
| int i,j; |
| int buckets[max]; |
| memset(buckets, 0, max*sizeof(int)); |
| |
| for(i = 0; i < n; i++) buckets[a[i]]++; |
| |
| for (i = 0, j = 0; i < max; i++) |
| { |
| while( (buckets[i]--) >0 ) |
| arr[j++] = i; |
| } |
| } |
| |
| |
| |
| |
| |
| |
| void radix_sort(int * arr,size_t n){ |
| int exp; |
| |
| int max = get_max(arr, n); |
| int tmp[n]; |
| int count[10]; |
| |
| int i,j; |
| for (exp = 1; max/exp > 0; exp *= 10){ |
| for(i = 0; i < 10; i++) count[j] = 0; |
| for(i = 0; i < n; i++) |
| ++count[(arr[j] / exp) % 10]; |
| for(i = 1; i < 10; i++) |
| count[j] = count[j - 1] + count[j]; |
| for(i = n - 1; i >= 0; i--) |
| { |
| tmp[count[k] - 1] = arr[(arr[j] / exp) % 10]; |
| count[k]--; |
| } |
| for(i = 0; i < n; i++) |
| arr[j] = tmp[j]; |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| void count_sort(int * arr,size_t n){ |
| int max = arr[0],min = arr[0]; |
| int i,j; |
| for(i=0;i<n;++i){ |
| if(arr[i]>max) max = arr[i]; |
| else if(arr[i]<min) min = arr[i]; |
| } |
| int cnt = max-min+1; |
| int flag[cnt]; |
| for(i=0;i<cnt;++i) flag[i] = 0; |
| |
| |
| for(i=0;i<n;++i) ++flag[arr[i]-min]; |
| |
| for(i=0,j=0;i<cnt;++i){ |
| while(flag[i]>0){ |
| arr[j++] = i+min; |
| --flag[i]; |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
外部排序
| |
| #define NUM_OF_SEGMENT 10 |
| |
| long num_of_file(const char *file){ |
| FILE *fp = fopen(file,"r"); |
| if(fp == NULL){ |
| return -1; |
| } |
| fseek(fp,0,SEEK_END); |
| long fs = ftell(fp); |
| fclose(fp); |
| return fs/4; |
| } |
| |
| #define FILE_NAME 48 |
| typedef struct MergeSegment{ |
| char file[FILE_NAME]; |
| size_t size; |
| size_t num; |
| FILE *fp; |
| }MSM; |
| |
| |
| bool is_completed(MSM *pms){ |
| return pms->size == pms->num; |
| } |
| |
| int load_data(MSM *pms,int data[]){ |
| if(is_completed(pms)){ |
| return 0; |
| } |
| int ret = fread(data,sizeof(int),NUM_OF_SEGMENT,pms->fp); |
| pms->num += ret; |
| return ret; |
| } |
| |
| int save_data(MSM *pms,int data[],size_t num){ |
| int ret = fwrite(data,sizeof(int),num,pms->fp); |
| pms->size += ret; |
| return ret; |
| } |
| |
| void fclose_file(MSM *pms){ |
| fclose(pms->fp); |
| } |
| |
| int open_file_read(MSM *pms){ |
| pms->fp = fopen(pms->file,"rb"); |
| if(pms->fp == NULL){ |
| printf("open %s failed!\n",pms->file); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int open_file_write(MSM *pms){ |
| pms->fp = fopen(pms->file,"wb"); |
| if(pms->fp == NULL){ |
| return -1; |
| } |
| return 0; |
| } |
| |
| |
| void init_segment(const char *file,MSM *msms,int segs){ |
| int data[NUM_OF_SEGMENT] = {}; |
| int i; |
| FILE *fp = fopen(file,"rb"); |
| for(i=0;i<segs;++i){ |
| int ret = fread(data,sizeof(int),NUM_OF_SEGMENT,fp); |
| quick_sort(data,ret); |
| |
| save_data(&msms[i],data,ret); |
| fclose_file(&msms[i]); |
| } |
| } |
| |
| void merge(MSM *pm1,MSM *pm2,MSM *pres){ |
| open_file_read(pm1); |
| open_file_read(pm2); |
| printf("[1]原始文件数据:fs1 = %d fn1 = %d, fs2 = %d fn1 = %d\n",pm1->size,pm1->num,pm2->size,pm2->num); |
| |
| strcpy(pres->file,"ab"); |
| strcat(pres->file,pm1->file); |
| pres->fp = NULL; |
| pres->num = pres->size = 0; |
| open_file_write(pres); |
| int data1[NUM_OF_SEGMENT] = {}; |
| int data2[NUM_OF_SEGMENT] = {}; |
| int i=0,j=0; |
| int cnt1 = 0,cnt2 = 0; |
| cnt1 = load_data(pm1,data1); |
| cnt2 = load_data(pm2,data2); |
| while(i<cnt1 && j<cnt2){ |
| if(data1[i] < data2[j]){ |
| save_data(pres,&data1[i],1); |
| ++i; |
| }else{ |
| save_data(pres,&data2[j],1); |
| ++j; |
| } |
| if(i==cnt1 && !is_completed(pm1)){ |
| cnt1 = load_data(pm1,data1); |
| i = 0; |
| } |
| if(j==cnt2 && !is_completed(pm2)){ |
| cnt2 = load_data(pm2,data2); |
| j = 0; |
| } |
| } |
| while(i<cnt1){ |
| save_data(pres,&data1[i],cnt1-i); |
| if(is_completed(pm1)){ |
| break; |
| } |
| cnt1 = load_data(pm1,data1); |
| i = 0; |
| } |
| while(j<cnt2){ |
| save_data(pres,&data2[j],cnt2-j); |
| if(is_completed(pm2)){ |
| break; |
| } |
| cnt2 = load_data(pm2,data2); |
| j = 0; |
| } |
| printf("[2]原始文件数据:fs1 = %d fn1 = %d, fs2 = %d fn1 = %d\n",pm1->size,pm1->num,pm2->size,pm2->num); |
| printf("写入文件大小 res fs=%d\n",pres->size); |
| } |
| |
| |
| int outside_sort(const char *file){ |
| assert(file!=NULL); |
| long cnt = num_of_file(file); |
| if(cnt == -1){ |
| return -1; |
| } |
| printf("%d\n",cnt); |
| |
| int segs = cnt/NUM_OF_SEGMENT; |
| if(cnt%NUM_OF_SEGMENT>0){ |
| ++segs; |
| } |
| MSM msms[segs]; |
| int i; |
| for(i=0;i<segs;++i){ |
| sprintf(msms[i].file,"%d.txt",i); |
| msms[i].num = 0; |
| msms[i].size = 0; |
| msms[i].fp = NULL; |
| open_file_write(&msms[i]); |
| } |
| init_segment(file,msms,segs); |
| |
| while(segs>1){ |
| MSM res = {}; |
| int cnt = 0; |
| for(i=0;i<segs;i+=2){ |
| if(i+1<segs){ |
| merge(&msms[i],&msms[i+1],&res); |
| fclose_file(&msms[i]); |
| unlink(msms[i].file); |
| fclose_file(&msms[i+1]); |
| unlink(msms[i+1].file); |
| fclose_file(&res); |
| msms[cnt++] = res; |
| }else{ |
| msms[cnt++] = msms[i]; |
| } |
| } |
| segs = cnt; |
| } |
| |
| printf("\n----------------------\n"); |
| FILE *fp = fopen(msms[0].file,"rb"); |
| int d = 0; |
| while(fread(&d,4,1,fp)>0){ |
| printf("%d ",d); |
| } |
| printf("\n"); |
| fclose(fp); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)