首页 各种排序算法及其java程序实现.

各种排序算法及其java程序实现.

举报
开通vip

各种排序算法及其java程序实现.各种排序算法及其java程序实现. 各种排序算法及其java程序实现 2011-11-26 13:12:53 我来说两句 收藏 我要投稿 各种排序算法:冒择路(入)兮(稀)快归堆,桶式排序,基数排序 冒泡排序,选择排序,插入排序,稀尔排序,快速排序,归并排序,堆排序,桶式排序,基数排序 一、冒泡排序(BubbleSort) 1. 基本思想: 两两比较待排序数据元素的大小,发现两个数据元素的次序相反时即进行交换,直到没有反序的数据元素为止。 2. 排序过程: 设想被排序的数组R,1..N,垂直竖立...

各种排序算法及其java程序实现.
各种排序算法及其java程序实现. 各种排序算法及其java程序实现 2011-11-26 13:12:53 我来说两句 收藏 我要投稿 各种排序算法:冒择路(入)兮(稀)快归堆,桶式排序,基数排序 冒泡排序,选择排序,插入排序,稀尔排序,快速排序,归并排序,堆排序,桶式排序,基数排序 一、冒泡排序(BubbleSort) 1. 基本思想: 两两比较待排序数据元素的大小,发现两个数据元素的次序相反时即进行交换,直到没有反序的数据元素为止。 2. 排序过程: 设想被排序的数组R,1..N,垂直竖立,将每个数据元素看作有重量的气泡,根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R,凡扫描到违反本原则的轻气泡,就使其向上"漂浮",如此反复进行,直至最后任何两个气泡都是轻者在上,重者在下为止。 【示例】: 49 13 13 13 13 13 13 13 38 49 27 27 27 27 27 27 65 38 49 38 38 38 38 38 97 65 38 49 49 49 49 49 76 97 65 49 49 49 49 49 13 76 97 65 65 65 65 65 27 27 76 97 76 76 76 76 49 49 49 76 97 97 97 97 java代码实现: /** 02.* 冒泡排序:执行完一次内for循环后,最小的一个数放到了数组的最前面(跟那一个排序算法* 不一样)。相邻位置之间交换 03.*/ 04. 05.public class BubbleSort { 06. 07. /** 08. * 排序算法的实现,对数组中指定的元素进行排序 09. * @param array 待排序的数组 10. * @param from 从哪里开始排序 11. * @param end 排到哪里 12. * @param c 比较器 13. */ 14. public void bubble(Integer[] array, int from, int end) { 15. //需array.length - 1轮比较 16. for (int k = 1; k < end - from + 1; k++) { 17. //每轮循环中从最后一个元素开始向前起泡,直到i=k止,即i等于轮次止 18. for (int i = end - from; i >= k; i--) { 19. //按照一种规则(后面元素不能小于前面元素)排序 20. if ((array[i].compareTo(array[i - 1])) < 0) { 21. //如果后面元素小于了(当然是大于还是小于要看比较器实现了)前面的元素, 则前后交换 22. swap(array, i, i - 1); 23. } 24. } 25. } 26. } 27. 28. /** 29. * 交换数组中的两个元素的位置 30. * @param array 待交换的数组 31. * @param i 第一个元素 32. * @param j 第二个元素 33. */ 34. public void swap(Integer[] array, int i, int j) { 35. if (i != j) {//只有不是同一位置时才需交换 36. Integer tmp = array[i]; 37. array[i] = array[j]; 38. array[j] = tmp; 39. } 40. } 41. 42. 43. /** 44. * 测试 45. * @param args 46. */ 47. public static void main(String[] args) { 48. Integer[] intgArr = { 7, 2, 4, 3, 12, 1, 9, 6, 8, 5, 11, 10 }; 49. BubbleSort bubblesort = new BubbleSort(); 50. bubblesort.bubble(intgArr,0,intgArr.length-1); 51. for(Integer intObj:intgArr){ 52. System.out.print(intObj + " "); 53. } 54. } 55.} 另外一种实现方式: /** 冒泡排序:执行完一次内for循环后,最大的一个数放到了数组的最后面。相邻位置 之间交换 */ public class BubbleSort2{ public static void main(String[] args){ int[] a = {3,5,9,4,7,8,6,1,2}; BubbleSort2 bubble = new BubbleSort2(); bubble.bubble(a); for(int num:a){ System.out.print(num + " "); } } public void bubble(int[] a){ for(int i=a.length-1;i>0;i--){ for(int j=0;j0){ swap(a,j,j+1); } } } } public void swap(int[] a,int x,int y){ int temp; temp=a[x]; a[x]=a[y]; a[y]=temp; } } 二、选择排序 1. 基本思想: 每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好 序的数列的最后,直到全部待排序的数据元素排完。 2. 排序过程: 【示例】: 初始关键字[49 38 65 97 76 13 27 49] 第一趟排序后13 ,38 65 97 76 49 27 49] 第二趟排序后13 27 ,65 97 76 49 38 49] 第三趟排序后13 27 38 [97 76 49 65 49] 第四趟排序后13 27 38 49 [49 97 65 76] 第五趟排序后13 27 38 49 49 [97 97 76] 第六趟排序后13 27 38 49 49 76 [76 97] 第七趟排序后13 27 38 49 49 76 76 [ 97] 最后排序结果13 27 38 49 49 76 76 97 java代码实现: 01./** 02.* 简单选择排序:执行完一次内for循环后最小的一个数放在了数组的最前面。 03.*/ 04.public class SelectSort { 05. 06. /** 07. * 排序算法的实现,对数组中指定的元素进行排序 08. * @param array 待排序的数组 09. * @param from 从哪里开始排序 10. * @param end 排到哪里 11. * @param c 比较器 12. */ 13. public void select(Integer[] array) { 14. int minIndex;//最小索引 15. /* 16. * 循环整个数组(其实这里的上界为array.length - 1 即可,因为当i= array.length-1 17. * 时,最后一个元素就已是最大的了,如果为array.length时,内层循环将不再循环),每轮假设 18. * 第一个元素为最小元素,如果从第一元素后能选出比第一个元素更小元素,则让让最小元素与第一 19. * 个元素交换 20. */ 21. for (int i=0; i 0) { //找到插入点后,从插入点开始向后所有元素后移一位 move(array, j, i - 1); //将待排序元素插入到有序数组中 array[j] = insertedElem; break; } } } //=======以下是java.util.Arrays的插入排序算法的实现 /* * 该算法看起来比较简洁一j点,有点像冒泡算法。 * 将数组逻辑上分成前后两个集合,前面的集合是已经排序好序的元素,而后面集合为待排序的 * 集合,每次内层循从后面集合中拿出一个元素,通过冒泡的形式,从前面集合最后一个元素开 * 始往前比较,如果发现前面元素大于后面元素,则交换,否则循环退出 * * 总感觉这种算术有点怪怪,既然是插入排序,应该是先找到插入点,而后再将待排序的元素插 * 入到的插入点上,那么其他元素就必然向后移,感觉算法与排序名称不匹,但返过来与上面实 * 现比,其实是一样的,只是上面先找插入点,待找到后一次性将大的元素向后移,而该算法却 * 是走一步看一步,一步一步将待排序元素往前移 */ /* for (int i = from; i <= end; i++) { for (int j = i; j > from && c.compare(array[j - 1], array[j]) > 0; j--) { swap(array, j, j - 1); } } */ } /** * 数组元素后移 * @param array 待移动的数组 * @param startIndex 从哪个开始移 * @param endIndex 到哪个元素止 */ public void move(Integer[] array, int startIndex, int endIndex) { for (int i = endIndex; i >= startIndex; i--) { array[i+1] = array[i]; } } /** * 测试 * @param args */ public static void main(String[] args) { Integer[] intgArr = { 5, 9, 1, 4, 2, 6, 3, 8, 0, 7 }; InsertSort insertSort = new InsertSort(); insertSort.insert(intgArr,0,intgArr.length-1); for(Integer intObj:intgArr){ System.out.print(intObj + " "); } } } 四、稀尔排序 java代码实现: 01./** 02.* 插入排序----希尔排序:我们选择步长为:15,7,3,1 03.* 我们选择步长公式为:2^k-1,2^(k-1)-1,……,15,7,3,1 (2^4-1,2^3-1,2^2-1,2^1-1) 04.* 注意所有排序都是从小到大排。 05.*/ 06.public class ShellSort { 07. 08. /** 09. * 排序算法的实现,对数组中指定的元素进行排序 10. * @param array 待排序的数组 11. * @param from 从哪里开始排序 12. * @param end 排到哪里 13. * @param c 比较器 14. */ 15. public void sort(Integer[] array, int from, int end) { 16. //初始步长,实质为每轮的分组数 17. int step = initialStep(end - from + 1); 18. 19. //第一层循环是对排序轮次进行循环。(step + 1) / 2 - 1 为下一轮步长值 20. for (; step >= 1; step = (step + 1) / 2 - 1) { 21. //对每轮里的每个分组进行循环 22. for (int groupIndex = 0; groupIndex < step; groupIndex++) { 23. 24. //对每组进行直接插入排序 25. insertSort(array, groupIndex, step, end); 26. } 27. } 28. } 29. 30. /** 31. * 直接插入排序实现 32. * @param array 待排序数组 33. * @param groupIndex 对每轮的哪一组进行排序 34. * @param step 步长 35. * @param end 整个数组要排哪个元素止 36. * @param c 比较器 37. */ 38. public void insertSort(Integer[] array, int groupIndex, int step, int end) { 39. int startIndex = groupIndex;//从哪里开始排序 40. int endIndex = startIndex;//排到哪里 41. /* 42. * 排到哪里需要计算得到,从开始排序元素开始,以step步长,可求得下元素是 否在数组范围内, 43. * 如果在数组范围内,则继续循环,直到索引超现数组范围 44. */ 45. while ((endIndex + step) <= end) { 46. endIndex += step; 47. } 48. 49. // i为每小组里的第二个元素开始 50. for (int i = groupIndex + step; i <= end; i += step) { 51. for (int j = groupIndex; j < i; j += step) { 52. Integer insertedElem = array[i]; 53. //从有序数组中最一个元素开始查找第一个大于待插入的元素 54. if ((array[j].compareTo(insertedElem)) >= 0) { 55. //找到插入点后,从插入点开始向后所有元素后移一位 56. move(array, j, i - step, step); 57. array[j] = insertedElem; 58. break; 59. } 60. } 61. } 62. } 63. 64. /** 65. * 根据数组长度求初始步长 66. * 67. * 我们选择步长的公式为:2^k-1,2^(k-1)-1,...,15,7,3,1 ,其中2^k 减一即为 该步长序列,k 68. * 为排序轮次 69. * 70. * 初始步长:step = 2^k-1 71. * 初始步长约束条件:step < len - 1 初始步长的值要小于数组长度还要减一的 值(因 72. * 为第一轮分组时尽量不要分为一组,除非数组本身的长度就小于等于4) 73. * 74. * 由上面两个关系试可以得知:2^k - 1 < len - 1 关系式,其中k为轮次,如果把2^k 表 达式 75. * 转换成step 表达式,则2^k-1 可使用(step + 1)*2-1 替换(因为step+1 相当于第k-1 76. * 轮的步长,所以在step+1 基础上乘以2 就相当于2^k 了),即步长与数组长度的关系不等式为 77. * (step + 1)*2 - 1 < len -1 78. * 79. * @param len 数组长度 80. * @return 81. */ 82. public static int initialStep(int len) { 83. /* 84. * 初始值设置为步长公式中的最小步长,从最小步长推导出最长初始步长值,即按照以下公式来推: 85. * 1,3,7,15,...,2^(k-1)-1,2^k-1 86. * 如果数组长度小于等于4时,步长为1,即长度小于等于4的数组不用分组,此时直接退化为直接插入排序 87. */ 88. int step = 1; 89. 90. //试探下一个步长是否满足条件,如果满足条件,则步长置为下一步长 91. while ((step + 1) * 2 - 1 < len - 1) { 92. step = (step + 1) * 2 - 1; 93. } 94. 95. System.out.println("初始步长: " + step); 96. return step; 97. } 98. 99. /** 100. * 以指定的步长将数组元素后移,步长指定每个元素间的间隔 101. * @param array 待排序数组 102. * @param startIndex 从哪里开始移 103. * @param endIndex 到哪个元素止 104. * @param step 步长 105. */ 106. protected final void move(Integer[] array, int startIndex, int endIndex, int step) { 107. for (int i = endIndex; i >= startIndex; i -= step) { 108. array[i + step] = array[i]; 109. } 110. } 111. 112. 113. /** 114. * 测试 115. * @param args 116. */ 117. public static void main(String[] args) { 118. Integer[] intgArr = { 5, 9, 1, 4, 8, 2, 6, 3, 7, 0 }; 119. ShellSort shellSort = new ShellSort(); 120. shellSort.sort(intgArr,0,intgArr.length-1); 121. for(Integer intObj:intgArr){ 122. System.out.print(intObj + " "); 123. } 124. } 125.} 五、快速排序(Quick Sort) 1. 基本思想: 在当前无序区R[1..H]中任取一个数据元素作为比较的"基准"(不妨记为X),用此基准将当前无序区划分为左右两个较小的无序区:R[1..I-1]和R[I+1..H],且左边的无序子区中数据元素均小于等于基准元素,右边的无序子区中数据元素均大于等于基准元素,而基准X则位于最终排序的位置上,即R[1..I-1]?X.Key?R[I+1..H](1?I?H),当R[1..I-1] 和R[I+1..H]均非空时,分别对它们进行上述的划分过程,直至所有无序子区中的数据元素均已排序为止。 2. 排序过程: 【示例】: 初始关键字 ,49 38 65 97 76 13 27 49, 一趟排序之后 ,27 38 13,49 ,76 97 65 49, 二趟排序之后 ,13,27 ,38,49 ,49 65,76 ,97, 三趟排序之后13 27 38 49 49 ,65,76 97 最后的排序结果13 27 38 49 49 65 76 97 各趟排序之后的状态 java代码实现: 01./** 02.* 快速排序: 03.*/ 04. 05.public class QuickSort { 06. 07. /** 08. * 排序算法的实现,对数组中指定的元素进行排序 09. * @param array 待排序的数组 10. * @param from 从哪里开始排序 11. * @param end 排到哪里 12. * @param c 比较器 13. */ 14. //定义了一个这样的公有 方法 快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载 sort,在这个方法体里面执行私有方法quckSort(这 种方式值得借鉴)。 15. public void sort(Integer[] array, int from, int end) { 16. quickSort(array, from, end); 17. } 18. 19. /** 20. * 递归快速排序实现 21. * @param array 待排序数组 22. * @param low 低指针 23. * @param high 高指针 24. * @param c 比较器 25. */ 26. private void quickSort(Integer[] array, int low, int high) { 27. /* 28. * 如果分区中的低指针小于高指针时循环;如果low=higth说明数组只有一个元 素,无需再处理; 29. * 如果low > higth,则说明上次枢纽元素的位置pivot就是low或者是higth, 此种情况 30. * 下分区不存,也不需处理 31. */ 32. if (low < high) { 33. //对分区进行排序整理 34. 35. //int pivot = partition1(array, low, high); 36. int pivot = partition2(array, low, high); 37. //int pivot = partition3(array, low, high); 38. 39. /* 40. * 以pivot为边界,把数组分成三部分[low, pivot - 1]、[pivot]、[pivot + 1, high] 41. * 其中[pivot]为枢纽元素,不需处理,再对[low, pivot - 1]与[pivot + 1, high] 42. * 各自进行分区排序整理与进一步分区 43. */ 44. quickSort(array, low, pivot - 1); 45. quickSort(array, pivot + 1, high); 46. } 47. 48. } 49. 50. /** 51. * 实现一 52. * 53. * @param array 待排序数组 54. * @param low 低指针 55. * @param high 高指针 56. * @param c 比较器 57. * @return int 调整后中枢位置 58. */ 59. private int partition1(Integer[] array, int low, int high) { 60. Integer pivotElem = array[low];//以第一个元素为中枢元素 61. //从前向后依次指向比中枢元素小的元素,刚开始时指向中枢,也是小于与大小 中枢的元素的分界点 62. int border = low; 63. 64. /* 65. * 在中枢元素后面的元素中查找小于中枢元素的所有元素,并依次从第二个位置从前往后存放 66. * 注,这里最好使用i来移动,如果直接移动low的话,最后不知道数组的边界了,但后面需要 67. * 知道数组的边界 68. */ 69. for (int i = low + 1; i <= high; i++) { 70. //如果找到一个比中枢元素小的元素 71. if ((array[i].compareTo(pivotElem)) < 0) { 72. swap(array, ++border, i);//border前移,表示有小于中枢元素的元素 73. } 74. } 75. /* 76. * 如果border没有移动时说明说明后面的元素都比中枢元素要大,border与low相等,此时是 77. * 同一位置交换,是否交换都没关系;当border移到了high时说明所有元素都小于中枢元素,此 78. * 时将中枢元素与最后一个元素交换即可,即low与high进行交换,大的中枢元素移到了 序列最 79. * 后;如果low 0) { 112. swap(array, low, pivot); 113. //交换后中枢元素在低指针位置了 114. pivot = low; 115. } else {//如果未找到大于中枢元素,则低指针后移继续找 116. low++; 117. } 118. } 119. if (low == high) { 120. break; 121. } 122. } 123. //返回中枢元素所在位置,以便下次分区 124. return pivot; 125. } 126. 127. /** 128. * 实现三 129. * 130. * @param array 待排序数组 131. * @param low 待排序区低指针 132. * @param high 待排序区高指针 133. * @param c 比较器 134. * @return int 调整后中枢位置 135. */ 136. private int partition3(Integer[] array, int low, int high) { 137. int pivot = low;//中枢元素位置,我们以第一个元素为中枢元素 138. low++; 139. //----调整高低指针所指向的元素顺序,把小于中枢元素的移到前部分,大于中 枢元素的移到后面部分 140. //退出条件这里只可能是low = high 141. 142. while (true) { 143. //如果高指针未超出低指针 144. while (low < high) { 145. //如果低指针指向的元素大于或等于中枢元素时表示找到了,退出,注:等于时 也要后移 146. if ((array[low].compareTo(array[pivot])) >= 0) { 147. break; 148. } else {//如果低指针指向的元素小于中枢元素时继续找 149. low++; 150. } 151. } 152. 153. while (high > low) { 154. //如果高指针指向的元素小于中枢元素时表示找到,退出 155. if ((array[high].compareTo(array[pivot])) < 0) { 156. break; 157. } else {//如果高指针指向的元素大于中枢元素时继续找 158. high--; 159. } 160. } 161. //退出上面循环时low = high 162. if (low == high) { 163. break; 164. } 165. 166. swap(array, low, high); 167. } 168. 169. //----高低指针所指向的元素排序完成后,还得要把中枢元素放到适当的位置 170. if ((array[pivot].compareTo(array[low])) > 0) { 171. //如果退出循环时中枢元素大于了低指针或高指针元素时,中枢元素需与low元 素交换 172. swap(array, low, pivot); 173. pivot = low; 174. } else if ((array[pivot].compareTo(array[low])) <= 0) { 175. swap(array, low - 1, pivot); 176. pivot = low - 1; 177. } 178. 179. //返回中枢元素所在位置,以便下次分区 180. return pivot; 181. } 182. 183. /** 184. * 交换数组中的两个元素的位置 185. * @param array 待交换的数组 186. * @param i 第一个元素 187. * @param j 第二个元素 188. */ 189. public void swap(Integer[] array, int i, int j) { 190. if (i != j) {//只有不是同一位置时才需交换 191. Integer tmp = array[i]; 192. array[i] = array[j]; 193. array[j] = tmp; 194. } 195. } 196. 197. /** 198. * 测试 199. * @param args 200. */ 201. public static void main(String[] args) { 202. Integer[] intgArr = { 5, 9, 1, 4, 2, 6, 3, 8, 0, 7 }; 203. QuickSort quicksort = new QuickSort(); 204. quicksort.sort(intgArr,0,intgArr.length-1); 205. for(Integer intObj:intgArr){ 206. System.out.print(intObj + " "); 207. } 208. } 209.} 六、归并排序 java代码实现: ** 02.归并排序:里面是一个递归程序,深刻理解之。 03.*/ 04.public class MergeSort{ 05. 06. /** 07. * 递归划分数组 08. * @param arr 09. * @param from 10. * @param end 11. * @param c void 12. */ 13. public void partition(Integer[] arr, int from, int end) { 14. //划分到数组只有一个元素时才不进行再划分 15. if (from < end) { 16. //从中间划分成两个数组 17. int mid = (from + end) / 2; 18. partition(arr, from, mid); 19. partition(arr, mid + 1, end); 20. //合并划分后的两个数组 21. merge(arr, from, end, mid); 22. } 23. } 24. 25. /** 26. * 数组合并,合并过程中对两部分数组进行排序 27. * 前后两部分数组里是有序的 28. * @param arr 29. * @param from 30. * @param end 31. * @param mid 32. * @param c void 33. */ 34. public void merge(Integer[] arr, int from, int end, int mid) { 35. Integer[] tmpArr = new Integer[10]; 36. int tmpArrIndex = 0;//指向临时数组 37. int part1ArrIndex = from;//指向第一部分数组 38. int part2ArrIndex = mid + 1;//指向第二部分数组 39. 40. //由于两部分数组里是有序的,所以每部分可以从第一个元素依次取到最后一个 元素,再对两部分 41. //取出的元素进行比较。只要某部分数组元素取完后,退出循环 42. while ((part1ArrIndex <= mid) && (part2ArrIndex <= end)) { 43. //从两部分数组里各取一个进行比较,取最小一个并放入临时数组中 44. if (arr[part1ArrIndex] - arr[part2ArrIndex] < 0) { 45. //如果第一部分数组元素小,则将第一部分数组元素放入临时数组中,并且临时 数组指针 46. //tmpArrIndex下移一个以做好下次存储位置准备,前部分数组指针 part1ArrIndex 47. //也要下移一个以便下次取出下一个元素与后部分数组元素比较 48. tmpArr[tmpArrIndex++] = arr[part1ArrIndex++]; 49. } else { 50. //如果第二部分数组元素小,则将第二部分数组元素放入临时数组中 51. tmpArr[tmpArrIndex++] = arr[part2ArrIndex++]; 52. } 53. } 54. //由于退出循环后,两部分数组中可能有一个数组元素还未处理完,所以需要额 外的处理,当然不可 55. //能两部分数组都有未处理完的元素,所以下面两个循环最多只有一个会执行, 并且都是大于已放入 56. //临时数组中的元素 57. while (part1ArrIndex <= mid) { 58. tmpArr[tmpArrIndex++] = arr[part1ArrIndex++]; 59. } 60. while (part2ArrIndex <= end) { 61. tmpArr[tmpArrIndex++] = arr[part2ArrIndex++]; 62. } 63. 64. //最后把临时数组拷贝到源数组相同的位置 65. System.arraycopy(tmpArr, 0, arr, from, end - from + 1); 66. } 67. 68. /** 69. * 测试 70. * @param args 71. */ 72. public static void main(String[] args) { 73. Integer[] intgArr = {5,9,1,4,2,6,3,8,0,7}; 74. MergeSort insertSort = new MergeSort(); 75. insertSort.partition(intgArr,0,intgArr.length-1); 76. for(Integer a:intgArr){ 77. System.out.print(a + " "); 78. } 79. } 80.} 七、堆排序(Heap Sort) 1. 基本思想: 堆排序是一树形选择排序,在排序过程中,将R[1..N]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。 2. 堆的定义: N个元素的序列K1,K2,K3,...,Kn.称为堆,当且仅当该序列满足特性: Ki?K2i Ki ?K2i+1(1?I?[N/2]) 堆实质上是满足如下性质的完全二叉树:树中任一非叶子结点的关键字均大于等于其孩子结点的关键字。例如序列10,15,56,25,30,70就是一个堆,它对应的完全二叉树如上图所示。这种堆中根结点(称为堆顶)的关键字最小,我们把它称为小根堆。反之,若完全二叉树中任一非叶子结点的关键字均大于等于其孩子的关键字,则称之为大根堆。 3. 排序过程: 堆排序正是利用小根堆(或大根堆)来选取当前无序区中关键字小(或最大)的记录实现排序的。我们不妨利用大根堆来排序。每一趟排序的基本操作是:将当前无序区调整为一个大根堆,选取关键字最大的堆顶记录,将它和无序区中的最后一个记录交换。这样,正好和直接选择排序相反,有序区是在原记录区的尾部形成并逐步向前扩大到整个记录区。 【示例】:对关键字序列42,13,91,23,24,16,05,88建堆 java代码实现: 01./** 02.* 选择排序之堆排序: 03.*/ 04.public class HeapSort { 05. 06. /** 07. * 排序算法的实现,对数组中指定的元素进行排序 08. * @param array 待排序的数组 09. * @param from 从哪里开始排序 10. * @param end 排到哪里 11. * @param c 比较器 12. */ 13. public void sort(Integer[] array, int from, int end) { 14. //创建初始堆 15. initialHeap(array, from, end); 16. 17. /* 18. * 对初始堆进行循环,且从最后一个节点开始,直接树只有两个节点止 19. * 每轮循环后丢弃最后一个叶子节点,再看作一个新的树 20. */ 21. for (int i = end - from + 1; i >= 2; i--) { 22. //根节点与最后一个叶子节点交换位置,即数组中的第一个元素与最后一个元素 互换 23. swap(array, from, i - 1); 24. //交换后需要重新调整堆 25. adjustNote(array, 1, i - 1); 26. } 27. 28. } 29. 30. /** 31. * 初始化堆 32. * 比如原序列为:7,2,4,3,12,1,9,6,8,5,10,11 33. * 则初始堆为:1,2,4,3,5,7,9,6,8,12,10,11 34. * @param arr 排序数组 35. * @param from 从哪 36. * @param end 到哪 37. * @param c 比较器 38. */ 39. private void initialHeap(Integer[] arr, int from, int end) { 40. int lastBranchIndex = (end - from + 1) / 2;//最后一个非叶子节点 41. //对所有的非叶子节点进行循环 ,且从最一个非叶子节点开始 42. for (int i = lastBranchIndex; i >= 1; i--) { 43. adjustNote(arr, i, end - from + 1); 44. } 45. } 46. 47. /** 48. * 调整节点顺序,从父、左右子节点三个节点中选择一个最大节点与父节点转换 49. * @param arr 待排序数组 50. * @param parentNodeIndex 要调整的节点,与它的子节点一起进行调整 51. * @param len 树的节点数 52. * @param c 比较器 53. */ 54. private void adjustNote(Integer[] arr, int parentNodeIndex, int len) { 55. int minNodeIndex = parentNodeIndex; 56. //如果有左子树,i * 2为左子节点索引 57. if (parentNodeIndex * 2 <= len) { 58. //如果父节点小于左子树时 59. if ((arr[parentNodeIndex - 1].compareTo(arr[parentNodeIndex * 2 - 1])) < 0) { 60. minNodeIndex = parentNodeIndex * 2;//记录最大索引为左子节点索引 61. } 62. 63. // 只有在有或子树的前提下才可能有右子树,再进一步断判是否有右子树 64. if (parentNodeIndex * 2 + 1 <= len) { 65. //如果右子树比最大节点更大 66. if ((arr[minNodeIndex - 1].compareTo(arr[(parentNodeIndex * 2 + 1) - 1])) < 0) { 67. minNodeIndex = parentNodeIndex * 2 + 1;//记录最大索引为右子节点索引 68. } 69. } 70. } 71. 72. //如果在父节点、左、右子节点三都中,最大节点不是父节点时需交换,把最大 的与父节点交换,创建大顶堆 73. if (minNodeIndex != parentNodeIndex) { 74. swap(arr, parentNodeIndex - 1, minNodeIndex - 1); 75. //交换后可能需要重建堆,原父节点可能需要继续下沉 76. if (minNodeIndex * 2 <= len) {//是否有子节点,注,只需判断是否有左子树 即可知道 77. adjustNote(arr, minNodeIndex, len); 78. } 79. } 80. } 81. 82. /** 83. * 交换数组中的两个元素的位置 84. * @param array 待交换的数组 85. * @param i 第一个元素 86. * @param j 第二个元素 87. */ 88. public void swap(Integer[] array, int i, int j) { 89. if (i != j) {//只有不是同一位置时才需交换 90. Integer tmp = array[i]; 91. array[i] = array[j]; 92. array[j] = tmp; 93. } 94. } 95. 96. /** 97. * 测试 98. * @param args 99. */ 100. public static void main(String[] args) { 101. Integer[] intgArr = { 5, 9, 1, 4, 2, 6, 3, 8, 0, 7 }; 102. HeapSort heapsort = new HeapSort(); 103. heapsort.sort(intgArr,0,intgArr.length-1); 104. for(Integer intObj:intgArr){ 105. System.out.print(intObj + " "); 106. } 107. } 108. 109.} 八、桶式排序 java代码实现: 01./** 02. * 桶式排序: 03. * 桶式排序不再是基于比较的了,它和基数排序同属于分配类的排序, 04. * 这类排序的特点是事先要知道待排 序列的一些特征。 05. * 桶式排序事先要知道待排 序列在一个范围内,而且这个范围应该不是很大的。 06. * 比如知道待排序列在[0,M)内,那么可以分配M个桶,第I个桶记录I的出现 情况, 07. * 最后根据每个桶收到的位置信息把数据输出成有序的形式。 08. * 这里我们用两个临时性数组,一个用于记录位置信息,一个用于方便输出数据 成有序方式, 09. * 另外我们假设数据落在0到MAX,如果所给数据不是从0开始,你可以把每个数 减去最小的数。 10. */ 11.public class BucketSort { 12. public void sort(int[] keys,int from,int len,int max) 13. { 14. int[] temp=new int[len]; 15. int[] count=new int[max]; 16. 17. 18. for(int i=0;i=0;k--)//从最末到开头保持稳定性 30. { 31. keys[--count[temp[k]]]=temp[k];// position +1 =count 32. } 33. } 34. /** 35. * @param args 36. */ 37. public static void main(String[] args) { 38. 39. int[] a={1,4,8,3,2,9,5,0,7,6,9,10,9,13,14,15,11,12,17,16}; 40. BucketSort bucketSort=new BucketSort(); 41. bucketSort.sort(a,0,a.length,20);//actually is 18, but 20 will also work 42. 43. 44. for(int i=0;i 0) { 17. pow *= 10; 18. } 19. return (int) (x / pow % 10); 20. } 21. 22. /** 23. * 基数排序实现,以升序排序(下面程序中的位记录器count中,从第0个元素到第9个元素依次用来 24. * 记录当前比较位是0的有多少个..是9的有多少个数,而降序时则从第0个元素到第9个元素依次用来 25. * 记录当前比较位是9的有多少个..是0的有多少个数) 26. * @param arr 待排序数组 27. * @param digit 数组中最大数的位数 28. * @return 29. */ 30. public long[] radixSortAsc(long[] arr) { 31. //从低位往高位循环 32. for (int d = 1; d <= getMax(arr); d++) { 33. //临时数组,用来存放排序过程中的数据 34. long[] tmpArray = new long[arr.length]; 35. //位记数器,从第0个元素到第9个元素依次用来记录当前比较位是0的有多少个..是9的有多少个数 36. int[] count = new int[10]; 37. //开始统计0有多少个,并存储在第0位,再统计1有多少个,并存储在第1位..依次统计到9有多少个 38. for (int i = 0; i < arr.length; i++) { 39. count[digit(arr[i], d)] += 1; 40. } 41. /* 42. * 比如某次经过上面统计后结果为:[0, 2, 3, 3, 0, 0, 0, 0, 0, 0]则经过下面计算后 结果为: 43. * [0, 2, 5, 8, 8, 8, 8, 8, 8, 8]但实质上只有如下[0, 2, 5, 8, 0, 0, 0, 0, 0, 0]中 44. * 非零数才用到,因为其他位不存在,它们分别表示如下:2表示比较位为1的元素可以存放在索引为1、0的 45. * 位置,5表示比较位为2的元素可以存放在4、3、2三个(5-2=3)位置,8表示比较位为3的元素可以存放在 46. * 7、6、5三个(8-5=3)位置 47. */ 48. for (int i = 1; i < 10; i++) { 49. count[i] += count[i - 1]; 50. } 51. 52. /* 53. * 注,这里只能从数组后往前循环,因为排序时还需保持以前的已排序好的 顺序,不应该打 54. * 乱原来已排好的序,如果从前往后处理,则会把原来在前面会摆到后面去,因为在处理某个 55. * 元素的位置时,位记数器是从大到到小(count[digit(arr[i], d)]--)的方式来处 56. * 理的,即先存放索引大的元素,再存放索引小的元素,所以需从最后一个元素开始处理。 57. * 如有这样的一个序列[212,213,312],如果按照从第一个元素开始循环的话,经过第一轮 58. * 后(个位)排序后,得到这样一个序列[312,212,213],第一次好像没什么问题,但问题会 59. * 从第二轮开始出现,第二轮排序后,会得到[213,212,312],这样个位为3的元素本应该 60. * 放在最后,但经过第二轮后却排在了前面了,所以出现了问题 61. */ 62. for (int i = arr.length - 1; i >= 0; i--) {//只能从最后一个元素往前处理 63. //for (int i = 0; i < arr.length; i++) {//不能从第一个元素开始循环 64. tmpArray[count[digit(arr[i], d)] - 1] = arr[i]; 65. count[digit(arr[i], d)]--; 66. } 67. 68. System.arraycopy(tmpArray, 0, arr, 0, tmpArray.length); 69. } 70. return arr; 71. } 72. 73. /** 74. * 基数排序实现,以降序排序(下面程序中的位记录器count中,从第0个元素 到第9个元素依次用来 75. * 记录当前比较位是0的有多少个..是9的有多少个数,而降序时则从第0个元 素到第9个元素依次用来 76. * 记录当前比较位是9的有多少个..是0的有多少个数) 77. * @param arr 待排序数组 78. * @return 79. */ 80. public long[] radixSortDesc(long[] arr) { 81. for (int d = 1; d <= getMax(arr); d++) { 82. long[] tmpArray = new long[arr.length]; 83. //位记数器,从第0个元素到第9个元素依次用来记录当前比较位是9的有多少 个..是0的有多少个数 84. int[] count = new int[10]; 85. //开始统计0有多少个,并存储在第9位,再统计1有多少个,并存储在第8位.. 依次统计 86. //到9有多少个,并存储在第0位 87. for (int i = 0; i < arr.length; i++) { 88. count[9 - digit(arr[i], d)] += 1; 89. } 90. 91. for (int i = 1; i < 10; i++) { 92. count[i] += count[i - 1]; 93. } 94. 95. for (int i = arr.length - 1; i >= 0; i--) { 96. tmpArray[count[9 - digit(arr[i], d)] - 1] = arr[i]; 97. count[9 - digit(arr[i], d)]--; 98. } 99. 100. System.arraycopy(tmpArray, 0, arr, 0, tmpArray.length); 101. } 102. return arr; 103. } 104. 105. private int getMax(long[] array) { 106. int maxlIndex = 0; 107. for (int j = 1; j < array.length; j++) { 108. if (array[j] > array[maxlIndex]) { 109. maxlIndex = j; 110. } 111. } 112. return String.valueOf(array[maxlIndex]).length(); 113. } 114. 115. public static void main(String[] args) { 116. long[] ary = new long[] { 123, 321, 132, 212, 213, 312, 21, 223 }; 117. RadixSort rs = new RadixSort(); 118. System.out.println("升- " + Arrays.toString(rs.radixSortAsc(ary))); 119. 120. ary = new long[] { 123, 321, 132, 212, 213, 312, 21, 223 }; 121. System.out.println("降- " + Arrays.toString(rs.radixSortDesc(ary))); 122. } 123.} 十、几种排序算法的比较和选择 1. 选取排序方法需要考虑的因素: (1) 待排序的元素数目n; (2) 元素本身信息量的大小; (3) 关键字的结构及其分布情况; (4) 语言工具的条件,辅助空间的大小等。 2. 小结: (1) 若n较小(n <= 50),则可以采用直接插入排序或直接选择排序。由于直接插入排序所需的记录移动操作较直接选择排序多,因而当记录本身信息量较大时,用直接选择排序较好。 (2) 若文件的初始状态已按关键字基本有序,则选用直接插入或冒泡排序为宜。 (3) 若n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序。 快速排序是目前基于比较的内部排序法中被认为是最好的方法。 (4) 在基于比较排序方法中,每次比较两个关键字的大小之后,仅仅出现两种可能的转移,因此可以用一棵二叉树来描述比较判定过程,由此可以证明:当文件的n个关键字随机分布时,任何借助于"比较"的排序算法,至少需要O(nlog2n)的时间。 (5) 当记录本身信息量较大时,为避免耗费大量时间移动记录,可以用链表作为存储结构。 排序简介 排序是数据处理中经常使用的一种重要运算,在计算机及其应用系统中,花费在排序上的时间在系统运行时间中占有很大比重;并且排序本身对推动算法分析的发展也起很大作用。目前已有上百种排序方法,但尚未有一个最理想的尽如人意的方法,本章介绍常用的如下排序方法,并对它们进行分析和比较。 1、插入排序(直接插入排序、折半插入排序、希尔排序); 2、交换排序(起泡排序、快速排序); 3、选择排序(直接选择排序、堆排序); 4、归并排序; 5、基数排序; 学习重点 1、掌握排序的基本概念和各种排序方法的特点,并能加以灵活应用; 2、掌握插入排序(直接插入排序、折半插入排序、希尔排序)、交换排序(起泡排序、快速排序)、选择排序(直接选择排序、堆排序)、二路归并排序的方法及其性能分析方法; 3、了解基数排序方法及其性能分析方法。 排序(sort)或分类 所谓排序,就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来。其确切定义如下: 输入:n个记录R1,R2,…,Rn,其相应的关键字分别为K1,K2,…,Kn。 输出:Ril,Ri2,…,Rin,使得Ki1?Ki2?…?Kin。(或Ki1?Ki2?…?Kin)。 1(被排序对象--文件 被排序的对象--文件由一组记录组成。 记录则由若干个数据项(或域)组成。其中有一项可用来标识一个记录,称为关键字项。该数据项的值称为关键字(Key)。 注意: 在不易产生混淆时,将关键字项简称为关键字。 2(排序运算的依据--关键字 用来作排序运算依据的关键字,可以是数字类型,也可以是字符类型。 关键字的选取应根据问题的要求而定。 【例】在高考成绩统计中将每个考生作为一个记录。每条记录包含准考证号、姓名、各科的分数和总分数等项 内容 财务内部控制制度的内容财务内部控制制度的内容人员招聘与配置的内容项目成本控制的内容消防安全演练内容 。若要惟一地标识一个考生的记录,则必须用"准考证号"作为关键字。若要按照考生的总分数排名次,则需用"总分数"作为关键字。 排序的稳定性 当待排序记录的关键字均不相同时,排序结果是惟一的,否则排序结果不唯一。 在待排序的文件中,若存在多个关键字相同的记录,经过排序后这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是稳定的;若具有相同关键字的记录之间的相对次序发生变化,则称这种排序方法是不稳定的。 注意: 排序算法的稳定性是针对所有输入实例而言的。即在所有可能的输入实例中,只要有一个实例使得算法不满足稳定性要求,则该排序算法就是不稳定的。 排序方法的分类 1(按是否涉及数据的内、外存交换分 在排序过程中,若整个文件都是放在内存中处理,排序时不涉及数据的内、外存交换,则称之为内部排序(简称内排序);反之,若排序过程中要进行数据的内、外存交换,则称之为外部排序。 注意: ? 内排序适用于记录个数不很多的小文件 ? 外排序则适用于记录个数太多,不能一次将其全部记录放人内存的大文件。 2(按策略划分内部排序方法 可以分为五类:插入排序、选择排序、交换排序、归并排序和分配排序。 排序算法分析 1(排序算法的基本操作 大多数排序算法都有两个基本的操作: (1) 比较两个关键字的大小; (2) 改变指向记录的指针或移动记录本身。 注意: 第(2)种基本操作的实现依赖于待排序记录的存储方式。 2(待排文件的常用存储方式 (1) 以顺序表(或直接用向量)作为存储结构 排序过程:对记录本身进行物理重排(即通过关键字之间的比较判定,将记录移到合适的位置) (2) 以链表作为存储结构 排序过程:无须移动记录,仅需修改指针。通常将这类排序称为链表(或链式)排序; (3) 用顺序的方式存储待排序的记录,但同时建立一个辅助表(如包括关键字和指向记录位置的指针组成的索引表) 排序过程:只需对辅助表的表目进行物理重排(即只移动辅助表的表目,而不移动记录本身)。适用于难于在链表上实现,仍需避免排序过程中移动记录的排序方法。 3(排序算法性能评价 (1) 评价排序算法好坏的 标准 excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载 评价排序算法好坏的标准主要有两条: ? 执行时间和所需的辅助空间 ? 算法本身的复杂程度 (2) 排序算法的空间复杂度 若排序算法所需的辅助空间并不依赖于问题的规模n,即辅助空间是O(1),则称 之为就地排序(In-PlaceSou)。 非就地排序一般要求的辅助空间为O(n)。 (3) 排序算法的时间开销 大多数排序算法的时间开销主要是关键字之间的比较和记录的移动。有的排序算 法其执行时间不仅依赖于问题的规模,还取决于输入实例中数据的状态。 文件的顺序存储结构表示 #define n l00 //假设的文件长度,即待排序的记录数目 typedef int KeyType;//假设的关键字类型 typedef struct{ //记录类型 KeyType key;//关键字项 InfoType otherinfo;//其它数据项,类型InfoType依赖于具体应用而定义 }RecType; typedef RecType SeqList[n+1];//SeqList为顺序表类型,表中第0个单元一般用作 哨兵 注意: 若关键字类型没有比较算符,则可事先定义宏或函数来表示比较运算。 【例】关键字为字符串时,可定义宏"#define LT(a,b)(Stromp((a),(b))<0)"。那 么算法中"a 规定 关于下班后关闭电源的规定党章中关于入党时间的规定公务员考核规定下载规定办法文件下载宁波关于闷顶的规定 的次序重排各记录,完成这种重排的时间是O(n)。 001 //插入排序: 002 003 package org.rut.util.algorithm.support; 004 005 import org.rut.util.algorithm.SortUtil; 006 /** 007 * @author treeroot 008 * @since 2006-2-2 009 * @version 1.0 010 */ 011 public class InsertSort implements SortUtil.Sort{ 012 013 /** (non-Javadoc) 014 * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[]) 015 */ 016 public void sort(int[] data) { 017 int temp; 018 for(int i=1;i0)&&(data[j]i;j--){ 059 if(data[j] i; j--) { 091 if (data[j] < data[lowIndex]) { 092 lowIndex = j; 093 } 094 } 095 SortUtil.swap(data,i,lowIndex); 096 } 097 } 098 099 } 100 101 //Shell排序: 102 103 package org.rut.util.algorithm.support; 104 105 import org.rut.util.algorithm.SortUtil; 106 107 /** 108 * @author treeroot 109 * @since 2006-2-2 110 * @version 1.0 111 */ 112 public class ShellSort implements SortUtil.Sort{ 113 114 /** (non-Javadoc) 115 * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[]) 116 */ 117 public void sort(int[] data) { 118 for(int i=data.length/2;i>2;i/=2){ for(int 119 j=0;j=inc)&&(data[j]1) quickSort(data,i,k-1); 169 if((j-k)>1) quickSort(data,k+1,j); 170 171 } 172 /** 173 * @param data 174 * @param i 175 * @param j 176 * @return 177 */ 178 private int partition(int[] data, int l, int r,int pivot) { 179 do{ 180 while(data[++l]pivot); 182 SortUtil.swap(data,l,r); 183 } 184 while(l0){ 219 int j=stack[top--]; 220 int i=stack[top--]; 221 222 pivotIndex=(i+j)/2; 223 pivot=data[pivotIndex]; 224 225 SortUtil.swap(data,pivotIndex,j); 226 227 //partition 228 l=i-1; 229 r=j; 230 do{ 231 while(data[++l]pivot)); 233 SortUtil.swap(data,l,r); 234 } 235 while(lTHRESHOLD){ 240 stack[++top]=i; 241 stack[++top]=l-1; 242 } 243 if((j-l)>THRESHOLD){ 244 stack[++top]=l+1; 245 stack[++top]=j; 246 } 247 248 } 249 //new InsertSort().sort(data); 250 insertSort(data); 251 } 252 /** 253 * @param data 254 */ 255 private void insertSort(int[] data) { 256 int temp; 257 for(int i=1;i0)&&(data[j]r) 301 data[cur]=temp[i1++]; 302 else if(temp[i1]= THRESHOLD) 342 mergeSort(data, temp, l, mid); 343 else 344 insertSort(data, l, mid - l + 1); 345 if ((r - mid) > THRESHOLD) 346 mergeSort(data, temp, mid + 1, r); 347 else 348 insertSort(data, mid + 1, r - mid); 349 350 for (i = l; i <= mid; i++) { 351 temp[i] = data[i]; 352 } 353 for (j = 1; j <= r - mid; j++) { 354 temp[r - j + 1] = data[j + mid]; 355 } 356 int a = temp[l]; 357 int b = temp[r]; 358 for (i = l, j = r, k = l; k <= r; k++) { 359 if (a < b) { 360 data[k] = temp[i++]; 361 a = temp[i]; 362 } else { 363 data[k] = temp[j--]; 364 b = temp[j]; 365 } 366 } 367 } 368 369 /** 370 * @param data 371 * @param l 372 * @param i 373 */ 374 private void insertSort(int[] data, int start, int len) { 375 for(int i=start+1;istart) && data[j]queue[j]) //不用交换 438 break; 439 SortUtil.swap(queue,j,k); 440 k = j; 441 } 442 } 443 private void fixUp(int k) { 444 while (k > 1) { 445 int j = k >> 1; 446 if (queue[j]>queue[k]) 447 break; 448 SortUtil.swap(queue,j,k); 449 k = j; 450 } 451 } 452 453 } 454 455 } 456 457 458 459 //SortUtil: 460 461 package org.rut.util.algorithm; 462 463 import org.rut.util.algorithm.support.BubbleSort; 464 import org.rut.util.algorithm.support.HeapSort; 465 import org.rut.util.algorithm.support.ImprovedMergeSort; 466 import org.rut.util.algorithm.support.ImprovedQuickSort; 467 import org.rut.util.algorithm.support.InsertSort; 468 import org.rut.util.algorithm.support.MergeSort; 469 import org.rut.util.algorithm.support.QuickSort; 470 import org.rut.util.algorithm.support.SelectionSort; 471 import org.rut.util.algorithm.support.ShellSort; 472 473 /** 474 * @author treeroot 475 * @since 2006-2-2 476 * @version 1.0 477 */ 478 public class SortUtil { 479 public final static int INSERT = 1; 480 481 public final static int BUBBLE = 2; 482 483 public final static int SELECTION = 3; 484 485 public final static int SHELL = 4; 486 487 public final static int QUICK = 5; 488 489 public final static int IMPROVED_QUICK = 6; 490 491 public final static int MERGE = 7; 492 493 public final static int IMPROVED_MERGE = 8; 494 495 public final static int HEAP = 9; 496 497 public static void sort(int[] data) { 498 sort(data, IMPROVED_QUICK); 499 } 500 private static String[] name={ 50"insert","bubble","selection","shell","quick","improved_quick","me 1 rge","improved_merge","heap" 502 }; 503 504 private static Sort[] impl=new Sort[]{ 505 new InsertSort(), 506 new BubbleSort(), 507 new SelectionSort(), 508 new ShellSort(), 509 new QuickSort(), 510 new ImprovedQuickSort(), 511 new MergeSort(), 512 new ImprovedMergeSort(), 513 new HeapSort() 514 }; 515 516 public static String toString(int algorithm){ 517 return name[algorithm-1]; 518 } 519 520 public static void sort(int[] data, int algorithm) { 521 impl[algorithm-1].sort(data); 522 } 523 524 public static interface Sort { 525 public void sort(int[] data); 526 } 527 528 public static void swap(int[] data, int i, int j) { 529 int temp = data[i]; 530 data[i] = data[j]; 531 data[j] = temp; 532 } 533 }
本文档为【各种排序算法及其java程序实现&#46;】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_954223
暂无简介~
格式:doc
大小:138KB
软件:Word
页数:0
分类:企业经营
上传时间:2017-09-30
浏览量:15