数据结构算法基础-内部排序算法

 1 arr = [1,23,12,9,8,8,9,1,1,8,]
 2 def quickSortCore(arr,start,end):
 3     if start < end:
 4         index = partition(arr,start,end)
 5         quickSortCore(arr,start,index-1)
 6         quickSortCore(arr,index+1,end)
 7
 8 def partition(arr,start,end):
 9     key = arr[start]
10     while(start < end):
11         while(start < end  and key <= arr[end]):
12             end -= 1
13         if(start < end):
14             arr[start],arr[end] = arr[end],arr[start]
15         while(start < end and key >= arr[start]):
16             start += 1
17         if(start<end):
18             arr[start],arr[end] = arr[end],arr[start]
19     return start
20 quickSortCore(arr,0,len(arr)-1)
21 print(arr)

 1 package com.sort;
 2
 3 public class QuickSortDemo {
 4     public static void main(String[] args) {
 5         int []arr = {8,9,8,8,9,1,1};
 6         QuickSortDemo q = new QuickSortDemo();
 7         q.quickSortCore(arr,0,arr.length-1);
 8         for(int a : arr){
 9             System.out.print(a+" ");
10         }
11     }
12     private void quickSortCore(int[] arr, int start, int end) {
13        if(start<end){
14            int sepIndex = partition(arr,start,end);
15 //           System.out.println(sepIndex);
16            quickSortCore(arr, start, sepIndex-1);
17            quickSortCore(arr, sepIndex+1, end);
18        }
19
20     }
21     //分开
22     private int partition(int[] arr, int start, int end) {
23        int key = arr[start];
24        int tmp = 0;
25        while(start < end){
26            while((start < end) &&(key<= arr[end]) ){
27                end --;
28            }
29            // 交换时,一定是 start 与 end 相交换
30            if(start<end){
31                tmp = arr[end];
32                arr[end] = arr[start];
33                arr[start] = tmp;
34                start++;
35            }
36            while((start< end) &&(key>= arr[start])){
37                start++;
38            }
39            if(start<end){
40                tmp = arr[start];
41                arr[start] = arr[end];
42                arr[end] = tmp;
43                end--;
44            }
45        }// start == end
46 //       arr[start] = key;// 可不加
47         return start;
48     }
49
50 }

注意:1) 交换时是 start 与 end 相交换,与 key是无关的。以上的代码应是最慢的quickSort; 2) 快排是不稳定的排序方法,空间复杂度为O(logN)

2、归并排序(稳定的排序方法,空间复杂度为O(n))

 1 package com.sort;
 2
 3 import java.util.Arrays;
 4
 5 public class MergSortDemo {
 6     public static void main(String[] args) {
 7         int[] arr = { 8, 9, 8, 8, 9, 1, 1 };
 8         MergSortDemo m = new MergSortDemo();
 9         m.mergeSort(arr);
10         System.out.println(Arrays.toString(arr));
11     }
12
13     public void mergeSort(int[] arr) {
14         int[] tmp = new int[arr.length];
15         mergeSortCore(arr, 0, arr.length - 1, tmp);
16     }
17
18     public void mergeSortCore(int[] arr, int start, int end, int[] tmp) {
19
20         if (start < end) {
21             int mid = (end - start) / 2 + start;
22             mergeSortCore(arr, start, mid, tmp);
23             mergeSortCore(arr, mid+1, end, tmp);
24             merge(arr, start, mid , end);
25         }
26     }
27
28     // / arr[start...mid] 与 arr[mid+1,... end] ; 两个有序的子数组进行归并
29     private void merge(int[] arr, int start, int mid, int end) {
30         int s = start;
31         int m = mid + 1;
32 //        int e = end;
33         int[] tmp = new int[end - start + 1];
34         int index = 0;
35         // 处理共同的
36         while (s <= mid && m <= end) {
37             while (s <= mid && arr[s] <= arr[m]) {
38                 tmp[index++] = arr[s++];
39             }
40             while (m <= end && arr[s]> arr[m]) {
41                 tmp[index++] = arr[m++];
42             }
43         }
44         // 处理剩下的
45         while (s <= mid) {
46             tmp[index++] = arr[s++];
47         }
48         while (m <= end) {
49             tmp[index++] = arr[m++];
50         }
51         for (int i = start, j = 0; i <= end; i++) {
52             arr[i] = tmp[j++];
53         }
54     }
55
56 }

 1 def mergeSort(arr,start,end):
 2     if start > end:
 3         return
 4     if(start < end):
 5         mid = (end - start)//2 + start
 6         mergeSort(arr,start,mid)
 7         mergeSort(arr,mid+1,end)
 8         merge(arr,start,mid,end)
 9
