title: 带权中位数
date: 2021-04-12
tags: 算法
categories: 学习
mathjax: true

带权中位数

1.题目描述

带权中位数 - 图1

2.思想

基于寻找无序数组第k小个数的select算法,以rand()选出的pivot将数组分为三个部分,并进行前后两部分权值总和的判断。
若leftWeight <=0.5 && rightWeight <=0.5,pivot为带权中位数
否则,若leftWeight > rightWeight,则带权中位数在pivot左侧数组中,将右侧权值赋给pivot,进行递归
leftWeight<= rightWeight同理

原文链接:https://blog.csdn.net/qq_36544876/article/details/88866480

3.代码

  1. #include"iostream"
  2. #include"cstdlib"
  3. using namespace std;
  4. class term
  5. {
  6. public:
  7. double num;
  8. double weight;
  9. };
  10. class Term_array
  11. {
  12. public:
  13. term *elmt;
  14. int num;
  15. int head;
  16. int tail;
  17. Term_array(int Element_num)
  18. {
  19. num = Element_num;
  20. head = 0;
  21. tail = num - 1;
  22. elmt = new term[Element_num];//记得中括号
  23. for (int i = 0; i < Element_num; i++)
  24. {
  25. elmt[i].num = 0;
  26. elmt[i].weight = 0;
  27. }
  28. }
  29. ~Term_array()
  30. {
  31. if (elmt)
  32. delete[]elmt;
  33. }
  34. };
  35. /*测试用
  36. void print(Term_array &arr)
  37. {
  38. for (int i =0; i < arr.num; i++)
  39. {
  40. cout << arr.elmt[i].num << ' ' << arr.elmt[i].weight << ' ' << endl;
  41. }
  42. cout << "-----------" << endl;
  43. }
  44. */
  45. void swaparr(int ele1, int ele2, Term_array &arr)
  46. {
  47. double num_tmp = arr.elmt[ele1].num;
  48. double weight_tmp = arr.elmt[ele1].weight;
  49. arr.elmt[ele1].num = arr.elmt[ele2].num;
  50. arr.elmt[ele1].weight = arr.elmt[ele2].weight;
  51. arr.elmt[ele2].num = num_tmp;
  52. arr.elmt[ele2].weight = weight_tmp;
  53. }
  54. void copyele(int ele1, int ele2, Term_array &arr)
  55. {
  56. arr.elmt[ele1].num = arr.elmt[ele2].num;
  57. arr.elmt[ele1].weight = arr.elmt[ele2].weight;
  58. }
  59. int partition(int p,Term_array &arr)//以下标p开始划分
  60. {
  61. int start = arr.head;
  62. swaparr(start, p, arr);//与0号交换位置
  63. term tmp = arr.elmt[start];
  64. int l =arr.head; int r = arr.tail;
  65. while (l < r)
  66. {
  67. while (l < r&&arr.elmt[r].num >= tmp.num)
  68. {
  69. r--;
  70. }
  71. copyele(l, r, arr);
  72. while (l < r&&arr.elmt[l].num <= tmp.num)
  73. {
  74. l++;
  75. }
  76. copyele(r, l, arr);
  77. }
  78. arr.elmt[l] = tmp;
  79. return l;
  80. }
  81. int isWm(int &l, Term_array &arr)
  82. {
  83. int flag = 0;
  84. double lsum = 0.0;
  85. double rsum = 0.0;
  86. for (int i = 0; i < l; i++)
  87. lsum += arr.elmt[i].weight;
  88. for (int i = l + 1; i < arr.num; i++)
  89. rsum += arr.elmt[i].weight;
  90. if (lsum<=0.5&&rsum<=0.5)
  91. flag = 0;
  92. else if (lsum < rsum)
  93. flag = -1;
  94. else if(lsum>rsum)
  95. flag = 1;
  96. return flag;
  97. }
  98. int main()
  99. {
  100. int Element_Num = 0;
  101. int Wm = 0;
  102. cin >> Element_Num;
  103. Term_array arr(Element_Num);
  104. for (int i = arr.head; i <= arr.tail; i++)
  105. {
  106. cin >> arr.elmt[i].num;
  107. }
  108. for (int i = arr.head; i <= arr.tail; i++)
  109. {
  110. cin >> arr.elmt[i].weight;
  111. }
  112. if (arr.num > 1)
  113. {
  114. int rand_num = (rand() % (arr.tail - arr.head + 1) + arr.head);//生成随机数
  115. int pos = partition(8, arr);//随机开始划分
  116. //接下来判断是否是带权中位数
  117. int flag = 0;
  118. while (1)
  119. {
  120. flag = isWm(pos, arr);
  121. if (flag == 0)//恰好是带权中位数
  122. {
  123. Wm = arr.elmt[pos].num;
  124. break;
  125. }
  126. else if (flag == -1)//右边大于左边,在右边找
  127. {
  128. arr.head = pos + 1;
  129. rand_num = (rand() % (arr.tail - arr.head + 1) + arr.head);
  130. pos = partition(rand_num, arr);
  131. }
  132. else if (flag == 1)
  133. {
  134. arr.tail = pos - 1;
  135. rand_num = (rand() % (arr.tail - arr.head + 1) + arr.head);
  136. pos = partition(rand_num, arr);
  137. }
  138. }
  139. }
  140. else
  141. Wm = arr.elmt[0].num;
  142. cout << Wm << endl;
  143. return 0;
  144. }