28、MATLAB 中的排序、索引与搜索

MATLAB 中的排序、索引与搜索

在数据处理和分析中,排序、索引和搜索是非常重要的操作。MATLAB 提供了丰富的函数和方法来实现这些操作,下面将详细介绍相关内容。

1. 排序操作

1.1 对结构体向量排序

可以使用自定义函数 general_pack_sort 对结构体向量按指定字段进行排序。例如,有如下结构体向量 packages
| Item | Cost | Price | Code |
| ---- | ---- | ---- | ---- |
| 587 | 11.11 | 33.33 | w |
| 123 | 19.99 | 39.95 | g |
| 456 | 5.99 | 49.99 | l |

cost 字段排序的代码如下:

pack_by_cost = general_pack_sort(packages,'cost');
printpackages(pack_by_cost)

排序后的结果为:
| Item | Cost | Price | Code |
| ---- | ---- | ---- | ---- |
| 456 | 5.99 | 49.99 | l |
| 587 | 11.11 | 33.33 | w |
| 123 | 19.99 | 39.95 | g |

若尝试按 profit 字段排序,会提示错误,因为该字段名不正确:

pack_by_profit = general_pack_sort(packages,'profit')

结果为:

Sorry, not a correct field name
pack_by_profit =
[]

1.2 字符串排序

1.2.1 使用 sort 函数排序

对于字符串矩阵, sort 函数按字符的 ASCII 码逐列排序。例如:

words = char('Hello', 'Howdy', 'Hi', 'Goodbye', 'Ciao');
sort(words)

结果显示空格字符在字符编码中排在字母之前:

ans =
Ce
Giad
Hildb
Hoolo
Howoyye

若要按行排序,需指定第二个维度:

sort(words,2)

结果表明空格在字母之前,大写字母在小写字母之前:

ans =
Hello
Hdowy
Hi
Gbdeooy
Caio
1.2.2 使用 sortrows 函数按字母顺序排序

sortrows 函数从左到右逐列检查字符串,确定字母顺序后将整个字符串放入相应行。例如:

sortrows(words)

结果为:

ans =
Ciao
Goodbye
Hello
Hi
Howdy

该函数也可用于数字矩阵排序,如:

mat = [5 7 2; 4 6 7; 3 4 1; 5 6 2];
sortrows(mat)

结果为:

ans =
3 4 1
4 6 7
5 6 2
5 7 2
1.2.3 对单元格数组排序

使用 sort 函数对单元格数组中的字符串排序,示例如下:

engcellnames = {'Chemical','Mechanical',...
    'Biomedical','Electrical', 'Industrial'};
sort(engcellnames)

结果为:

ans =
    'Biomedical'
    'Chemical'
    'Electrical'
    'Industrial'
    'Mechanical'

排序操作总结

排序对象 排序函数 示例代码
结构体向量 general_pack_sort pack_by_cost = general_pack_sort(packages,'cost');
字符串矩阵(逐列) sort sort(words)
字符串矩阵(按行) sort(words,2) sort(words,2)
字符串矩阵(按字母顺序) sortrows sortrows(words)
数字矩阵(按行) sortrows sortrows(mat)
单元格数组 sort sort(engcellnames)

2. 索引操作

索引是排序向量的一种替代方法,向量保持原始顺序,通过索引向量按所需顺序指向原始向量中的值。

2.1 简单向量索引示例

假设有一个考试成绩向量 grades

grades = [85 70 100 95 80 91];

按升序排列,最低分在第 2 个元素,次低分在第 5 个元素,索引向量 grade_index 给出了这个顺序:

grade_index = [2 5 1 6 4 3];

使用索引向量获取升序成绩:

grades(grade_index)

结果为:

ans =
70
80
85
91
95
100

2.2 自动创建索引向量

可以使用自定义函数 createind 自动创建升序索引向量,代码如下:

function indvec = createind(vec)
%This function creates index vector in ascending order
% Initialize the index vector
len = length(vec);
indvec = 1:len;
for i = 1:len-1
    low = i;
    for j=i+1:len
        % Compare values in the original vector
        if vec(indvec(j)) < vec(indvec(low))
            low = j;
        end
    end
    % Exchange elements in the index vector
    temp = indvec(i);
    indvec(i) = indvec(low);
    indvec(low) = temp;
