zoukankan      html  css  js  c++  java
  • (排序算法整理)NEFU 30/32

    版权声明:本文为博主原创文章,未经博主同意不得转载。

    https://blog.csdn.net/caihongshijie6/article/details/26165093


           事实上,在ACM比赛时,非常少人会自己去写寻常时的那种排序算法。都是直接使用库函数里面的排序算法。可是表示或者是面试的时候一般会问道这些主要的算法。

    所以今天就把排序算法发整理了一下。也在OJ上找了几道简单题来验证一下。


    如今把当中主要的排序算法整理例如以下(临时还没有将堆排序的实现贴上来):

    /*
     * nefu_sort.cpp
     *
     *  Created on: 2014年5月18日
     *      Author: pc
     */
    
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    int n;
    
    /**
     * 第一种交换算法:
     * 借助中间变量
     */
    void swap1(int arr[],int i,int j){
    	int temp = arr[i];
    	arr[i] = arr[j];
    	arr[j] = temp;
    }
    
    /**
     * 另外一种交换算法:
     * 不借助中间变量,使用算术运算
     */
    void swap2(int arr[],int i, int j){
    	arr[i] = arr[i] + arr[j];
    	arr[j] = arr[i] - arr[j];
    	arr[i] = arr[i] - arr[j];
    }
    
    /**
     * 第三种交换算法:
     * 使用位运算
     */
    void swap3(int arr[], int i, int j){
    	arr[i] = arr[i]^arr[j];
    	arr[j] = arr[i]^arr[j];
    	arr[i] = arr[i]^arr[j];
    }
    
    
    /**
     * 冒泡排序的第一种方式:
     * 标准方式
     */
    void bubblesort1(int arr[],int n){
    	int i;
    	int j;
    	for(i = 0 ; i < n-1 ;++i){//循环n-1次(由于1个数默觉得有序的状态),每次能是一个数达到有序状态
    		for(j = 0 ; j < n-i-1 ; ++j){//每次将从第一个数到有序状态之前的数进行比較(有序状态以后的数不再须要进行比較)
    			if(arr[j] > arr[j+1]){//假设前面的数大于后面的数
    				swap3(arr,j,j+1);//则进行交换
    			}
    		}
    	}
    }
    
    
    /**
     * 冒泡排序的另外一种方式:採用"扫描一遍以后,假如没有发生交换,即是达到了有序状态"的特点进行优化
     */
    void bubblesort2(int arr[],int n){
    	int k = n;
    	bool flag = true;
    	while(flag){
    		flag = false;
    		for(int j = 0 ; j < k-1 ; ++j){
    			if(arr[j] > arr[j+1]){
    				swap3(arr,j,j+1);
    				flag = true;//用来标记这一次是否发生了交换
    			}
    		}
    		--k;
    	}
    }
    
    
    /**
     * 冒泡排序的第三种方式:在另外一种的基础上,用于处理"假如有100个数据,假如后90个都已经有序的情况"
     */
    void bubblesort3(int arr[],int n){
    	int k;
    	int flag = n;
    	while(flag > 0){
    		k = flag;
    		flag = 0;
    		for(int j = 1 ; j < k ; ++j){
    			if(arr[j-1] > arr[j]){
    				swap3(arr,j-1,j);
    				flag = j;//对方式2的改进...用来标记发生交换的是哪一个位置
    			}
    		}
    	}
    }
    
    void insertsort1(int arr[], int n){
    	int i;
    	for(i = 1 ; i < n ; ++i){//当仅仅有一个数的时候默认是有序的,所以从第二个位置上開始考虑
    		int j;
    		for(j = i-1 ; j >= 0 ; --j){//从当前位置往前找合适的位置
    			if(arr[j] < arr[i]){
    				break;
    			}
    		}
    
    		if(j != i-1){//假设找到了合适的位置...假设j=i-1,则说明[0-i]都是有序的
    
    			int temp = arr[i];//保存当前位置的数
    			int k;
    			for(k = i-1 ; k > j ; --k){//将i-1位置到j位置上的书往后移
    				arr[k+1] = arr[k];
    			}
    
    			arr[k+1] = temp;//将原来i位置上的数放到j位置后面
    		}
    	}
    }
    
    void insertsort2(int arr[],int n){
    	int i;
    	for(i = 1 ; i < n ; ++i){//从第二个位上開始扫
    		if(arr[i-1] > arr[i]){//假设找到一个位置,他的后面一个数要比他的前面一个数小
    			int j;
    			int temp = arr[i];//将当前位置上的数保存
    			for(j = i-1 ; j >= 0 && arr[j] > temp ; --j){//将i-1位置及之前的比arr[i]大的数都往后移一位
    				arr[j+1] = arr[j];
    			}
    
    			arr[j+1] = temp;//将arr[i]插入到从后面数比arr[i]小的第一个数的后面
    		}
    	}
    }
    
    
    /**
     * 希尔排序中的插入的逻辑部分
     */
    void shellinsert(int arr[],int d , int n){
    	int i;
    	for(i = d ; i < n ; ++i){//循环遍历依据步长分成的组.(步长为n。就分成了n个组)
    
    		int temp = arr[i];//保存当前位置的值
    		int j;
    		for(j = i-d ; j>= 0 && arr[j] > temp ; j -= d){//寻找合适的位置.从后往前找,找到那个比当前位置的数小的位置
    			arr[j+d] = arr[j];//将找到的位置后面的书都往后移
    		}
    
    		if(j != i-d){//假设找到了合适的位置
    			arr[j+d] = temp;//将当前位置的数放到合适的位置
    		}
    	}
    }
    
    /**
     * 希尔排序
     */
    void shellsort(int arr[],int n){
    	int d = n/2;//设置初始步长
    	while(d>=1){
    		shellinsert(arr,d,n);//将整个序列划分成若干个子序列,对子序列运行插入排序
    		d /= 2;//不断地缩小步长
    	}
    }
    
    
    /**
     * 选择排序
     */
    void selectsort(int arr[] , int n){
    	for(int i = 0 ; i < n-1 ; ++i){//扫描序列n-1次
    		int index = i;
    
    		for(int j = i+1 ; j < n ; ++j){//从i+1的位置開始扫
    			if(arr[j] < arr[index]){
    				index = j;//找到该次所扫描的序列的最小值
    			}
    		}
    		if(index != i){//假设最小数的位置发生变换
    			swap3(arr,i,index);//则进行交换
    		}
    	}
    }
    
    
    
    /**
     * 合并有序序列
     */
    void mergeArr(int arr[],int first, int mid , int last,int temp[]){
    	int i = first,j = mid+1;
    	int m = mid,n = last;
    	int k = 0;
    
    	while(i <= m && j <= n){//当两个序列都还有值的时候
    		if(arr[i] <= arr[j]){//去两个序列中的最小值
    			temp[k++] = arr[i++];
    		}else{
    			temp[k++] = arr[j++];
    		}
    	}
    
    	//下面两个循环用于处理某一个序列没有值的情况
    	while(i <= m ){
    		temp[k++] = arr[i++];
    	}
    
    	while(j <= n){
    		temp[k++] = arr[j++];
    	}
    
    	//更新原序列
    	for(i = 0 ; i < k ;++i){
    		arr[first+i] = temp[i];
    	}
    }
    
    
    /**
     * 归并排序
     */
    void mergeSort(int arr[],int first,int last,int temp[]){
    	if(first < last){//假设还没切割到仅仅剩一个元素,就不断的切割
    		int mid = (first+last)/2;
    		mergeSort(arr,first,mid,temp);//达到左边有序的状态
    		mergeSort(arr,mid+1,last,temp);//达到右边有序的状态
    		mergeArr(arr,first,mid,last,temp);//归并
    	}
    }
    
    
    void quicksort(int arr[],int l,int r){
    	int i = l;
    	int j = r;
    	int x = arr[l];//将最左边的数作为基准数
    
    	if(l < r){
    		while(i < j){//假设i!=j就不断的进行循环
    
    			while(i < j && arr[j] >= x){//从后往前扫,找到第一个比基准数小的数
    				--j;
    			}
    			if(i < j){//假设找到了
    				arr[i++] = arr[j];//将坑填上,并将i的值++
    			}
    
    			while(i < j && arr[i] <= x){//从前往后扫,找到第一个比基准数大的数
    				++i;
    			}
    			if(i < j){
    				arr[j--] = arr[i];//将坑填上,并将j的值--
    			}
    		}
    		arr[i] = x;//将最后的基准位置上的坑填上
    
    		//分治策略
    		quicksort(arr,l,i-1);//递归调用
    		quicksort(arr,i+1,r);
    	}
    }
    
    
    
    void printArr(int arr[]){
    	int i;
    	for(i = 0 ; i < n ; ++i){
    		printf("%d " , arr[i]);
    	}
    	printf("
    ");
    }
    
    void handleInput(int arr[]){
    	int i;
    	for(i = 0 ; i < n ; ++i){
    		scanf("%d",&arr[i]);
    	}
    }
    


    二、下面用这些算法来做几道简单题

    在上面的基础上

    nefu 30


    void handleInput1(int arr[],int n){
    	int i;
    	for(i = 1 ; i < n ; ++i){
    		scanf("%d",&arr[i]);
    	}
    }
    
    int main(){
    	n = 10;
    	int arr[n];
    	while(scanf("%d",&arr[0])!=EOF){
    		handleInput1(arr,n);
    		shellsort(arr,n);//这里能够换成各种各样的算法
    		printArr(arr);
    	}
    
    	return 0;
    }
    

    nefu 32

    #include "sort.h"
    
    int main(){
    	int t;
    	scanf("%d",&t);
    
    	while(t--){
    		scanf("%d",&n);
    		int arr[n];
    
    		int temp[n];
    		handleInput(arr);
    //		selectsort(arr,n);
    		mergeSort(arr,0,n-1,temp);
    		printArr(arr);
    	}
    }
    


    NEFU 100 查找最大值

    这道题的话。事实上也属于排序题。先按升序排一下序,然后输出最后一个即可了

    /*
     * 100.cpp
     *
     *  Created on: 2014年5月22日
     *      Author: pc
     */
    
    
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    const int maxn = 1005;
    int arr[maxn];
    
    void quicksort(int arr[],int l,int r){
    	int i = l;
    	int j = r;
    	int x = arr[l];//将最左边的数作为基准数
    
    	if(l < r){
    		while(i < j){//假设i!=j就不断的进行循环
    
    			while(i < j && arr[j] >= x){//从后往前扫,找到第一个比基准数小的数
    				--j;
    			}
    			if(i < j){//假设找到了
    				arr[i++] = arr[j];//将坑填上,并将i的值++
    			}
    
    			while(i < j && arr[i] <= x){//从前往后扫,找到第一个比基准数大的数
    				++i;
    			}
    			if(i < j){
    				arr[j--] = arr[i];//将坑填上,并将j的值--
    			}
    		}
    		arr[i] = x;//将最后的基准位置上的坑填上
    
    		//分治策略
    		quicksort(arr,l,i-1);//递归调用
    		quicksort(arr,i+1,r);
    	}
    }
    
    
    int main(){
    	int n;
    	while(scanf("%d",&n)!=EOF){
    		int i;
    		for(i = 0 ; i < n ; ++i){
    			scanf("%d",&arr[i]);
    		}
    
    		quicksort(arr,0,n-1);
    
    		printf("%d
    ",arr[n-1]);
    	}
    
    	return 0;
    }
    






  • 相关阅读:
    Hashmap
    string字符串分词
    关于链表的几道经典例题
    【C语言】链表(LinkedList)的建立与基本操作
    01迷宫
    2019 数学联赛 题解 / 游记
    一种简单方法构造 n 元有限域
    Python逆向某网站之 AES解密数据
    我发现了一个网站Bug,然后反馈了
    在多线程中使用静态方法是否有线程安全问题
  • 原文地址:https://www.cnblogs.com/mqxnongmin/p/10516807.html
Copyright © 2011-2022 走看看