数组索引排序算法 案例

7 篇文章 0 订阅

索引排序

在排序时,若是数据很复杂,对数据的移动显然是费时的。若把数据移动改为索引(或指针)移动,则减少了操作复杂度。索引排序,也叫地址排序,就是这种排序思想。

索引含义

根据索引的含义不同,索引排序的算法上也主要分为两种。

一、index[i]为array[i]最终在有序序列中的位置。

二、index[i]为位置i上最终应存放元素的下标。即最终元素按array[index[0]]、array[index[1]]……有序。

一个实例

原序列 array: 17  19  23  21  38  5   33  22

        下标:0   1   2   3   4   5   6   7

      index1:1   2   5   3   7   0   6   4

      index2:5   0   1   3   7   2   6   4

得到索引数组后,根据索引数组对元素进行重排,由于index含义不同,重排算法也不同。下面直接给出两种索引排序代码,代码中有详细注释:

索引排序一

代码


 
 
  1. #include<iostream>
  2. #include<iomanip>
  3. using namespace std;
  4. /*
  5. 索引排序一
  6. index[i]是array[i]的最终下标
  7. */
  8. void IndexSort1(int array[], int n)
  9. {
  10. if ( array && n > 1)
  11. {
  12. //创建索引数组
  13. int *index = new int[n];
  14. //初始化索引数组
  15. int i, j;
  16. for (i = 0; i < n; i++)
  17. index[i] = i;
  18. //类似于插入排序,在插入比较的过程中不断地修改index数组
  19. for (i = 1; i < n; i++)
  20. {
  21. j = i;
  22. while (j)
  23. {
  24. if ( array[i] < array[j -1])
  25. {
  26. index[i]--;
  27. index[j - 1]++;
  28. }
  29. j--;
  30. }
  31. }
  32. //打印索引数组
  33. cout << "索引数组" << endl;
  34. for (i = 0; i < n; i++)
  35. cout << setw( 4) << index[i];
  36. cout << endl;
  37. //根据index数组,重排原序列
  38. bool modified = true;
  39. while (modified)
  40. {
  41. modified = false;
  42. for (i = 0; i < n - 1; i++)
  43. {
  44. //如果不在位置上,则调整
  45. if (index[i] != i)
  46. {
  47. modified = true;
  48. j = index[i];
  49. swap( array[i], array[j]);
  50. index[i] = index[j];
  51. index[j] = j;
  52. }
  53. }
  54. }
  55. //释放空间
  56. delete[]index;
  57. }
  58. }
  59. //打印
  60. void print(int array[], int n)
  61. {
  62. if( array && n> 0)
  63. {
  64. int i;
  65. for (i = 0; i < n; i++)
  66. cout << setw( 4) << array[i];
  67. cout << endl;
  68. }
  69. }
  70. int main()
  71. {
  72. cout << "***索引排序***by David***\n";
  73. int array[] = { 17, 19, 23, 21, 38, 5, 33, 22};
  74. int n = sizeof( array) / sizeof( array[ 0]);
  75. cout << "原序列\n";
  76. print( array, n);
  77. cout << "索引排序一" << endl;
  78. IndexSort1( array, n);
  79. cout << "排序后" << endl;
  80. print( array, n);
  81. system( "pause");
  82. return 0;
  83. }

运行


 

索引排序二

代码


 
 
  1. #include<iostream>
  2. #include<iomanip>
  3. using namespace std;
  4. /*
  5. 索引排序二
  6. index[i]是array[i]中应该放置数据的下标
  7. */
  8. void IndexSort2(int array[], int n)
  9. {
  10. if ( array && n > 1)
  11. {
  12. //创建索引数组
  13. int *index = new int[n];
  14. //初始化索引数组
  15. int i, j;
  16. for (i = 0; i < n; i++)
  17. index[i] = i;
  18. //类似于插入排序,在插入比较的过程中不断地修改index数组
  19. for (i = 0; i < n; i++)
  20. {
  21. j = i;
  22. while (j)
  23. {
  24. if ( array[index[j]] < array[index[j - 1]])
  25. swap(index[j], index[j - 1]);
  26. else
  27. break;
  28. j--;
  29. }
  30. }
  31. //打印索引数组
  32. cout << "索引数组" << endl;
  33. for (i = 0; i < n; i++)
  34. cout << setw( 4) << index[i];
  35. cout << endl;
  36. //元素重排
  37. int temp, k;
  38. for (i = 0; i < n; i++)
  39. {
  40. j = i;
  41. temp = array[i];
  42. while (index[j] != i)
  43. {
  44. k = index[j];
  45. array[j] = array[k];
  46. index[j] = j;
  47. j = k;
  48. }
  49. array[j] = temp;
  50. index[j] = j;
  51. }
  52. //释放空间
  53. delete[]index;
  54. }
  55. }
  56. //打印
  57. void print(int array[], int n)
  58. {
  59. if( array && n> 0)
  60. {
  61. int i;
  62. for (i = 0; i < n; i++)
  63. cout << setw( 4) << array[i];
  64. cout << endl;
  65. }
  66. }
  67. int main()
  68. {
  69. cout << "***索引排序***by David***\n";
  70. int array[] = { 17, 19, 23, 21, 38, 5, 33, 22};
  71. int n = sizeof( array) / sizeof( array[ 0]);
  72. cout << "原序列\n";
  73. print( array, n);
  74. cout << "索引排序二" << endl;
  75. IndexSort2( array, n);
  76. cout << "排序后" << endl;
  77. print( array, n);
  78. system( "pause");
  79. return 0;
  80. }

元素重排算法的详细解释


 
 
  1. /*
  2. 元素重排
  3. 看似两重循环,则实际上的时间复杂度是线性的:O(n)
  4. 一般情况下,经过一次while循环,将有多个元素归位
  5. */
  6. int temp, k;
  7. for (i = 0; i < n; i++)
  8. {
  9. /*
  10. 加了这个判断后,while循环的后两条语句的执行得到优化
  11. :当元素已在正确的位置,则不需回填
  12. */
  13. if (index[i] != i)
  14. {
  15. //以下的做法类似于“挖坑填数”
  16. j = i;
  17. temp = array[i];
  18. while (index[j] != i)
  19. {
  20. k = index[j];
  21. //元素归位
  22. array[j] = array[k];
  23. //索引归位
  24. index[j] = j;
  25. //新的坑
  26. j = k;
  27. }
  28. //元素归位
  29. array[j] = temp;
  30. //索引归位
  31. index[j] = j;
  32. }
  33. }

运行


    

转载请注明出处,本文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/37889669


若有所帮助,顶一个哦!


专栏目录:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值