end

使用示例:

clear grade_index;
grade_index = createind(grades);
grades(grade_index)

结果与手动创建索引向量相同。

2.3 结构体向量索引

当数据结构为结构体向量时,可能需要按不同字段顺序遍历向量。例如,对于之前的 packages 向量,可创建基于 cost price 的索引向量:
| | item_no | cost | price | code | cost_ind | price_ind |
| ---- | ---- | ---- | ---- | ---- | ---- | ---- |
| 1 | 123 | 19.99 | 39.95 | ‘g’ | 1 | 2 |
| 2 | 456 | 5.99 | 49.99 | ‘l’ | 2 | 3 |
| 3 | 587 | 11.11 | 33.33 | ‘w’ | 3 | 1 |

创建索引向量后,可使用自定义函数 printpackind 按指定顺序遍历 packages 向量:

function printpackind(packstruct, indvec)
% This function prints a table showing all
% values from a vector of packages structures
fprintf('Item # Cost Price Code \n')
no_packs = length(packstruct);
for i = 1:no_packs
    fprintf('%6d %6.2f %6.2f %3c\n', ...
        packstruct(indvec(i)).item_no, ...
        packstruct(indvec(i)).cost, ...
        packstruct(indvec(i)).price, ...
        packstruct(indvec(i)).code)
end

使用示例:

printpackind(packages,cost_ind)
printpackind(packages,price_ind)

索引操作流程

graph TD;
    A[定义原始向量] --> B[手动或自动创建索引向量];
    B --> C[使用索引向量访问原始向量元素];

3. 搜索操作

搜索是在列表或向量中查找特定值(键)的操作,这里介绍两种搜索算法:顺序搜索和二分搜索。

3.1 顺序搜索

顺序搜索从向量开头逐个元素遍历,查找键值。若找到,返回元素索引;若未找到,返回 0。以下是实现顺序搜索的函数:

function index = seqsearch(vec, key)
% Implements a sequential search through a
% vector looking for a key; returns the index
len = length(vec);
index = 0;
for i = 1:len
    if vec(i) == key
        index = i;
    end
end

使用示例:

values = [85 70 100 95 80 91];
key = 95;
seqsearch(values, key)
seqsearch(values, 77)

结果分别为 4 和 0。

该算法效率不高,可改进为使用 while 循环,找到键值或遍历完整个向量后停止:

function index = smartseqsearch(vec, key)
% Smart sequential search; searches a vector
% for a key but ends when it is found
% Returns the index or 0 if not found
len = length(vec);
index = 0;
i = 1;
while i < len && vec(i) ~= key
    i = i + 1;
end
if vec(i) == key
    index = i;
end

3.2 二分搜索

二分搜索要求向量已排序,其算法类似于在电话簿中查找姓名。查找键值时,先看中间元素:
- 若为键值,找到索引;
- 若不是,决定搜索前半部分还是后半部分,并调整搜索范围,重复此过程。

以下是二分搜索的实现函数:

function outind = binsearch(vec, key)
% This function implements a binary search
low = 1;
high = length(vec);
outind = -1;
while low <= high && outind == -1
    mid = floor((low + high)/2);
    if vec(mid) == key
        outind = mid;
    elseif key < vec(mid)
        high = mid - 1;
    else
        low = mid + 1;
    end
end

使用示例:

vec = randint(1,7, [1 30]);
svec = sort(vec);
binsearch(svec, 4)
binsearch(svec, 25)
binsearch(svec, 5)

二分搜索也可实现为递归函数:

function outind = recbinsearch(vec, key, low, high)
% Recursive binary search function
mid = floor((low + high)/2);
if low > high
    outind = -1;
elseif vec(mid) == key
    outind = mid;
elseif key < vec(mid)
    outind = recbinsearch(vec,key,low,mid-1);
else
    outind = recbinsearch(vec,key,mid+1,high);
end

使用示例:

recbinsearch(svec, 5,1,length(svec))
recbinsearch(svec, 25,1,length(svec))
recbinsearch(svec, 4,1,length(svec))

