00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "quickselect.h"
00011
00012 #define ELEM_SWAP(a,b) { register unsigned char t=(a);(a)=(b);(b)=t; }
00013
00014 unsigned char
00015 quick_select(unsigned char *arr, int nelems, int select)
00016 {
00017 int low, high, middle, ll, hh;
00018
00019 low = 0;
00020 high = nelems - 1;
00021
00022 for (;;) {
00023 if (high <= low)
00024 return arr[select];
00025
00026 if (high == low + 1) {
00027 if (arr[low] > arr[high])
00028 ELEM_SWAP(arr[low], arr[high]);
00029 return arr[select];
00030 }
00031
00032
00033 middle = (low + high) / 2;
00034 if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]);
00035 if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]);
00036 if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]);
00037
00038
00039 ELEM_SWAP(arr[middle], arr[low+1]);
00040
00041
00042 ll = low + 1;
00043 hh = high;
00044 for (;;) {
00045 do ll++; while (arr[low] > arr[ll]);
00046 do hh--; while (arr[hh] > arr[low]);
00047
00048 if (hh < ll)
00049 break;
00050
00051 ELEM_SWAP(arr[ll], arr[hh]);
00052 }
00053
00054
00055 ELEM_SWAP(arr[low], arr[hh]);
00056
00057
00058 if (hh <= select)
00059 low = ll;
00060 if (hh >= select)
00061 high = hh - 1;
00062 }
00063 }
00064
00065 #undef ELEM_SWAP
00066
00067 unsigned char
00068 quick_select_median(unsigned char *arr, int nelems)
00069 {
00070 return quick_select(arr, nelems, (nelems - 1) / 2);
00071 }
00072
00073 #define ELEM_SWAP(a,b) { register unsigned short t=(a);(a)=(b);(b)=t; }
00074
00075 unsigned short
00076 quick_select_ushort(unsigned short *arr, int nelems, int select)
00077 {
00078 int low, high, middle, ll, hh;
00079
00080 low = 0;
00081 high = nelems - 1;
00082
00083 for (;;) {
00084 if (high <= low)
00085 return arr[select];
00086
00087 if (high == low + 1) {
00088 if (arr[low] > arr[high])
00089 ELEM_SWAP(arr[low], arr[high]);
00090 return arr[select];
00091 }
00092
00093
00094 middle = (low + high) / 2;
00095 if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]);
00096 if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]);
00097 if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]);
00098
00099
00100 ELEM_SWAP(arr[middle], arr[low+1]);
00101
00102
00103 ll = low + 1;
00104 hh = high;
00105 for (;;) {
00106 do ll++; while (arr[low] > arr[ll]);
00107 do hh--; while (arr[hh] > arr[low]);
00108
00109 if (hh < ll)
00110 break;
00111
00112 ELEM_SWAP(arr[ll], arr[hh]);
00113 }
00114
00115
00116 ELEM_SWAP(arr[low], arr[hh]);
00117
00118
00119 if (hh <= select)
00120 low = ll;
00121 if (hh >= select)
00122 high = hh - 1;
00123 }
00124 }
00125
00126 #undef ELEM_SWAP
00127
00128 unsigned short
00129 quick_select_median_ushort(unsigned short *arr, int nelems)
00130 {
00131 return quick_select_ushort(arr, nelems, (nelems - 1) / 2);
00132 }
00133
00134 #define ELEM_SWAP(a,b) { register float t=(a);(a)=(b);(b)=t; }
00135
00136 float
00137 quick_select_float(float *arr, int nelems, int select)
00138 {
00139 int low, high, middle, ll, hh;
00140
00141 low = 0;
00142 high = nelems - 1;
00143
00144 for (;;) {
00145 if (high <= low)
00146 return arr[select];
00147
00148 if (high == low + 1) {
00149 if (arr[low] > arr[high])
00150 ELEM_SWAP(arr[low], arr[high]);
00151 return arr[select];
00152 }
00153
00154
00155 middle = (low + high) / 2;
00156 if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]);
00157 if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]);
00158 if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]);
00159
00160
00161 ELEM_SWAP(arr[middle], arr[low+1]);
00162
00163
00164 ll = low + 1;
00165 hh = high;
00166 for (;;) {
00167 do ll++; while (arr[low] > arr[ll]);
00168 do hh--; while (arr[hh] > arr[low]);
00169
00170 if (hh < ll)
00171 break;
00172
00173 ELEM_SWAP(arr[ll], arr[hh]);
00174 }
00175
00176
00177 ELEM_SWAP(arr[low], arr[hh]);
00178
00179
00180 if (hh <= select)
00181 low = ll;
00182 if (hh >= select)
00183 high = hh - 1;
00184 }
00185 }
00186
00187 float
00188 quick_select_median_float(float *arr, int nelems)
00189 {
00190 return quick_select_float(arr, nelems, (nelems - 1) / 2);
00191 }
00192
00193 #undef ELEM_SWAP
00194
00195