Matlab中的搜索和排序教程

270 阅读8分钟

Matlab中的搜索和排序

搜索是指在一个大的数据集中找到一个给定的对象或数据的过程。而排序则是将数据按照特定的要求顺序排列。

这些算法的常见应用是在数据库和其他计算机应用中。计算机数据库是储存所有计算机数据的地方。在没有搜索和排序算法的情况下,在计算机中查找数据很可能需要花费大量时间。这些算法简化了这一过程,最大限度地减少了搜索和排序的时间。

简介

你将使用的算法类型将取决于复杂性、内存使用和适应性。算法的内存使用和适应性依赖于输入数据。因此,计算中的搜索和排序算法的效果就是内存的使用。

一些算法使用大量的内存空间,这影响了计算机的整体性能。搜索和排序有多种应用,但主要的应用是在一个给定的矢量中定位与目标相似的数据。

前提条件

搜索

搜索的主要目标是数据的唯一性。例如,如果你访问一家银行,检索你的账户细节是通过搜索算法实现的。有两种类型的搜索算法。

这些是。

  1. 序列式
  2. 二进制搜索

1.顺序搜索

它也被称为线性搜索。它是一种在一个列表中寻找元素的方法。在这里,目标与整个向量空间进行比较,或者在与目标相似的变量中停止。矢量空间是构成列表的数据。

首先,我们应该在这个向量内确定目标值。如果我们找到一个类似的变量,我们就给出它的索引作为输出,如果我们没有找到它,我们就提供一个不可能的索引作为输出。

这个不可能的索引可以是-1这样的值,以表明该算法无法找到目标。下面是一个在matlab中实现搜索的示例代码。

function index = sequential_search(vector, target, first, last)
found = false;                %Assumming target not found
for n = first:last
if target == vector(n)
found = true;                  % If target is found then found is true
break;                         % Stop the search when found is true
end
end
index = n;                      % index of our target
if ~found
index = -1;                      % If not found, the index is -1
end

在我们的函数中,我们有四个输入。第一个输入是矢量(n),我们在其中定位我们的目标值。第二个输入是我们试图找到的目标。第三和第四个是我们向量的第一个和最后一个值。

在大多数情况下,我们的第一个值总是1,而最后一个值是向量的整个长度。但如果你想搜索到一个给定的极限,你就在第一个和最后一个值中输入你的范围。我们还可以使用内部标志found,true, 和false 函数来确定我们是否找到了我们的目标。

例子

我们有一个向量M = [ 3 2 6 34 22 98 77 45 99 12] ,我们想找到34。

我们将调用我们的函数,如下图所示。

sequential_search(M, 34, 1, 10)

当我们执行这个函数时,我们得到的输出是我们的目标值的索引,即4。

index for the target

对于大量的数据,顺序搜索需要时间来定位一个给定的数据。这是因为它将所有的数据与目标值进行比较,以获得一个类似的变量。为了更快地搜索,你需要首先对数据进行排序,但顺序搜索却不是这样的。这意味着它是唯一用于搜索无排序列表的算法。

2.二进制搜索

在列表被排序的情况下,那么搜索就比较容易了。这里应用的搜索方法是二进制搜索。这种算法不断地将你的列表分成猜测的部分,直到它将其缩小为一个。例如,你想在0到100的范围内搜索。假设你想用28作为数字。

如果我告诉你,我们要搜索的数字大于这个数字,你可能会想到80这样的数字。如果我告诉你,我们的数字小于80,你就知道目标值在29和79之间。这就是二进制搜索划分数据的方式,直到找到目标。

二进制搜索有两种实现方式,分别是。

  1. 二进制搜索的递归实现
  2. 二进制搜索的迭代实现

二进制搜索的递归实现

在二进制搜索的递归实现中,它是一种我们都可能熟悉的搜索。例如,在你的手机上寻找一个联系人。你已经知道你可能需要的联系人可能出现在哪个页面。

当你看了页面上的一个名字,那么你已经知道目标名字是否在那里。继续下去,你会达到一个点,即你不按顺序看联系人,而是进行扫描。当你应用这个过程时,你是在应用你的二进制搜索的递归近似值。

二进制搜索的函数是。

function index = binary_search_recursive(vector,target,first,last)
mid = fix( (first + last)/2 );

上面的代码是在寻找中间变量时使用的。如果中间变量是一个十进制值,我们使用fix 函数将小数修正为整数或数值。

if ~(first <= last) % In case first and last values are out of order
index = -1;          % Returns -1 to show the value is not in the list.

如果目标值不在范围内,那么索引将被返回为-1。

elseif target == vector(mid)
index = mid; % found it!

中间的元素会与目标值进行比较。如果它们相等,那么搜索成功并返回输出。

elseif target < vector(mid)
index = binary_search_recursive(vector,target,first, mid-1);

如果目标值小于中间元素,则剔除中间元素和它后面的所有值。因此,在中间元素之前的范围内进行搜索。

binary_search_recursive(vector, target, first, mid-1) 是用来调用我们的函数来搜索中间元素之前的元素范围的,否则目标大于,它就搜索中间元素之后的值。

else
index = binary_search_recursive(vector,target,mid+1, last);
end