搜索操作总结

搜索算法 特点 适用场景 示例代码
顺序搜索 逐个元素遍历 未排序向量或向量较短 seqsearch(values, key)
智能顺序搜索 找到键值或遍历完停止 未排序向量 smartseqsearch(vec, key)
二分搜索 要求向量已排序,效率高 排序后的向量 binsearch(svec, key)
递归二分搜索 递归实现二分搜索 排序后的向量 recbinsearch(svec, key, low, high)

二分搜索流程

graph TD;
    A[初始化 low = 1, high = 向量长度] --> B[计算 mid = floor((low + high)/2)];
    B --> C{vec(mid) == key?};
    C -- 是 --> D[返回 mid];
    C -- 否 --> E{key < vec(mid)?};
    E -- 是 --> F[high = mid - 1];
    E -- 否 --> G[low = mid + 1];
    F --> B;
    G --> B;
    B --> H{low > high?};
    H -- 是 --> I[返回 -1];

常见陷阱与编程风格指南

常见陷阱

  • 忘记 max min 函数仅返回最大值或最小值首次出现的索引。
  • 未意识到数据集中存在异常值,可能会严重影响统计函数的结果。
  • 对结构体向量按字段排序时,忘记在排序算法中比较字段时需交换整个结构体。
  • 使用二分搜索前忘记对数据集进行排序。

编程风格指南

  • 在进行统计分析前,从大数据集中去除最大和最小数,以处理异常值问题。
  • 使用 sortrows 对矩阵中的字符串按字母顺序排序,对单元格数组使用 sort 函数。
  • 当需要按多个不同字段顺序遍历结构体向量时,创建基于这些字段的索引向量可能比多次排序结构体向量更高效。

练习

以下是一些相关练习,可帮助巩固所学知识:
1. 实验数据值存储在文件中,创建一个矩阵形式的随机值文件进行测试,编写脚本加载数据并确定文件中最大和最小数的差值。
2. 数据集的范围是最大值与最小值之差,数据文件 tensile.dat 存储了一些铝样品的拉伸强度,创建测试数据文件,读取拉伸强度并打印范围。
3. 编写函数 mymin ,接收任意数量的参数并返回最小值。
4. 游泳池的化学平衡对游泳者安全很重要,每天测量游泳池的 pH 值并存储在文件中,创建数据文件模拟这些测量,读取 pH 值并计算其均值和标准差。
5. 质量工程师正在测试一批 500 欧姆的电阻,文件 testresist.dat 存储了一些已测量电阻的值,创建数据文件,加载信息并计算和打印电阻的均值、中位数、众数和标准差,同时计算有多少电阻在 500 欧姆的 1% 范围内。
6. 编写函数 calcvals ,根据调用时使用的输出参数数量计算向量的最大值、最小值和均值。
7. 编写脚本创建两个包含 20 个随机整数的向量,一个范围从 1 到 5,另一个从 1 到 500,回答关于均值、中位数和标准差的预期问题,使用内置函数查找每个向量的最小值、最大值、均值、中位数、标准差和众数,并在子图中绘制直方图。
8. 编写函数返回向量中除最小值和最大值外的值的均值,假设向量中的值唯一,可使用内置 mean 函数,创建一个包含 10 个 0 到 50 之间随机整数的向量进行测试。
9. 编写函数 mymedian ,接收向量作为输入参数,对向量排序并返回中位数,可使用除 median 函数外的任何内置函数,不允许使用循环。
10. 若数据集中只有两个值,均值和中位数的差异是什么?
11. 学生错过一门课程的四次考试中的一次,教授决定使用其他三门考试成绩的平均值作为错过考试的成绩,若三门记录的成绩为 99、88 和 95,均值和中位数哪个对学生更有利?若成绩为 99、70 和 77 呢?
12. 当数据值有不同权重时,使用加权均值,编写函数接收两个向量作为输入参数:一个是数据值向量,一个是权重向量,并返回加权均值。
13. 生产设施生产的钉子直径应为 0.15 英寸,在五个不同时间测量了 10 个样本钉子的直径,将其存储在一个有五行、每行 10 个直径值的文件中,创建数据文件,编写脚本打印每组样本钉子的均值和标准差。
14. 变异系数用于比较均值差异较大的数据集,历史课程有两个不同的部分,其期末考试成绩存储在文件的两行中,创建数据文件,将数据读入向量,使用变异系数比较这两个部分的课程。
15. 编写函数 allparts ,读取两个工厂生产零件的零件编号列表,这些列表存储在数据文件 xyparts.dat qzparts.dat 中,函数将返回所有生产零件的排序向量(无重复)。
16. 集合函数可用于字符串单元格数组,创建两个单元格数组存储两个学生选修的课程编号,使用集合函数确定学生共同选修的课程。
17. 向量 v 应存储唯一的随机数,使用集合函数确定是否如此。
18. 编写函数 mydsort ,使用循环(不使用内置 sort 函数)对向量按降序排序。
19. 在产品设计中,评估产品不同特征对潜在客户的重要性很有用,一种方法是进行调查,询问人们某个特征是否重要,统计回答“是”的潜在客户数量,创建数据文件,使用子图显示按问题排列的柱状图和帕累托图。
20. DNA 是一种双链螺旋聚合物,以核苷酸碱基模式包含基本遗传信息,构建单元格数组存储一些 DNA 序列字符串并按字母顺序排序,构建矩阵存储相同长度的 DNA 序列并按字母顺序排序。
21. 编写函数 matsort 对矩阵中的所有值进行排序(决定排序后的值按行还是按列存储),接收一个矩阵参数并返回排序后的矩阵,不使用循环,使用内置 sort reshape 函数。
22. 编写函数接收两个参数:一个向量和一个字符(’a’ 或 ‘d’),按指定字符的顺序(升序或降序)对向量进行排序。
23. 编写函数接收一个向量并返回两个索引向量:一个用于升序,一个用于降序,编写脚本调用该函数,使用索引向量按升序和降序打印原始向量,检查函数的正确性。
24. 编写函数 myfind ,在向量中搜索键值并返回所有出现该键值的索引,类似于内置 find 函数,接收两个参数:向量和键值,返回索引向量(若未找到键值,返回空向量 [])。