10 def merge(arr,start,mid,end):
11      # i =start,j = mid+1  ## python 中千万不要这样赋值!!
12      i = start
13      j = mid + 1
14      # print(str(start) + ‘..‘+ str(end))
15      tmp = []
16      while(i<=mid and j<=end):
17          if(arr[i] <= arr[j]):
18              tmp.append(arr[i])
19              i = i+1
20          else:
21              tmp.append(arr[j])
22              j = j + 1
23      if(i<= mid):
24          tmp.extend(arr[i:mid+1])
25      if(j <= end):
26         tmp.extend(arr[j:end+1])
27      arr[start:end+1] = tmp
28      del tmp
29      return arr
30 mergeSort(arr,0,len(arr)-1)
31 # merge(arr,0, (len(arr)-1)//2, len(arr)-1)
32 print(arr)

3、堆排序(不是稳定的排序方法)(下期)

扩展:

1)求数组中第K小的数

思想:利用快排的思想,随机选择元素 t , 它将数组分成两部分,小于 t 的 和大于 t 的; 分别计为 a[0...m-1] ; a[m+1,...n-1]

若  m = k -1 ;则返回 t ;

若 m> k-1 ,说明 第k小的值在a[0...m-1];则求a[0...m-1]中第K小的值;

若 m< k-1 ,说明 第k小的值在a[m+1,...n-1],则在a[m+1,...n-1] 求 k-m小的数。 //  在代码中应是与 下标相比较,所以左右都是K,都是K

平均时间复杂度O(N)

 1 def getKthSmall(arr,start,end,k):
 2     s = start
 3     e = end
 4     key = arr[s]
 5     while(s <  e):
 6         while(s < e and key <= arr[e]):
 7             e -= 1
 8         if key > arr[e]:
 9             arr[s] ,arr[e] = arr[e], arr[s]
10         while(s < e and key > arr[s]):
11             s += 1
12         if key < arr[s]:
13             arr[s], arr[e] = arr[e], arr[s]
14     print(‘start = %d;  end = %d  s = %d‘ % (start, end,s))
15     if s == k-1:
16         return s
17     elif s > k-1:
18         return getKthSmall(arr,start,s-1,k)
19     else:
20         ## getKthSmall(arr,s+1,end, k-s-1), 不是这个,不是这个,不是这个,
21         ## 因为 我们是与下标比较,所以都是K,
22         return getKthSmall(arr,s+1,end,k)
23
24 arr = [33,3,4,6,32]
25 index = getKthSmall(arr,0,len(arr)-1,3)
26 print(arr[index])

2) 求数组中的逆序数问题

给定一个数组A[0,...N-1] ,若对于两个元素a[i],a[j] ,若 i<j  且 a[i] >a[j] ,则称(a[i],a[j])为逆序对。

如数组 2,56,2,7的逆序数为 3. 归并排序图解如下,在合并时,都可用来计算其逆序对的数。

 1 package com.sort;
 2
 3 public class 逆序对数 {
 4     static Integer count = 0;
 5     public static void main(String[] args) {
 6         int[] arr = { 3, 56, 2, 7 };
 7         mergeSort(arr, 0, arr.length - 1);
 8         System.out.println(count);
 9     }
10
11     private static void mergeSort(int[] arr, int start, int end) {
12         if (start < end) {
13             int mid = (end - start) / 2 + start;
14             mergeSort(arr, start, mid);
15             mergeSort(arr, mid + 1, end);
16             merge(arr, start, mid, end);
17         }
18     }
19
20     private static void merge(int[] arr, int start, int mid, int end) {
21 //        System.out.println(".......2............");
22         int i = start, j = mid + 1;
23         int k = 0;
24         int[] tmp = new int[end - start + 1];
25         while (i <= mid && j <= end) {
26             if (i <= mid && arr[i] < arr[j]) {  // if (i <= mid && arr[i] <= arr[j])
27                 tmp[k++] = arr[i++];
28             }else{                                 // if (j <= end && arr[i] > arr[j])
29                 count += (mid - i + 1);           // 主要在这一块地方求!!,别注意条件,前没有=,
30                                                  //这也很好理解,有等于号,也是有逆序数对的。
31                 tmp[k++] = arr[j++];
32
33             }
34         }
35         while (i <= mid) {
36             tmp[k++] = arr[i++];
37         }
38         while (j <= end) {
39             tmp[k++] = arr[j++];
40         }
41         k = 0;
42         for (int t = start; t <= end; t++) {
43             arr[t] = arr[k++];
44         }
45 //        System.out.println("..================............");
46     }
47
48 }

即,如下图所示,在求 逆序对时,两个有序合并时, count  += (mid- i + 1);另要注意  arr[i]  等于 arr[j]  时,也是有逆序对的。注意 判断的条件!!

附其它O(n**2)的排序算法