我们调用我们的函数来搜索中间元素之后的值,其结果在输出中给出。这种方法被称为二进制。这是因为它不断地将列表分成两部分。因此,例如,如果你想在1-100的范围内搜索一个值,搜索范围将是100,50,25,12,6,3,1。

这意味着我们将有七次调用我们的函数来寻找目标。如果我们看一下这个,我们就会发现二进制搜索与顺序搜索相比,只进行了不到40次的比较就达到了目标,如果目标不在范围内的话,顺序搜索可能需要100次比较。

例子

我们给了向量A=[2 13 17 22 29 43 64 73 82 89 99],我们想用我们的函数来定位89。

binary_search_recursive(A, 89, 1, length(A))
binary_search_recursive(A, 88, 1, length(A))  %unavailable 

output for target and out of range

在重复值中,该函数给出了它第一次定位的值的索引,这与顺序搜索不同,它找到了列表中的第一个变量。

二进制搜索的迭代实现

在二进制搜索的迭代实现中,第一个和最后一个变量分别被设定为范围内的第一个和最后一个索引。

因此,将列表分成更小的部分涉及到每次改变第一个或最后一个变量。这可以通过将第一个变量移到最后,将最后一个变量移到第一个来实现。

它是通过使用while 循环实现的。当第一个数值大于最后一个数值时,while 循环停止,这意味着定位目标不成功。

function index = binary_search_iterative(vector,target,first,last)
found = false;
while first <= last && ~found
mid = fix( (first + last) /2 );
if target < vector(mid)
last = mid - 1;                   %moving towards the beginning
elseif target > vector(mid)
first = mid + 1 ;                 %moving towards the end
else
found = true;
end
end
if found
index = mid;                      %Return the index if found
else
index = -1;                       % Return -1 if not found
end

如果我们有一个向量A=[2 13 17 22 29 43 64 73 82 89 99],我们想定位73,这个函数的调用应该是。

binary_search_iterative(A, 73, 1, length(A))

输出将是。

index of 73

排序

排序是将一个列表按特定顺序排列。使用的算法定义了如何进行排序。排序的重要性在于它将搜索提升到了一个很高的水平。

正如我们所看到的,二进制搜索比顺序搜索的优势在于,二进制搜索可以搜索排序后的列表。

排序的另一个好处是它以更可读的格式表示数据。

一般来说,我们有三种类型的排序:选择排序、快速排序和合并排序。

我们将只看quicksort和merge sort。

快速排序

这是最有效的排序类型,也非常容易理解。一般来说,这种quicksort将数据分为三部分:v (1), smaller, 和 remainder。v (1) 是列表中的第一个值。例如,如果M = [ 3 2 6 34 22 98 77 45 99 12] 是我们的向量,那么我们的v(1)就是3。

Smaller是由所有小于v(1)的向量组成的列表,例如,在我们的列表中,小于v(1)的值是2.而余数由向量(v)中所有剩余的值组成。在把你的向量分成三份后,现在这三部分被排序并汇集在一起。

它对较小的列表进行排序,输出结果被分配到left ,它对剩余部分进行排序,输出结果被称为right 。所以在调用我们的函数时,我们使用了leftright

为了将我们的向量分成几部分,我们使用下面的代码。

function v = quicksort(v) 
if length(v)<=1, return, end
Now, we want to produce less than v(1) elements and the output assigned to smaller. 
less = v<v(1);
smaller = v(less);

我们现在要创建余数列表。逻辑保持不变,但我们用~less 替换less ,表示not less ,并产生大于v (1)的值。

remainder(2:end) 这段代码是为了从列表中删除v (1)。然后它对较小的和剩余的列表进行快速排序。

remainder = v(~less);
remainder = remainder(2:end);

然后我们对排序后的列表进行相应的分配。排序后的小列表被分配到left ,排序后的剩余部分被分配到right

left = quicksort(smaller);
right = quicksort(remainder);
The algorithm now brings the three lists together to form the final sorted list.
v = [left, v(1), right]

例子

给定向量M = [ 3 2 6 34 22 98 77 45 99 12],使用quicksort对这个向量进行排序。

要做到这一点,我们执行下面的命令。

quicksort(M)

输出结果将是。

output

合并排序

这种算法比quicksort更好。Quicksort将数据分为三份,但如果你敏锐地看一下,在这个列表中并没有真正做什么。

这使得它没有任何重要性和用途。在这种情况下,合并排序将列表分为两个相等的部分,分别对这两部分进行排序,然后合并这两个列表。

合并排序的函数是。

function v = merge_sort(v)
N = length(v);
if N == 1, return; % already sorted
else
mid = fix(N/2);              %Divides the vector into two
v1 = merge_sort(v(1:mid));    %Elements from the first to the mid are sorted
v2 = merge_sort(v(mid+1:end)); %Elements from the mid to the last are sorted
v = merge_sorted_lists(v1,v2);  %The two lists are merged
end

结论

搜索和排序是各种活动中的基本算法。它们使工作变得简单,并简化了对大量数据的处理。

Matlab为实现这些算法提供了一个合适的环境。它有内置的功能,可以防止代码过于庞大,但又简单易懂。