通过以上内容,我们详细介绍了 MATLAB 中的排序、索引和搜索操作,以及相关的常见陷阱和编程风格指南,并提供了丰富的练习帮助大家巩固知识。希望这些内容对大家在数据处理和分析方面有所帮助。

4. 练习解答示例

4.1 实验数据最大最小值差值

% 创建随机矩阵数据文件
data = rand(10, 10); % 示例 10x10 矩阵
dlmwrite('test_data.txt', data);

% 加载数据
loaded_data = dlmread('test_data.txt');

% 计算最大最小值差值
max_val = max(loaded_data(:));
min_val = min(loaded_data(:));
diff_val = max_val - min_val;
disp(['最大和最小数的差值为: ', num2str(diff_val)]);

4.2 拉伸强度范围计算

% 创建测试数据文件
tensile_strength = rand(1, 20) * 100; % 示例 20 个拉伸强度值
dlmwrite('tensile.dat', tensile_strength);

% 读取数据
tensile_data = dlmread('tensile.dat');

% 计算范围
range_val = max(tensile_data) - min(tensile_data);
disp(['拉伸强度的范围为: ', num2str(range_val)]);

4.3 自定义最小值函数

function min_val = mymin(varargin)
    min_val = varargin{1};
    for i = 2:nargin
        if varargin{i} < min_val
            min_val = varargin{i};
        end
    end
end

使用示例:

result = mymin(3, 6, 77, 2, 99);
disp(['最小值为: ', num2str(result)]);

4.4 游泳池 pH 值统计

% 创建数据文件
pH_values = 7 + rand(1, 30); % 示例 30 个 pH 值
dlmwrite('pH_data.txt', pH_values);

% 读取数据
pH_data = dlmread('pH_data.txt');

% 计算均值和标准差
mean_pH = mean(pH_data);
std_pH = std(pH_data);
disp(['pH 值的均值为: ', num2str(mean_pH)]);
disp(['pH 值的标准差为: ', num2str(std_pH)]);

