精华内容
下载资源
问答
  • excel 区域内按行排序 Excel 2010中对行进行排序 (Sort a Row in Excel 2010) Most of the time when you're sorting in Excel, you sort based on the values in one or more columns. If your workbooks are ...

    excel 区域内按行排序

    Most of the time when you're sorting in Excel, you sort based on the values in one or more columns. If your workbooks are like mine, it's rare that you sort horizontally, based on the values in a row. But if you need to do that, here's how to sort a row in Excel.

    大多数情况下, 在Excel中进行排序时,都是基于一列或多列中的值进行排序。 如果您的工作簿像我的工作簿,那么很少会根据一行中的值进行水平排序。 但是,如果您需要这样做,这里是在Excel中对行进行排序的方法。

    排序行 (Sort a Row)

    Usually we sort by the values in a column in Excel. It is possible though, to sort by the values in a row, and you can sort in ascending, descending, or custom sort order.

    通常,我们按Excel列中的值进行排序。 但是,可以按行中的值进行排序,并且可以按升序,降序或自定义排序顺序进行排序。

    excelsort11

    更改排序选项 (Change the Sort Options)

    To sort by row, click the Options button in the Sort dialog box. Then, in the Sort Options, select Sort Left to Right.

    要按行排序,请单击“排序”对话框中的“选项”按钮。 然后,在“排序选项”中,选择“从左到右排序”。

    excelsort16

    In the screen shot below, the total row has been sorted, so the month with the highest total is at the left.

    在下面的屏幕截图中,总计行已排序,因此总计最高的月份在左侧。

    excelsort18

    Excel 2010排序 (Excel 2010 Sorting)

    So much has changed in Excel 2010 and Excel 2007 sorting, that I've finally updated the sorting in Excel page on the Contextures website. You can find the detailed instructions for sorting by row, and other sorting tips.

    Excel 2010和Excel 2007排序发生了很大变化,我终于更新了Contextures网站上Excel页面中的排序 。 您可以找到有关按行排序的详细说明以及其他排序提示。

    There is also an Excel sorting sample workbook that you can download, at the bottom of the sorting page.

    排序页面底部还有一个Excel排序示例工作簿,您可以下载。

    观看Excel 2010排序视频 (Watch the Excel 2010 Sorting Video)

    To see the steps for sorting a row in Excel 2010, watch this short Excel video tutorial.

    若要查看在Excel 2010中对行进行排序的步骤,请观看此简短的Excel视频教程。

    演示地址

    翻译自: https://contexturesblog.com/archives/2011/07/11/sort-a-row-in-excel-2010/

    excel 区域内按行排序

    展开全文
  • 冒泡排序、选择排序、插入排序、快速排序、希尔排序

    一、冒泡排序

    1.1 冒泡排序基础【必会知识】

      冒泡排序是比较基础的排序算法之一,其思想是相邻的元素两两比较,较大的数下沉,较小的数冒起来,这样一趟比较下来,最大(小)值就会排列在一端。整个过程如同气泡冒起,因此被称作冒泡排序。
      冒泡排序的步骤是比较固定的:

    1>比较相邻的元素。如果第一个比第二个大,就交换他们两个。
    2>每趟从第一对相邻元素开始,对每一对相邻元素作同样的工作,直到最后一对。
    3>针对所有的元素重复以上的步骤,除了已排序过的元素(每趟排序后的最后一个元素),直到没有任何一对数字需要比较。

      此处引用网上一张比较经典的gif来展示冒泡排序的整个过程:

      冒泡排序的常规实现代码如下:

    	public static void bubbleSort(int[] arr) {
    		/*判断数组为空或为一个元素的情况,即边界检查*/
    		if (arr == null || arr.length < 2) {
    			return;
    		}
    		
    		/*规定每次两两比较的末尾元素的位置,最多为数组的最后一个位置*/
    		for (int end = arr.length - 1; end > 0; end--) {
    			/*从第一个元素开始,两两进行比较,如果前面的元素大于后面的
    			  元素,就交换,最终的结果就是最大的数在最后面
    			*/
    			for (int i = 0; i < end; i++) {
    				if (arr[i] > arr[i + 1]) {
    					swap(arr, i, i + 1);
    				}
    			}
    		}
    	}
    
    	public static void swap(int[] arr, int i, int j) {
    		int tmp = arr[i];
    		arr[i] = arr[j];
    		arr[j] = tmp;
    	}
    

    1.2 冒泡排序优化

      上个章节介绍了冒泡排序的常规实现,但是这种最简单的排序是存在着不必要的比较动作的。稍微修改上述代码,就可以查看每次比较后的结果:

            int[ ] array=new int[ ]{5,2,3,9,4};
            /*外循环为排序趟数,array.length个数进行array.length-1趟 */
            for(int i=0;i<array.length-1;i++){
            	/*内循环为每趟比较的次数,第i趟比较array.length-i次 */
                for(int j=0;j<array.length-1-i;j++){
                	 /*相邻元素比较,若满足条件则交换(升序为左大于右,降序反之) */
                    if(array[j]>array[j+1]){
                        int temp=array[j];
                        array[j]=array[j+1];
                        array[j+1]=temp;
                    }
                    /*查看每趟比较后的数组元素*/
                    System.out.println("第 "+(i+1)+" 趟,第 "+(j+1)+" 次比较后的结果:");
                    for(int k=0;k<array.length;k++){
                        System.out.print(array[k]+" ");
                    }
                    System.out.println();
                }
            }
    

      该代码的输出结果为:

    第 1 趟,第 1 次比较后的结果:
    2 5 3 9 4
    第 1 趟,第 2 次比较后的结果:
    2 3 5 9 4
    第 1 趟,第 3 次比较后的结果:
    2 3 5 9 4
    第 1 趟,第 4 次比较后的结果:
    2 3 5 4 9
    第 2 趟,第 1 次比较后的结果:
    2 3 5 4 9
    第 2 趟,第 2 次比较后的结果:
    2 3 5 4 9
    第 2 趟,第 3 次比较后的结果:
    2 3 4 5 9
    第 3 趟,第 1 次比较后的结果:
    2 3 4 5 9
    第 3 趟,第 2 次比较后的结果:
    2 3 4 5 9
    第 4 趟,第 1 次比较后的结果:
    2 3 4 5 9

      从上面的测试结果可以看出,从第2趟第3次比较后,数组元素已经处于有序状态,此后所有的比较都不必进行。

    1.2.1 外循环优化

      第一种优化就基于上面的测试结果来进行,如果某次比较过程中,发现没有任何元素移动,则不再进行接下来的比较。具体的做法是在每趟比较时,引入一个boolean型变量isSwap,来判断下次比较还有没有必要进行。示例代码如下:

            int[ ] array=new int[ ]{5,2,3,9,4};
            /*外循环为排序趟数,array.length个数进行array.length-1趟 */
            for(int i=0;i<array.length-1;i++){
            	boolean isSwap=false;
            	/*内循环为每趟比较的次数,第i趟比较array.length-i次 */
                for(int j=0;j<array.length-1-i;j++){
                	 /*相邻元素比较,若满足条件则交换(升序为左大于右,降序反之) */
                    if(array[j]>array[j+1]){
                        int temp=array[j];
                        array[j]=array[j+1];
                        array[j+1]=temp;
                        isSwap=true;
                    }
                    /*查看每趟比较后的数组元素*/
                    System.out.println("第 "+(i+1)+" 趟,第 "+(j+1)+" 次比较后的结果:");
                    for(int k=0;k<array.length;k++){
                        System.out.print(array[k]+" ");
                    }
                    System.out.println();
                }
                /*如果没有交换过元素,则已经有序,不再进行接下来的比较*/
                if(!isSwap){
                	break;
                }
            }
    

      测试结果如下:

    第 1 趟,第 1 次比较后的结果:
    2 5 3 9 4
    第 1 趟,第 2 次比较后的结果:
    2 3 5 9 4
    第 1 趟,第 3 次比较后的结果:
    2 3 5 9 4
    第 1 趟,第 4 次比较后的结果:
    2 3 5 4 9
    第 2 趟,第 1 次比较后的结果:
    2 3 5 4 9
    第 2 趟,第 2 次比较后的结果:
    2 3 5 4 9
    第 2 趟,第 3 次比较后的结果:
    2 3 4 5 9
    第 3 趟,第 1 次比较后的结果:
    2 3 4 5 9
    第 3 趟,第 2 次比较后的结果:
    2 3 4 5 9

      从上面的测试结果可以看出,已经对排序过程进行了优化,因为没有进行第4趟比较。也许有人会有疑问“第2趟比较结束后,数组已经有序了,为什么还要进行第3次比较”?之所以对此有疑问,可能是没太清楚isSwap变量的作用,该变量的作用是“假如本趟比较过程中没有交换发生,则不必进行下一趟比较”,在第2趟比较过程中,发生了交换动作,所以第3趟比较仍会进行。

    1.2.2 内循环优化

      第一种优化方式比较容易理解,但同时也存在着缺点:某趟比较只要开始,哪怕数组元素已经有序,也要把该趟的所有次比较完。也就是说,第一种优化方式,只能在“趟”的级别上优化。
      第二种优化方式,也就是要实现在“次”的级别进行优化,其思路是“记下最后一次交换的位置,后边没有交换,必然是有序的,然后下一次排序从第一个比较到上次记录的位置结束即可”。示例代码为:

            int[ ] array = new int[ ]{5,2,3,7,9};
            int position = array.length - 1;
            /*外循环为排序趟数,array.length个数进行array.length-1趟 */
            for(int i = 0;i<array.length-1;i++){
            	boolean isSwap = false;
            	/*用来记录最后一次交换的位置*/
            	int newPosition = 0;
            	/*内循环为每趟比较的次数,第i趟比较array.length-i次 */
                for(int j = 0;j<position;j++){
                	 /*相邻元素比较,若满足条件则交换(升序为左大于右,降序反之) */
                    if(array[j]>array[j+1]){
                        int temp = array[j];
                        array[j] = array[j+1];
                        array[j+1] = temp;
                        isSwap = true;
                        /*记录最后一次交换的位置*/
                        newPosition = j;
                    }
                    /*查看每趟比较后的数组元素*/
                    System.out.println("第 "+(i+1)+" 趟,第 "+(j+1)+" 次比较后的结果:");
                    for(int k = 0;k<array.length;k++){
                        System.out.print(array[k]+" ");
                    }
                    System.out.println();
                }
                /*如果没有交换过元素,则已经有序,不再进行接下来的比较*/
                if(!isSwap){
                	break;
                }
                /*下趟比较所需要比较到的位置*/
                position = newPosition;
            }
    

      测试结果如下:

    第 1 趟,第 1 次比较后的结果:
    2 5 3 7 9
    第 1 趟,第 2 次比较后的结果:
    2 3 5 7 9
    第 1 趟,第 3 次比较后的结果:
    2 3 5 7 9
    第 1 趟,第 4 次比较后的结果:
    2 3 5 7 9
    第 2 趟,第 1 次比较后的结果:
    2 3 5 7 9

      从上面的测试结果可以看出,在第2趟进行了1次比较后,数组元素已经处于有序状态,此时便不再进行接下来的比较。

    1.2.3 双向遍历

      上面的两种优化都是单向遍历比较的,然而在很多时候,遍历的过程可以从两端进行,从而提升效率。因此在冒泡排序中,其实也可以进行双向循环,正向循环把最大元素移动到数组末尾,逆向循环把最小元素移动到数组首部。该种排序方式也叫双向冒泡排序,也叫鸡尾酒排序。
      关于此种排序优化,示例代码如下:

    	static void bubbleSort(int[] array) {
            int arrayLength = array.length;
            
            int preIndex = 0;
            int backIndex = arrayLength - 1;
            while(preIndex < backIndex) {
                preSort(array, arrayLength, preIndex);
                preIndex++;
                
                if (preIndex >= backIndex) {
                    break;
                }
                
                backSort(array, backIndex);
                backIndex--;
            }
        }
        
        // 从前向后排序
    	static void preSort(int[] array, int length, int preIndex) {
            for (int i = preIndex + 1; i < length; i++) {
                if (array[preIndex] > array[i]) {
                    swap(array, preIndex, i);
                }
            }
        }
        
        // 从后向前排序
    	static void backSort(int[] array, int backIndex) {
            for (int i = backIndex - 1; i >= 0; i--) {
                if (array[i] > array[backIndex]) {
                    swap(array, i, backIndex);
                }
            }
        }
    	
    	static void swap (int[] arr, int i, int j) {
    		int temp = arr[i];
    		arr[i] = arr[j];
    		arr[j] = temp;
    	}
    

    1.3 冒泡排序的稳定性、复杂度和适用场景

    1.3.1 稳定性

      在冒泡排序中,遇到相等的值,是不进行交换的,只有遇到不相等的值才进行交换,所以是稳定的排序方式。

    1.3.2 时间复杂度

      如果待排序序列的初始状态恰好是我们希望的排序结果(如升序或降序),一趟扫描即可完成排序。所需的关键字比较次数C和记录移动次数M均达到最小值:
            
      冒泡排序最好的时间复杂度为O(n)。

      如果待排序序列是反序(如我们希望的结果是升序,待排序序列是降序)的,需要进行n-1趟排序。每趟排序要进行n-i次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:
            在这里插入图片描述
      冒泡排序的最坏时间复杂度为O(n2)。
      综上,因此冒泡排序总的平均时间复杂度为O(n2)。

    1.3.3 适用场景

      冒泡排序适用于数据量很小的排序场景,因为冒泡的实现方式较为简单。

    二、选择排序

    2.1 选择排序基础【必会知识】

      选择排序是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,继续放在起始位置知道未排序元素个数为0。
      选择排序的步骤:

    1>首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
    2>再从剩余未排序元素中继续寻找最小(大)元素,然后放到未排序序列的起始位置。
    3>重复第二步,直到所有元素均排序完毕。

      此处引用网上一张比较经典的gif来展示选择排序的整个过程:

      用代码来实现上述过程,示例如下:

    	public static void selectionSort(int[] arr) {
    		/*判断数组为空或为一个元素的情况,即边界检查*/
    		if (arr == null || arr.length < 2) {
    			return;
    		}
    
    		/*每次要进行比较的两个数,的前面那个数的下标*/
    		for (int i = 0; i < arr.length - 1; i++) { 
    			//min变量保存该趟比较过程中,最小元素所对应的索引,
    			//先假设前面的元素为最小元素
    			int minIndex = i;
    			/*每趟比较,将前面的元素与其后的元素逐个比较*/
    			for (int j = i + 1; j < arr.length; j++) {
    				//如果后面的元素小,将后面元素的索引极为最小值的索引
    				if(arr[j] < arr[minIndex]) {
    					minIndex = j;
    				}
    			}
    			//然后交换此次查找到的最小值和原始的最小值
    			swap(arr, i, minIndex);
    		}
    	}
    
    	public static void swap(int[] arr, int i, int j) {
    		int tmp = arr[i];
    		arr[i] = arr[j];
    		arr[j] = tmp;
    	}
    

    2.2 选择排序优化

    2.2.1 选择排序优化图示

      选择排序的优化思路一般是在一趟遍历中,同时找出最大值与最小值,放到数组两端,这样就能将遍历的趟数减少一半。第一次选择最大值与最小值,过程如下:
          

    2.2.2 选择排序优化实现

      示例代码如下:

            /*初始化左端、右端元素索引*/
    	    int left = 0;
    	    int right = len - 1;
    	    while (left < right){
    	    	/*初始化最小值、最大值元素的索引*/
    	        int min = left;
    	        int max = right;
    	        for (int i = left; i <= right; i++){
    	        	/*标记每趟比较中最大值和最小值的元素对应的索引min、max*/
    	            if (arr[i] < arr[min])
    	                min = i;
    	            if (arr[i] > arr[max])
    	                max = i;
    	        }
    	        /*最大值放在最右端*/
    	        int temp = arr[max];
    	        arr[max] = arr[right];
    	        arr[right] = temp;
    	        /*此处是先排最大值的位置,所以得考虑最小值(arr[min])在最大位置(right)的情况*/
    	        if (min == right)
    	            min = max;
    	        /*最小值放在最左端*/
    	        temp = arr[min];
    	        arr[min] = arr[left];
    	        arr[left] = temp;
    	        /*每趟遍历,元素总个数减少2,左右端各减少1,left和right索引分别向内移动1*/
    	        left++;
    	        right--;
    	    }
    

    2.3 选择排序的稳定性、复杂度及适用场景

    2.3.1 稳定性

      在选择排序中,每趟都会选出最大元素与最小元素,然后与两端元素交换,此时,待排序序列中如果存在与原来两端元素相等的元素,稳定性就可能被破坏。如[5,3,5,2,9],在array[0]与array[3]元素交换时,序列的稳定性就被破坏了,所以选择排序是一种不稳定的排序算法。

    2.3.2 时间复杂度

      选择排序的时间复杂度为O(n2)。

    2.3.3 适用场景

      待排序序列中,元素个数较少时。

    三、插入排序

    3.1 插入排序基础【必会知识】

      插入排序也是一种常见的排序算法,插入排序的思想是:将初始数据分为有序部分和无序部分,每一步将一个无序部分的数据插入到前面已经排好序的有序部分中,直到插完所有元素为止。
      插入排序的步骤如下:每次从无序部分中取出一个元素,与有序部分中的元素从后向前依次进行比较,并找到合适的位置,将该元素插到有序组当中。

      假如有[5,2,3,9,4,7]六个元素,下面就以排序过程中的一个步骤(此时有序部分为[2,3,5,9],无序部分为[4,7],接下来要把无序部分的“4”元素插入到有序部分),来展示一下插入排序的运行过程。

    1. 首先,原始的数组元素是这样的。
            
        其中,浅绿色代表有序部分,黄色代表无序部分。
    2. 在无序部分中挑出要插入到有序部分中的元素。
            
    3. 将要插入的元素与左边最近的有序部分的元素进行比较。由于4 < 9,所以9向后移,4向前移。
            
    4. 继续将要插入的元素与左边最近的有序部分的元素进行比较。由于4 < 5,所以5向后移,4继续向前移。
            
    5. 继续将4与3比较。由于4 > 3,所以不再向前比较,插入到当前位置。
            
    6. 此时有序部分,由[2,3,5,9]变成[2,3,4,5,9]。
            

      将上述过程用代码实现,示例如下:

    	public static void insertionSort(int[] arr) {
    		if (arr == null || arr.length < 2) {
    			return;
    		}
    		
    		//每次将从0-i位置的元素进行排序
    		for (int i = 1; i < arr.length; i++) { // 0 ~ i 做到有序
    			//int j = i - 1; j >= 0表示左边位置的边界条件
    			//arr[j] > arr[j + 1]表示最右边的数与相邻数的比较
    			//j--表示将这个过程向左推进
    			//swap(arr, j, j + 1)表示进行两个相邻数比较时,左边的数大于右边数时,才交换否则不交换
    			for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
    				swap(arr, j, j + 1);
    			}
    		}
    	}
    
    	public static void swap(int[] arr, int i, int j) {
    		int tmp = arr[i];
    		arr[i] = arr[j];
    		arr[j] = tmp;
    	}
    

    3.2 插入排序优化

      插入排序的优化方式一般有两种:折半插入排序和2-路插入排序。

    3.2.1 折半插入排序

      该类优化有二分的思想,是在将待排序的元素与有序部分的元素比较时,不再挨个比较,而是用二分折中的方式进行比较,加快比较效率。示例代码如下:

    	    int j,low,mid,high,temp;
    	    for(int i = 1;i<n;i++){
    	        low = 0;
    	        high = i-1;
    	        temp = arr[i];
    	        /*找到合适的插入位置high+1,如果中间位置元素
    	         *比要插入元素大,则查找区域向低半区移动,否
    	         *则向高半区移动
    	         */
    	        while(low <= high){
    	            mid = (low+high)/2;
    	            if(arr[mid]>temp){
    	                high = mid-1;
    	            }else{
    	                low = mid+1;
    	            }
    	        }
    	        /*high+1后的元素后移*/
    	        for(j = i-1;j >= high+1;j--)    
    	        {
    	            arr[j+1] = arr[j];
    	        }
    	        /*将元素插入到指定位置*/
    	        arr[j+1] = temp;    
    	    }
    

    3.2.2 2-路插入排序

      该中方式是在折半插入排序的基础上再进行改进的算法,其目的是减少排序过程中移动记录的次数,付出的代价是n个记录的辅助空间。
      假设原数组为 arr,另设一个相同类型的数组 tempArr,先将 arr[0] 赋值给 tempArr[0],并将tempArr[0] 看成是在有序序列中处于中间位置的元素,然后从 arr[1] 起一次插入到 tempArr[1] 之前或之后的有序序列中。
      先将待插元素和tempArr[0] 做比较,若小于tempArr[0],则插入tempArr[0] 之前的有序部分;反之,将其插入tempArr[0] 之后的有序部分中。在实现算法时,可将tempArr看成一个循环数组,并设 first 和last分别指向排序过程中得到的有序序列中的第一个元素和最后一个元素在tempArr中的位置。示例代码如下:

            int j, first, last, mid;
            /*临时数组*/
            int[ ] tempArr =new int[len];        
            tempArr[0] = arr[0];
            /*first和last分别指临时数组tempArr中排好序的元素的第一个和最后一个位置*/
            first = last = 0;       
    
            for(int i = 1; i<len; i++){
            	/*j 是调整系数*/
                if(first > last){
                    j = len;        
                }else{
                    j = 0;
                }
                /*tempArr中间元素的位置*/
                mid = ((first+last+j)/2)%len; 
                /*arr[i]应该插入在tempArr的前半部分*/
                if(arr[i] < tempArr[mid]){      
                	/*j指向tempArr数组中的第一个元素*/
                    j = first;    
                    /*first 前移,取余是为了实现循环数组效果*/
                    first = (first-1+len)%len;  
                    /*待插元素大于 j 所指元素*/
                    while(arr[i] > tempArr[j]){    
                    	/*j 所指元素前移,取余是为了实现循环数组效果*/
                    	tempArr[(j-1+len)%len] = tempArr[j];  
                    	/*j 指向下一个元素*/
                        j = j+1;               
                    }
                    /*移动结束,待插元素插在tempArr[j]前*/
                    tempArr[(j-1+len)%len] = arr[i];    
                /*arr[i]应该插入在tempArr的后半部分*/
                }else{   
                	/*j指向tempArr数组中的最后一个元素*/
                    j = last;    
                    /*last后移, 指向插入后的最后一个元素*/
                    last++;            
                    /*待插元素小于 j 所指元素*/
                    while(arr[i] < tempArr[j]){  
                    	/*j 所指元素后移*/
                    	tempArr[(j+1)%len] = tempArr[j]; 
                    	/*j 指向上一个元素*/
                        j = (j-1+len)%len;         
                    }
                    /*移动结束,待插元素插在tempArr[j]后*/
                    tempArr[(j+1)%len] = arr[i]; 
                }
            }
            
            /*把在tempArr中排好序的元素依次赋给arr*/
            for(int i = 0; i < len; i++){                    
            	arr[i] = tempArr[(first+i)%len];
            }
    

    3.3 插入排序的稳定性、复杂度和适用场景

    3.3.1 稳定性

      在使用插入排序时,元素从无序部分移动到有序部分时,必须是不相等(大于或小于)时才会移动,相等时不处理,所以直接插入排序是稳定的。

    3.3.2 时间复杂度

      在插入排序中,当待排序序列是有序时,是最优的情况,只需当前数跟前一个数比较一下就可以了,这时一共需要比较n- 1次,时间复杂度为O(n)。
      最坏的情况是待排序数组是逆序的,此时需要比较次数最多,总次数记为:1+2+3+…+N-1,所以,插入排序最坏情况下的时间复杂度为O(n2)。
      平均来说,array[1…j-1]中的一半元素小于array[j],一半元素大于array[j]。插入排序在平均情况运行时间与最坏情况运行时间一样,是O(n2)。

    3.3.3 适用场景

      待排序序列的元素个数不多(<=50),且元素基本有序。

    四、快速排序

    4.1 快速排序基础【必会知识】

      快速排序也是一种较为基础的排序算法,其效率比冒泡排序算法有大幅提升。因为使用冒泡排序时,一趟只能选出一个最值,有n个元素最多就要执行n - 1趟比较。而使用快速排序时,一次可以将所有元素按大小分成两堆,也就是平均情况下需要logn轮就可以完成排序。
      快速排序的思想是:每趟排序时选出一个基准值,然后将所有元素与该基准值比较,并按大小分成左右两堆,然后递归执行该过程,直到所有元素都完成排序。
      快速排序的步骤如下:

    1>先从数列中取出一个数作为基准数。
    2>分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
    3>再对左右区间重复第二步,直到各区间只有一个数。

      快排的不同版本,演进过程示例:

    	public static void quickSort1(int[] arr) {
    		if (arr == null || arr.length < 2) {
    			return;
    		}
    		process1(arr, 0, arr.length - 1);
    	}
    
    	//第一版快排,这一版的时间复杂度为O(n2)
    	public static void process1(int[] arr, int L, int R) {
    		if (L >= R) {
    			return;
    		}
    		//在[L,R]范围上,根据arr[R],模仿netherlandsFlag方法,
    		//将数组分为三个部分:<=arr[R]的部分,arr[R]本身,>=
    		//arr[R]的部分,这样确定了在最终的数组中arr[R]的位置,
    		//并返回这个位置
    		int M = partition(arr, L, R);
    		//接下来只要在左右两侧重复这个过程就行
    		process1(arr, L, M - 1);
    		process1(arr, M + 1, R);
    	}
    
    	public static int partition(int[] arr, int L, int R) {
    		if (L > R) {
    			return -1;
    		}
    		if (L == R) {
    			return L;
    		}
    		int lessEqual = L - 1;
    		int index = L;
    		while (index < R) {
    			if (arr[index] <= arr[R]) {
    				swap(arr, index, ++lessEqual);
    			}
    			index++;
    		}
    		swap(arr, ++lessEqual, R);
    		return lessEqual;
    	}
    
    	
    	public static void quickSort2(int[] arr) {
    		if (arr == null || arr.length < 2) {
    			return;
    		}
    		process2(arr, 0, arr.length - 1);
    	}
    
    	//第二版快排:相比第一版的区别/优势:在于一次可以确定
    	//相等基准值的一个区域,而不再只是一个值
    	//第二版的时间复杂度为O(n2)
    	public static void process2(int[] arr, int L, int R) {
    		if (L >= R) {
    			return;
    		}
    		int[] equalArea = netherlandsFlag(arr, L, R);
    		process2(arr, L, equalArea[0] - 1);
    		process2(arr, equalArea[1] + 1, R);
    	}
    	
    	//这个方法的目的是按arr[R]为基准值,将arr数组划分为小于基准值、
    	//等于基准值、大于基准值三个区域
    	
    	//在arr[L...R]上,以arr[R]做基准值,在[L...R]范围内,<arr[R]的数
    	//都放在左侧,=arr[R]的数放在中间,>arr[R]的数放在右边
    	//返回的值为和arr[R]相等的范围的数组
    	public static int[] netherlandsFlag(int[] arr, int L, int R) {
    		if (L > R) {
    			return new int[] { -1, -1 };
    		}
    		if (L == R) {
    			return new int[] { L, R };
    		}
    		//小于基准值的区域的右边界
    		int less = L - 1;
    		//大于基准值的区域的左边界
    		int more = R;
    		int index = L;
    		while (index < more) {
    			//等于基准值,不做处理,判断下一个数据
    			if (arr[index] == arr[R]) {
    				index++;
    			//当前数小于基准值
    			} else if (arr[index] < arr[R]) {
    				//将当前值和小于区域右边的一个值交换:swap
    				//判断下一个数据:index++
    				//小于区域右移:++less(先++是为了完成swap)
    				swap(arr, index++, ++less);
    			} else {
    				//将当前值和大于区域左边的一个值交换:swap
    				//大于区域左移:--more(先--是为了完成swap)
    				swap(arr, index, --more);
    			}
    		}
    		//因为最开始是把arr[R]作为基准值的,所以在进行接下来的一步之前,
    		//arr[R]实际是在大于区域的最右侧的,所以还需要进行一步交换,这样
    		//整个数组就成了小于区域、等于区域、大于区域的样子
    		swap(arr, more, R);
    		//less + 1是等于区域的起始位置,more经过上一步的和arr[R]交换后,
    		//就成了等于区域的结束位置
    		return new int[] { less + 1, more };
    	}
    	
    
    	public static void quickSort3(int[] arr) {
    		if (arr == null || arr.length < 2) {
    			return;
    		}
    		process3(arr, 0, arr.length - 1);
    	}
    
    	//第三版快排:不再固定去arr[R],改为去随机位置的值,然后
    	//和arr[R]进行交换,接下来的过程就和第二版一样
    	
    	//第三版的复杂度变化了,是O(nlogn),该事件复杂度是最终求
    	//的是数学上的一个平均期望值
    	public static void process3(int[] arr, int L, int R) {
    		if (L >= R) {
    			return;
    		}
    		swap(arr, L + (int) (Math.random() * (R - L + 1)), R);
    		int[] equalArea = netherlandsFlag(arr, L, R);
    		process3(arr, L, equalArea[0] - 1);
    		process3(arr, equalArea[1] + 1, R);
    	}
    
    	public static void swap(int[] arr, int i, int j) {
    		int tmp = arr[i];
    		arr[i] = arr[j];
    		arr[j] = tmp;
    	}
    

      在选择基准值的时候,越靠近中间,性能越好;越靠近两边,性能越差。第三版随机选一个数进行划分的目的就是让好情况和差情况都变成概率事件。把每一种情况都列出来,会有每种情况下的时间复杂度,但概率都是1/N。那么所有情况都考虑,时间复杂度就是这种概率模型下的长期期望。
      时间复杂度O(N*logN),额外空间复杂度O(logN)都是这么来的。

    4.2 快速排序优化

    4.2.1 三数取中

      该方法指的是选取基准值时,不再取固定位置(如第一个元素、最后一个元素)的值,因为这种固定取值的方式在面对随机输入的数组时,效率是非常高的。但是一旦输入数据是有序的,使用固定位置取值,效率就会非常低。因此此时引入了三数取中,即在数组中随机选出三个元素,然后取三者的中间值做为基准值。

    4.2.2 插入排序

      当待排序序列的长度分割到一定大小(如 < 10)后,使用插入排序。

    4.2.3 相等元素聚集(上个小节中的第二版快排)

      在一次分割结束后,可以把与Key相等的元素聚在一起,继续下次分割时,不用再对与key相等元素分割。

    4.3 快速排序的稳定性、复杂度和适用场景

    4.3.1 稳定性

      在使用快速排序时,每次元素分堆都要选择基准因子。此时,基准因子两边都有可能出现和基准因子相同的元素,如序列[1,3,2,4,3,4,6,3],如果选择了array[4]作为基准因子,那么array[1]和array[7]势必会被分到基准因子的同一侧,序列的稳定性被破坏。所以,快速排序是一种不稳定的排序算法。

    4.3.2 时间复杂度

      快速排序的时间复杂度是O(nlogn)【上小节第三版的时间复杂度】。

    4.3.3 适用场景

      快速排序的适用场景是:待排序序列元素较多,并且元素较无序。

    五、希尔排序

    5.1 希尔排序基础

      希尔排序又称为缩小增量排序,是对之前介绍的插入排序的一种优化版本,优化的地方在于:不用每次插入一个元素时,就和序列中有序部分中的所有元素进行比较。
      该方法的基本思想是:设待排序元素序列有n个元素,首先取一个整数increment(小于序列元素总数)作为间隔,所有距离为increment的元素放在同一个逻辑数组中,在每一个逻辑数组中分别实行直接插入排序。然后缩小间隔increment,重复上述逻辑数组划分和排序工作。直到最后取increment=1,将所有元素放在同一个数组中排序为止。
      其实从上面的希尔排序的思想中也能看出希尔排序的实现步骤:
       1>选increment,划分逻辑分组,组内进行直接插入排序。
       2>不断缩小increment,继续组内进行插入排序。
       3>直到increment=1,在包含所有元素的序列内进行直接插入排序。

    5.1.1 排序过程图示

      1>假如有[5,2,3,9,4,7]六个元素,第一趟取increment的方法是:6/3向下取整+1=3。将整个数据列划分为间隔为3的3个逻辑分组,然后对每一个逻辑分组执行直接插入排序,相当于对整个数组执行了部分排序调整。

      2>第二趟将间隔increment= increment/3向下取整+1=2,将整个数组划分为2个间隔为2的逻辑分组,分别进行排序。

      3>第3趟继续缩小间隔。间隔缩小为increment= increment/3向下取整+1=1,当增量为1的时候,实际上就是把整个数列作为一个逻辑分组进行插入排序。

    5.1.2 排序过程实现

      上述图示对应的代码实现,示例如下:

    		/*初始化划分增量*/
    		int increment = len;	
    		int temp;
    		/*每次减小增量,直到increment = 1*/
    		while (increment > 1){	
    			/*增量的取法之一:除三向下取整+1*/
    			increment = increment/3 + 1;
    			/*对每个按增量划分后的逻辑分组,进行直接插入排序*/
    			for (int i = increment; i < len; ++i) {	
    				if (arr[i-increment] > arr[i]) {
    					temp = arr[i];
    					int j = i-increment;
    					/*移动元素并寻找位置*/
    					while (j >= 0 && arr[j] > temp) {	
    						arr[j+increment] = arr[j];
    						j -= increment;
    					} 
    					/*插入元素*/
    					arr[j+increment] = temp;	
    				}
    			}
    		} 
    

      从上述代码可以看出,希尔排序的代码与直接插入排序的代码十分相似。因为希尔排序本就是直接插入排序的优化版本,不同的地方就是间隔慢慢减成1,直接插入排序的间隔一直就是1。

    5.2 希尔排序优化

      由于希尔排序是基于插入排序的,所以在插入排序中也可运用直接插入排序中的优化方式,此处以二分折中的方式来优化希尔排序,示例代码如下:

    	   /*初始化划分增量*/
    	   int increment = len;	
    	   int j,temp,low,mid,high;
    	   /*每次减小增量,直到increment = 1*/
    	   while (increment > 1){	
    		  /*增量的取法之一:除三向下取整+1*/
    		  increment = increment/3 + 1;
    		  /*对每个按增量划分后的逻辑分组,进行直接插入排序*/
    		  for (int i = increment; i < len; ++i) {	
    			 low = 0;
    			 high = i-1;
    			 temp = arr[i];
    	         while(low <= high){
    	            mid = (low+high)/2;
    	            if(arr[mid]>temp){
    	                high = mid-1;
    	            }else{
    	                low = mid+1;
    	            }
    	         }
    	         j = i-increment;
    		     /*移动元素并寻找位置*/
    			 while(j >= high+1){	
    				arr[j+increment] = arr[j];
    				j -= increment;
    			 } 
    			 /*插入元素*/
    			 arr[j+increment] = temp;	
    		  }
    	   }
    

    5.3 希尔排序的稳定性、复杂度及适用场景

    5.3.1 稳定性

      希尔排序是直接插入排序的优化版,在排序过程中,会根据间隔将一个序列划分为不同的逻辑分组,在不同的逻辑分组中,有可能将相同元素的相对位置改变。如[2,2,4,1],按间隔为2,降序排序,前两个元素的相对位置就会改变。因此,希尔排序是不稳定的排序方式。

    5.3.2 时间复杂度

      希尔排序在最坏情况下的时间复杂度为O(n2),平均情况下的时间复杂度为O(n1.3)。

    5.3.3 适用场景

      待排序序列元素较少时。

    展开全文
  • 求取圆形区域内的平均灰度值

    千次阅读 2015-05-18 16:23:27
    求取圆形区域内的平均灰度值
    #include <cmath>
    #include <opencv2/opencv.hpp>
    using namespace cv;
    using namespace std;
    
    const int kvalue = 15;//双边滤波邻域大小
    const double PI = 3.14;//圆周率
    
    int graylevel(Mat image, Mat dst, Point cen, int r)//求取圆形区域内的平均灰度值
    {
    	int graysum = 0, n = 0;
    
    	for(int i = (cen.y - r); i <= (cen.y + r); ++i)//访问矩形框内的像素值
    	{
    		uchar* data = image.ptr<uchar>(i);
    		for(int j = (cen.x - r); j <= (cen.x + r); ++j)
    		{
    			double d = (i-cen.y)*(i-cen.y) + (j-cen.x)*(j-cen.x);
    			if(d < r*r)
    			{
    				++n;
    				graysum += (int)data[j];
    			}
    		}
    	}
    
    	for(int i = (cen.y - r); i <= (cen.y + r); ++i)//画出圆,圆内像素值为平均灰度值
    	{
    		uchar* temp = dst.ptr<uchar>(i);
    		for(int j = (cen.x - r); j <= (cen.x + r); ++j)
    		{
    			double d = (i-cen.y)*(i-cen.y) + (j-cen.x)*(j-cen.x);
    			if(d < r*r)
    			{
    				temp[j] = (int)(graysum / n);
    			}
    		}
    	}
    
    	return(graysum / n);
    }
    
    int main()
    {
    	Mat src_color = imread("1.png");//读取原彩色图
    	imshow("原图-彩色", src_color);
    
    	Mat src_gray;//彩色图像转化成灰度图
    	cvtColor(src_color, src_gray, COLOR_BGR2GRAY);
    	imshow("原图-灰度", src_gray);
    	//imwrite("src_gray.png", src_gray);
    
    	//声明一个单通道图像,像素值全为0,用来将霍夫变换检测出的圆画在上面
    	Mat dst(src_gray.size(), src_gray.type());
    	dst = Scalar::all(0);
    
    	Mat bf;//对灰度图像进行双边滤波
    	bilateralFilter(src_gray, bf, kvalue, kvalue*2, kvalue/2);
    	//imshow("灰度双边滤波处理", bf);
    	//imwrite("src_bf.png", bf);
    
    	vector<Vec3f> circles;//声明一个向量,保存检测出的圆的圆心坐标和半径
    	HoughCircles(bf, circles, CV_HOUGH_GRADIENT, 1.5, 20, 130, 38, 10, 50);//霍夫变换检测圆
    
    	std::vector<int> v;//保存圆心的横坐标减纵坐标的绝对值,用于区分两排灯
    	cout << "x=\ty=\tr=\ts=\tg=" << endl;
    
    	for(size_t i = 0; i < circles.size(); i++)//把霍夫变换检测出的圆画出来
    	{
    		Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
    		int radius = cvRound(circles[i][2]);
    
    		double s = 0;//计算圆的面积
    		s = PI * radius * radius;
    
    		int average = 0;
    		average = graylevel(bf, dst, center, radius);//计算平均灰度,并画出圆
    
    		circle( dst, center, 2, Scalar(255), -1, 8, 0 );//画出圆心
    		circle( dst, center, radius, Scalar(255), 1, 8, 0 );//画出圆的轮廓
    
    		v.push_back(abs(center.x-center.y));//存储圆心的横坐标减纵坐标的绝对值,用于区分两排灯
    
    		cout << center.x << "\t" << center.y << "\t" << radius << "\t" << s << "\t" << average << endl;//在控制台输出圆心坐标和半径	
    	}
    
    	sort(v.begin(), v.end());//从小到大排序
    
    	std::vector<Point> points1, points2;//声明点向量,分别存储两排灯的圆心坐标
    
    	for (size_t i = 0; i < circles.size(); i++)//用来区分两排灯
    	{
    		Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
    		if (abs(center.x-center.y) < v[12])
    			points1.push_back(Point(center.x, center.y));//存储从左上到右下那排灯的圆心坐标
    		else
    			points2.push_back(Point(center.x, center.y));//存储从左下到右上那排灯的圆心坐标
    	}
    
    	cv::Vec4f line1, line2;//拟合直线
    	fitLine(Mat(points1), line1, CV_DIST_L2, 0, 0.01, 0.01);
    	fitLine(Mat(points2), line2, CV_DIST_L2, 0, 0.01, 0.01);
    
    	int x01 = (int)line1[2];
    	int y01 = (int)line1[3];
    	int x11 = (int)(x01 + 300*line1[0]);
    	int y11 = (int)(y01 + 300*line1[1]);
    	int x21 = (int)(x01 - 300*line1[0]);
    	int y21 = (int)(y01 - 300*line1[1]);	
    
    	int x02 = (int)line2[2];
    	int y02 = (int)line2[3];
    	int x12 = (int)(x02 + 300*line2[0]);
    	int y12 = (int)(y02 + 300*line2[1]);
    	int x22 = (int)(x02 - 300*line2[0]);
    	int y22 = (int)(y02 - 300*line2[1]);	
    
    	cv::line(dst, Point(x11, y11), Point(x21, y21), Scalar(255), 1);//画出直线
    	cv::line(dst, Point(x12, y12), Point(x22, y22), Scalar(255), 1);
    
    	imshow("特征提取", dst);
    	imwrite("chuli.png", dst);
    
    	waitKey();
    }


    展开全文
  • 交换排序之快速排序

    2016-03-28 13:12:18
    其基本思想是基于分治法的:排序表L[1…n]中任取一个元素pivot作为基准,通过一趟排序将待排序表划分为独立的两部分L[1…k-1]和L[k+1…n],使得L[1…k-1]中所有元素小于pivot,L[k+1…n]中所有元素大于或等于...

    快速排序是对冒泡排序的一种改进。其基本思想是基于分治法的:在待排序表L[1…n]中任取一个元素pivot作为基准,通过一趟排序将待排序表划分为独立的两部分L[1…k-1]和L[k+1…n],使得L[1…k-1]中所有元素小于pivot,L[k+1…n]中所有元素大于或等于pivot,则pivot放在了其最终位置L[k]上,这个过程称作一趟快速排序。而后分别递归地对两个子表重复上述过程,直至每部分内只有一个元素或空为止,即所有元素放在了其最终位置上。

    public class QuickSort {
    
        public static void main(String[] args) {
            int[] array = { 49, 85, 111, 38, 65, 97, 76, 13, 27 };
            quickSort(array, 0, array.length - 1);
        }
    
        /**
         * 先按照数组为数据原型写出算法,再写出扩展性算法。数组{49,38,65,97,76,13,27}
         * 
         * @param array
         * @param left
         * @param right
         */
        public static void quickSort(int[] array, int left, int right) {
            int pivot;
            if (left < right) {
                pivot = partition(array, left, right);
                // 对左右数组递归调用快速排序,直到顺序完全正确
                quickSort(array, left, pivot - 1);
                quickSort(array, pivot + 1, right);
            }
        }
    
        /**
         * pivotValue作为枢轴,较之小的元素排序后在其左,较之大的元素排序后在其右
         * 
         * @param array
         * @param left
         * @param right
         * @return
         */
        public static int partition(int[] array, int left, int right) {
            int pivot = array[left];
            // 枢轴选定后永远不变,最终在中间,前小后大
            while (left < right) {
                while (left < right && array[right] >= pivot) {
                    --right;
                }
                // 将比枢轴小的元素移到低端,此时right位相当于空,等待低位比pivot大的数补上
                array[left] = array[right];
                while (left < right && array[left] <= pivot) {
                    ++left;
                }
                // 将比枢轴大的元素移到高端,此时left位相当于空,等待高位比pivot小的数补上
                array[right] = array[left];
            }
            // 当left == right,完成一趟快速排序,此时left位相当于空,等待pivotkey补上
            array[left] = pivot;
    
            return left;
        }
    }

    快速排序算法的性能分析:
    1)空间效率:由于快速排序是递归的,需要借助递归工作栈来保存每一层递归调用的必要信息,其容量与递归调用的最大深度一致。最好情况下为⌈Log2(n+1)⌉;最坏的情况下,因为要进行n-1次递归调用,所以栈的深度为O(n);平均情况下,栈的深度为O(log2n)。因而空间复杂度最坏的情况下为O(n),平均情况下为O(log2n)。
    2)时间效率:快速排序的最坏情况发生在两个区域分别包含n-1个元素和0个元素时,这种最大程度的不对称性若发生在每一层递归上,即对应于初始排序表基本有序或基本逆序,此时时间复杂度为O(n²)。在最好的情况下,也即partition()可能做到最平衡的划分中,得到的两个字序列的大小都不可能大于n/2,在这种情况下,时间复杂度为O(nLog2n)。
    3)稳定性:在划分算法中,若右端区间存在两个关键字相同,且均小于基准值的记录,则在交换到左端区间后,它们的相对位置会发生变化,即快速排序是一个不稳定的排序方法。例如,表L={3,2,2},pivot为3,经过一趟排序后,L{2,2,3},最终排序也是L{2,2,3},但是2与2的相对次序已经发生了变化。

    展开全文
  • 问题描述:Windows无法连接到选定网络,网络可能不在区域中。请刷新可用网络的列表,重新尝试。 解决方法:路由器设置了密码。改一下设置密码的方式,路由有三四种加密方式。如果还不行,这个问题的原因可能是无线...
  • 排序算法

    2014-03-09 16:50:23
    排序算法已经是老话新谈了的话题了,但网上很少找到比较系统的总结。有的只给出代码,有的分析的很笼统等。如果大学学的是计算机专业,那么这些东西都是必须要学的。   排序是我们工作中经常碰到的一件事,基本...
  • 排序算法整理

    2019-08-19 23:01:34
    以下我所举例所有的排序思想都是递增式排序 稳定性排序:冒泡、插入、归并 不稳定排序:选择排序、堆排序、希尔排序、快速排序 时间复杂度为O(n*n):冒泡、插入、选择 时间复杂度为O(nlogn):快速排序、堆排序、归并...
  • 排序和顺序统计量

    千次阅读 2016-06-12 23:08:58
    很多计算机科学家认为排序是算法研究中最基础的问题,不仅如此,有的学者指出对待解决问题先进行排序,可能有利于的问题的分析以及求解思路的产生。排序算法 1 插入排序 2 归并排序 3 堆排序 31 堆 311 维护堆的性质...
  • 【数据结构】各种排序算法&各种排序算法的比较

    千次阅读 多人点赞 2019-05-25 21:29:32
    冒泡排序(Bubble Sort): 对于一串数字,如3 2 5 9 6 4 1 从3的位置开始往后进行 如果被比较数比3小,那么那个数就“浮上去”,即与3进行交换,此时变成 2 3 5 9 6 4 1 再从第二个位置开始,即3和5比,顺序正常 第...
  • 数据结构与算法分析笔记与总结(java实现)--排序5:快速排序练习题
  • 数据量很大的排序问题 大量数据如何排序  【尊重原创,转载请注明出处】http://blog.csdn.net/guyuealian/article/details/51151674  同学某天参加腾讯面试,技术面的时候,面试官问了排序问题:  问题一:...
  •  Excel表格是每个公司人员工作当中都会使用到处理数据的必备办公软件之一,有时候我们制作表格的时候需要针对数据进行数据排列,那么Excel表格中要如何对一列一列的数据进行排序呢?我们现在就来看看Excel...
  • 我们通常所说的排序算法往往指的是内部排序算法,即数据记录内存中进行排序。 排序算法大体可分为两种: 一种是比较排序,主要有:冒泡排序,选择排序,插入排序,归并排序,堆排序,快速排序等。 另一种是非...
  • 空间排序

    千次阅读 2005-04-19 08:59:00
    空间排序(SPATIAL SORTING) 第四章讨论了渲染一个层次化结构的场景,场景中的物体绘制的顺序是由深度优先遍历所决定的,几乎所有的情况下,渲染的场景都以这种方式不正确的绘制着。例如,如果沿眼睛视线的两个不...
  • Matlab学习笔记(6)——sort和sortrows对矩阵排序

    万次阅读 多人点赞 2017-09-20 08:50:13
    sort和sortrows对矩阵排序sort函数排序在处理问题时,排序是一个非常常见的需求。sort函数是Matlab内置的排序函数,可以满足常用的排序需求。sort函数的基本形式如下[Y,I] = sort(X,DIM,MODE) Y表示对X排序后的结果 ...
  • 最近复习常用排序算法发现了下面这个罪恶的排序方法列表页面,我被那些有趣的排序方法诱惑了,就把上面介绍的各种排序方法都整理了一遍(我觉得维基百科比其它我看过的算法书都要易懂一些),前半部分可以说还乐...
  • 区间模糊排序

    千次阅读 2009-05-23 17:18:00
    对于其中的每个数字,我们只知道它落实轴上的某个区间。亦即,给定的是n个形如[a(i), b(i)]的闭区间(这里小括后起下标的作用,后同),其中a(i) ,使得存在一个c(j)属于区间[a(i(j)), b(i(j))],满足c(1) a) 为...
  • Excel按数字大小排序

    千次阅读 2019-05-14 10:20:11
    发现excel排序是按照数字一位一位比较排序的 于是就出现以下截图的排序 我们的目标是按照数字大小排序的 解决方案: 增加辅助列 1. 截取标题中的数字 =RIGHT(A1,LEN(A1)-FIND(" ",A1)) 公式的意思是截取A1栏...
  • (即多字段排序,以先写的字段先进行排序,将相同的值为一组,以第二字段来排序,只有第一字段存在数值相同时第二字段的排序才有意义) ORDER BYA,B desc指A用升序,B用降序 ORDER BY A asc,B desc指A用升序,B用...
  • 心路历程: 排序算法可以算是任何编程语言数据结构和底层源码算法的基础。之前无数次接触过,始终没有整理归纳过,最近整理分享如下。希望大家浏览的过程中,都能有所收获;此外某些见识方面有所欠缺的地方,烦...
  • 【VBA研究】排序编程代码

    千次阅读 2015-10-29 15:11:04
    1、对Excel处理时经常会对工作表中的数据排序排序代码怎么写?通过录制宏可以很容易得到(我学习VBA的方法基本就是查资料、录制宏),例如2003版可以得到如下排序语句: Rows("1:1500").Select Selection.Sort ...
  • Sub 找出选定范围不重复的值() On Error Resume Next Dim d As Object Set d = CreateObject("scripting.dictionary") For c_i = 1 To selection.Columns.Count For Each ce In selection.Column
  • 做WPS表格的时候经常需要排序,不管是年终评比还是其他的,前几名的总是有好处的,那么WPS表格怎么排序呢?常规的排序很容易实现,但有时我们需要按特定的顺序对数据进行排序,例如:按照姓氏笔画对人员名单进行...
  • 算法导论第八章:线性时间排序

    千次阅读 2010-10-12 22:50:00
    前面介绍的算法都有一个共同的性质:排序结果中,各元素的次序基于输入时间的比较,我们把这类排序算法称为比较排序。 8.1比较排序算法的时间下界决策树模型比较排序的过程可以被抽象地视为决策树。一棵决策树是一...
  • 全球性的搜索引擎 Google,看似简单的搜索框背后隐藏的是极其复杂的系统架构和搜索算法,其中排序(以下统称 Ranking)的架构和算法更是关键部分。Google 正是通过 PageRank 算法深刻改变搜索排序而一举击败众多竞争...
  • 2、对透视表数据排序: 3、更改透视表数据源: 4、数据透视表的无效行标签如何清除(是否保留从数据源部分中删除的项目) 5、改变透视表汇总行的位置(上或下): 6、透视表跨工作簿引用数据时提示:“不能打开...
  • Excel 按性别(男女)排序用countif语句。=COUNTIF(B:B,"男")=COUNTIF(B:B,"女")B:B是你花名册中性别的那一列,我是假设B列的。Excel成绩表中的数据进行分类汇总,按性别分别求...1、打开需要操作的excel表格,做...
  • 决定放假期间先不上iOS Wow体验了;手头这篇译文不做完的话我心不甘。...今次这篇则是来自于本书的第四章——搜索、排序和筛选。貌似国内引进版也由XX出版社做着了,真心不关我事,自己走起。接下来
  • Excel2013向被粘贴区域的非空单元格粘贴数据 【问题如下】有以下两张表:学生表 和 成绩表。需要将成绩这一列的数据,全部粘贴到学生表的学号列中去,并且与学号对应,学号空白的单元格直接跳过。学生表中,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,602
精华内容 5,040
关键字:

如何在选定区域内排序