直接插入排序(稳定的排序方法):

 1 def straightInsertSort(arr):
 2     for i in range(1,len(arr)): ## [1,....len(arr)-1 ]个元素
 3         tmp = arr[i]
 4         j = i -1
 5         while j>=0 : ## 与 [i-1,....0]号元素相比较
 6             if(arr[j]> tmp):
 7                 arr[j+1] = arr[j]
 8                 j = j-1
 9             else:
10                 break
11         ## 跳出时 j==0 或 arr[j] <= tmp
12         arr[j+1] = tmp

下期:堆排序,桶排序的运用

参考:

原文地址:https://www.cnblogs.com/vincentbnu/p/9452268.html

时间: 2024-11-05 18:45:38

数据结构算法基础-内部排序算法的相关文章

数据结构6种内部排序算法的比较

1.需求分析 (1)输入数据的形式为:伪随机数产生程序产生,且每次输入数不少于100个,至少要用5组不同的输入数据 (2)输出的形式为:输出关键字参加的比较次数和关键字的移动次数(关键字交换计为3次移动)的数据 (3)程序能达到的功能:对起泡排序,直接插入排序,简单选择排序,快速排序,希尔排序,堆排序这6种常用的内部排序算法进行比较,比较的指标为有关键字参加的比较次数和关键字的移动次数(关键字交换计为3次移动) (4)测试数据:正确输入为由伪随机数产生程序产生100个随机数,然后输出比较结果,错

数据结构复习之内部排序算法总结

1.三种选择排序(简单选择排序,树形选择排序,堆排序) #include<iostream> #include<cstring> #include<string> #include<queue> #include<map> #include<cstdlib> #include<cstdio> const int INF=0X3f3f3f3f; using namespace std; typedef struct { in

七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)

 写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列.因此排序掌握各种排序算法非常重要.对下面介绍的各个排序,我们假定所有排序的关键字都是整数.对传入函数的参数默认是已经检查好了的.只是简单的描述各个算法并给出了具体实现代码,并未做其他深究探讨. 基础知识: 由于待排序的记录数量不同,使得排序过程中设计的存储器不同,可将排序方法分为两大类:一类是内部排序,指的是待排序记录存放在计算机随机存储器中进行的排序过程.另一类是外部排序,

内部排序算法(一):交换排序(冒泡排序,快速排序)

这是我的博文系列<内部排序算法>的第一篇.所谓排序,就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来.所谓内部排序,是指在排序过程中,若整个文件都是放在内存中处理,排序时不涉及数据的内.外存交换(外排序的定义则相反). 内部排序法按照策略可以划分为五类:插入排序.选择排序.交换排序.归并排序和分配排序.待排文件的存储方式采用顺序表(或直接用向量)作为存储结构(其他的存储结构还有以链表作为存储结构等). 在这个系列的博文中,我按照排序算法的给出,排序算法的分析(包括算法的时空复杂度

算法基础之排序(2)--选择排序 改进

1 /********************************************************************************************************** 2 * Function : test 3 * Create Date : 2014/03/23 4 * Author : NTSK13 5 * Email : [email protected] 6 * Copyright : 欢迎大家和我一起交流学习,转载请保持源文件的完整性

算法基础之排序(1)--冒泡排序 改进

1 /********************************************************************************************************** 2 * Function : test 3 * Create Date : 2014/03/23 4 * Author : NTSK13 5 * Email : [email protected] 6 * Copyright : 欢迎大家和我一起交流学习,转载请保持源文件的完整性

八大内部排序算法(上)-冒泡、直接插入、简单选择、快速

八大内部排序算法(上)冒泡.直接插入.简单选择.快速 排序分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. 1.直接插入排序 将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表.即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止. 要点:设立哨兵,作为临时存储和判断数组边界之用. 直接插入实现如下:

Java实现各种内部排序算法

数据结构中常见的内部排序算法: 插入排序:直接插入排序.折半插入排序.希尔排序 交换排序:冒泡排序.快速排序 选择排序:简单选择排序.堆排序 归并排序.基数排序.计数排序 直接插入排序: 思想:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中,直到全部记录插入完成. 性能:时间复杂度:最好o(n):有序,最坏o(n^2):逆序,平均o(n^2):空间复杂度o(1):稳定 1 public int[] straightInsertSort(int array[]){ 2 int

内部排序算法小结

内部排序算法主要分为插入类排序.交换类排序和选择类排序,它们在性能上的差异主要体现在时间复杂度.空间复杂度和稳定性.各种排序算法都会进行元素间的比较和移动,时间复杂度主要由整个排序过程中的比较次数和移动次数决定.空间复杂度体现在除了待排序记录本身所占的空间,排序过程中占用了多少辅助空间. 1.插入类排序 直接插入排序 如果待排序记录之间是顺序排列,此时整个排序过程中元素比较的次数为n-1次,移动次数为0次.如果待排序记录之间是逆序排列,第i趟排序比较次数为i,移动的次数为i+1,其中i的范围是2