4.5 电阻统计分析

% 创建数据文件
resistances = 500 + 5 * randn(1, 50); % 示例 50 个电阻值
dlmwrite('testresist.dat', resistances);

% 加载数据
resistance_data = dlmread('testresist.dat');

% 计算统计量
mean_resistance = mean(resistance_data);
median_resistance = median(resistance_data);
mode_resistance = mode(resistance_data);
std_resistance = std(resistance_data);

% 计算在 1% 范围内的电阻数量
within_range = sum(abs(resistance_data - 500) <= 5);

disp(['电阻的均值为: ', num2str(mean_resistance)]);
disp(['电阻的中位数为: ', num2str(median_resistance)]);
disp(['电阻的众数为: ', num2str(mode_resistance)]);
disp(['电阻的标准差为: ', num2str(std_resistance)]);
disp(['在 1% 范围内的电阻数量为: ', num2str(within_range)]);

4.6 自定义统计函数

function [mmax, mmin, mmean] = calcvals(vec)
    if nargout == 3
        mmax = max(vec);
        mmin = min(vec);
        mmean = mean(vec);
    elseif nargout == 2
        mmax = max(vec);
        mmin = min(vec);
    elseif nargout == 1
        mmax = max(vec);
    end
end

使用示例:

vec = [4 9 5 6 2 7 16 0];
[mmax, mmin, mmean] = calcvals(vec);
disp(['最大值为: ', num2str(mmax)]);
disp(['最小值为: ', num2str(mmin)]);
disp(['均值为: ', num2str(mmean)]);

4.7 随机向量统计分析

% 创建向量
vec1 = randi([1, 5], 1, 20);
vec2 = randi([1, 500], 1, 20);

% 分析预期
disp('对于 vec1,由于取值范围小,均值和中位数可能接近;对于 vec2,取值范围大,均值和中位数可能差异较大。');
disp('vec1 的标准差应小于 vec2 的标准差。');

% 计算统计量
min_vec1 = min(vec1);
max_vec1 = max(vec1);
mean_vec1 = mean(vec1);
median_vec1 = median(vec1);
std_vec1 = std(vec1);
mode_vec1 = mode(vec1);

min_vec2 = min(vec2);
max_vec2 = max(vec2);
mean_vec2 = mean(vec2);
median_vec2 = median(vec2);
std_vec2 = std(vec2);
mode_vec2 = mode(vec2);

% 打印结果
disp(['vec1 的最小值: ', num2str(min_vec1)]);
disp(['vec1 的最大值: ', num2str(max_vec1)]);
disp(['vec1 的均值: ', num2str(mean_vec1)]);
disp(['vec1 的中位数: ', num2str(median_vec1)]);
disp(['vec1 的标准差: ', num2str(std_vec1)]);
disp(['vec1 的众数: ', num2str(mode_vec1)]);

disp(['vec2 的最小值: ', num2str(min_vec2)]);
disp(['vec2 的最大值: ', num2str(max_vec2)]);
disp(['vec2 的均值: ', num2str(mean_vec2)]);
disp(['vec2 的中位数: ', num2str(median_vec2)]);
disp(['vec2 的标准差: ', num2str(std_vec2)]);
disp(['vec2 的众数: ', num2str(mode_vec2)]);

% 绘制直方图
subplot(2, 1, 1);
histogram(vec1);
title('vec1 直方图');
subplot(2, 1, 2);
histogram(vec2);
title('vec2 直方图');

4.8 去除最值后的均值

function mean_val = remove_max_min_mean(vec)
    sorted_vec = sort(vec);
    new_vec = sorted_vec(2:end-1);
    mean_val = mean(new_vec);
end

使用示例:

test_vec = randi([0, 50], 1, 10);
result_mean = remove_max_min_mean(test_vec);
disp(['去除最值后的均值为: ', num2str(result_mean)]);

4.9 自定义中位数函数

function median_val = mymedian(vec)
    sorted_vec = sort(vec);
    len = length(sorted_vec);
    if mod(len, 2) == 1
        median_val = sorted_vec((len + 1) / 2);
    else
        median_val = (sorted_vec(len / 2) + sorted_vec(len / 2 + 1)) / 2;
    end
