-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathquicksort.m
175 lines (157 loc) · 4.12 KB
/
quicksort.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
function index = quicksort(input, inl_fcn)
% QUICKSORT
% syntax:
% Index = quicksort(Input, Cmp_func)
%
% Input may be any Matlab data type multidimensional matrix or cell array.
%
% Input may be a multidimensional matrix or cell array.
% The sort is performed along the first non-singleton
% dimension of Input. The trivial case of a 1x1 input
% will not cause a crash.
%
% Cmp_func may be an inline function or function handle.
% Function handles are much faster than inlines.
% Cmp_func must take as arguments the input array and
% two indices. It then returns 1 if the element(s)
% associated with the first index rank higher than that
% (those) of the second index. It returns -1 if the same
% ranks lower and 0 if they are considered equal.
%
% Index is a 1xN index vector which can be used to sort
% the Input argument.
%
% Example:
% Sort a two-column matrix of integers by pairs with the
% first column in ascending order and the second column
% in descending order when the first column elements are
% equal.
%
% % matrix to be sorted
% x = floor(rand(10000,2)*10);
%
% % inline comparison function
% i_cmp = inline( ...
% 'sign(sign(m(x,1)-m(y,1))*10-sign(m(x,2)-m(y,2)))', ...
% 'm','x','y');
%
% % calculate the sorted index
% order = quicksort(x, i_cmp);
%
% % obtain the sorted matrix
% x_sorted = x(order,:);
%
sz = size(input);
while (sz(1) == 1) && (length(sz) > 1)
sz = sz(2:end);
end
index = cumsum(ones(1,sz(1)));
if isa(inl_fcn, 'function_handle')
index = quicksort_handle(input, inl_fcn, index, 1, sz(1));
else
index = quicksort_inline(input, inl_fcn, index, 1, sz(1));
end
%
% quicksort with an inline
%
function indx = quicksort_inline(inpt, cmp, indx, l, r)
% l and r remain unchanged. they are the left and right
% bounds of this sorting level
i = l + 1; % leftmost unknown
j = r; % rightmost unknown
p = l; % rightmost equal
if l >= r
return
end
% this while loop only runs while p == i - 1
while i <= j
switch cmp(inpt, indx(i), indx(l))
case 1
tmp = indx(j);
indx(j) = indx(i);
indx(i) = tmp;
j = j - 1;
case -1
i = i + 1;
break
otherwise
p = p + 1;
i = i + 1;
end
end
% this is actually the main while loop
% in this loop i > p + 1
while i <= j
switch cmp(inpt, indx(i), indx(l))
case 1
tmp = indx(j);
indx(j) = indx(i);
indx(i) = tmp;
j = j - 1;
case -1
i = i + 1;
otherwise
p = p + 1;
tmp = indx(p);
indx(p) = indx(i);
indx(i) = tmp;
i = i + 1;
end
end
% swap "less thans" with "equals"
indx(l:j) = [ indx((p + 1):j) indx(l:p) ];
indx = quicksort_inline(inpt, cmp, indx, l, l + j - p);
indx = quicksort_inline(inpt, cmp, indx, i, r);
return;
%
% quicksort with a function handle
%
function indx = quicksort_handle(inpt, cmp, indx, l, r)
% l and r remain unchanged. they are the left and right
% bounds of this sorting level
i = l + 1; % leftmost unknown
j = r; % rightmost unknown
p = l; % rightmost equal
if l >= r
return
end
% this while loop only runs while p == i - 1
while i <= j
switch feval(cmp, inpt, indx(i), indx(l))
case 1
tmp = indx(j);
indx(j) = indx(i);
indx(i) = tmp;
j = j - 1;
case -1
i = i + 1;
break
otherwise
p = p + 1;
i = i + 1;
end
end
% this is actually the main while loop
% in this loop i > p + 1
while i <= j
switch feval(cmp, inpt, indx(i), indx(l))
case 1
tmp = indx(j);
indx(j) = indx(i);
indx(i) = tmp;
j = j - 1;
case -1
i = i + 1;
otherwise
p = p + 1;
tmp = indx(p);
indx(p) = indx(i);
indx(i) = tmp;
i = i + 1;
end
end
% swap "less thans" with "equals"
indx(l:j) = [ indx((p + 1):j) indx(l:p) ];
indx = quicksort_handle(inpt, cmp, indx, l, l + j - p);
indx = quicksort_handle(inpt, cmp, indx, i, r);
return;