end

使用示例:

test_vec1 = 1:5;
test_vec2 = 1:6;
test_vec3 = [5 9 2];
test_vec4 = [5 9 2 4];

disp(['test_vec1 的中位数为: ', num2str(mymedian(test_vec1))]);
disp(['test_vec2 的中位数为: ', num2str(mymedian(test_vec2))]);
disp(['test_vec3 的中位数为: ', num2str(mymedian(test_vec3))]);
disp(['test_vec4 的中位数为: ', num2str(mymedian(test_vec4))]);

4.10 两个值的均值和中位数差异

当数据集中只有两个值 $a$ 和 $b$ 时,均值为 $\frac{a + b}{2}$,中位数也为 $\frac{a + b}{2}$,所以均值和中位数相等。

4.11 学生成绩选择

grades1 = [99, 88, 95];
grades2 = [99, 70, 77];

mean_grades1 = mean(grades1);
median_grades1 = median(grades1);

mean_grades2 = mean(grades2);
median_grades2 = median(grades2);

disp(['对于成绩 [99, 88, 95],均值为: ', num2str(mean_grades1), ',中位数为: ', num2str(median_grades1)]);
disp(['对于成绩 [99, 70, 77],均值为: ', num2str(mean_grades2), ',中位数为: ', num2str(median_grades2)]);
disp('对于成绩 [99, 88, 95],均值和中位数一样好;对于成绩 [99, 70, 77],中位数对学生更有利。');

4.12 加权均值计算

function weighted_mean_val = weighted_mean(data, weights)
    weighted_sum = sum(data .* weights);
    total_weight = sum(weights);
    weighted_mean_val = weighted_sum / total_weight;
end

使用示例:

quiz_scores = [95, 70, 80];
exam_scores = [85, 90];
data = [quiz_scores, exam_scores];
weights = [ones(1, length(quiz_scores)), 2 * ones(1, length(exam_scores))];

result = weighted_mean(data, weights);
disp(['加权均值为: ', num2str(result)]);

4.13 钉子直径统计

% 创建数据文件
nail_diameters = 0.15 + 0.01 * randn(5, 10);
dlmwrite('nail_diameters.txt', nail_diameters);

% 读取数据
nail_data = dlmread('nail_diameters.txt');

% 计算每组的均值和标准差
for i = 1:size(nail_data, 1)
    mean_val = mean(nail_data(i, :));
    std_val = std(nail_data(i, :));
    disp(['第 ', num2str(i), ' 组的均值为: ', num2str(mean_val), ',标准差为: ', num2str(std_val)]);
end

4.14 课程成绩变异系数比较

% 创建数据文件
section1_scores = [99 100 95 92 98 89 72 95 100 100];
section2_scores = [83 85 77 62 68 84 91 59 60];
dlmwrite('course_scores.txt', [section1_scores; section2_scores]);

% 读取数据
scores = dlmread('course_scores.txt');

% 计算变异系数
cv_section1 = std(scores(1, :)) / mean(scores(1, :)) * 100;
cv_section2 = std(scores(2, :)) / mean(scores(2, :)) * 100;

disp(['第 1 部分的变异系数为: ', num2str(cv_section1), '%']);
disp(['第 2 部分的变异系数为: ', num2str(cv_section2), '%']);
disp('变异系数越小,数据越稳定。');

4.15 合并零件编号

function partslist = allparts
    xyparts = dlmread('xyparts.dat');
    qzparts = dlmread('qzparts.dat');
    all_parts = unique([xyparts, qzparts]);
    partslist = sort(all_parts);
end

使用示例:

result_parts = allparts;
disp(['所有零件编号为: ', num2str(result_parts)]);

4.16 学生共同课程

s1 = {'EC 101', 'CH 100', 'MA 115'};
s2 = {'CH 100', 'MA 112', 'BI 101'};

common_courses = intersect(s1, s2);
disp('学生共同选修的课程为:');
disp(common_courses);

4.17 检查向量唯一性

v = randi([1, 10], 1, 10);
is_unique = length(unique(v)) == length(v);
disp(['向量 v 是否唯一: ', num2str(is_unique)]);

4.18 自定义降序排序

function sorted_vec = mydsort(vec)
    len = length(vec);
    for i = 1:len - 1
        for j = i + 1:len
            if vec(j) > vec(i)
                temp = vec(i);
                vec(i) = vec(j);
                vec(j) = temp;
            end
        end
    end
    sorted_vec = vec;
end

使用示例:

test_vec = randi([1, 20], 1, 10);
sorted_result = mydsort(test_vec);
disp(['降序排序后的向量为: ', num2str(sorted_result)]);

4.19 产品特征调查

% 创建数据文件
feature_responses = randi([1, 200], 1, 10);
dlmwrite('feature_survey.txt', feature_responses);

% 读取数据
responses = dlmread('feature_survey.txt');

% 绘制柱状图和帕累托图
subplot(1, 2, 1);
bar(1:10, responses);
title('按问题排列的柱状图');
xlabel('问题编号');
ylabel('回答 Yes 的人数');

sorted_responses = sort(responses, 'descend');
subplot(1, 2, 2);
bar(1:10, sorted_responses);
title('帕累托图');
xlabel('问题编号');
ylabel('回答 Yes 的人数');

4.20 DNA 序列排序

% 单元格数组存储 DNA 序列
dna_cell = {'TACGGCAT', 'ACCGTAC'};
sorted_dna_cell = sort(dna_cell);
disp('单元格数组中 DNA 序列按字母顺序排序:');
disp(sorted_dna_cell);

% 矩阵存储 DNA 序列
dna_matrix = char('TACGGCAT', 'ACCGTAC');
sorted_dna_matrix = sortrows(dna_matrix);
disp('矩阵中 DNA 序列按字母顺序排序:');
disp(sorted_dna_matrix);

4.21 矩阵排序

function sorted_mat = matsort(mat)
    vec = mat(:);
    sorted_vec = sort(vec);
    sorted_mat = reshape(sorted_vec, size(mat));
end

使用示例:

test_mat = [4 5 2; 1 3 6; 7 8 4; 9 1 5];
sorted_result = matsort(test_mat);
disp('排序后的矩阵为:');
disp(sorted_result);

4.22 按指定顺序排序

function sorted_vec = custom_sort(vec, order)
    if strcmp(order, 'a')
        sorted_vec = sort(vec);
    elseif strcmp(order, 'd')
        sorted_vec = sort(vec, 'descend');
    end
end

使用示例:

test_vec = randi([1, 10], 1, 5);
ascending_vec = custom_sort(test_vec, 'a');
descending_vec = custom_sort(test_vec, 'd');
disp(['升序排序后的向量为: ', num2str(ascending_vec)]);
disp(['降序排序后的向量为: ', num2str(descending_vec)]);

4.23 升序降序索引向量

function [asc_ind, desc_ind] = get_index_vectors(vec)
    asc_ind = createind(vec);
    desc_vec = -vec;
    desc_ind = createind(desc_vec);
end

使用示例:

test_vec = randi([1, 10], 1, 5);
[asc_index, desc_index] = get_index_vectors(test_vec);
disp(['升序索引向量: ', num2str(asc_index)]);
disp(['降序索引向量: ', num2str(desc_index)]);
disp(['升序排列的向量: ', num2str(test_vec(asc_index))]);
disp(['降序排列的向量: ', num2str(test_vec(desc_index))]);

4.24 自定义查找函数

function indices = myfind(vec, key)
    indices = [];
    for i = 1:length(vec)
        if vec(i) == key
            indices = [indices, i];
        end
    end
end

使用示例:

test_vec = [1, 2, 3, 2, 4, 2];
key = 2;
result_indices = myfind(test_vec, key);
disp(['键值 ', num2str(key), ' 出现的索引为: ', num2str(result_indices)]);

通过以上练习解答示例,我们可以更深入地理解和掌握 MATLAB 中排序、索引和搜索操作的实际应用。在实际的数据处理和分析中,合理运用这些操作可以提高工作效率和数据处理的准确性。希望大家通过不断练习,熟练掌握这些技巧,为数据分析和科学研究提供有力支持。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值