算法设计与分析 实验一 排序算法性能分析(下)

简介: 算法设计与分析 实验一 排序算法性能分析(下)

(三)实验算法源码分析


详细的完整代码在附件中。

现对代码结构及实现过程进行如下解释:

1、L1~L9:

进行头文件声明


86dac256857e4fd6b4c9093e76a9484a.png


2、L11~L242:

定义各个排序函数,每个函数的实现过程中均包含详细的注释。


3c767dae87e34ceb82a120bbbea9c1df.png


3、L261~L558:

主函数:

①使用输出流创建文件,将每次程序运行的结果存入details.txt和result.txt中


4d017bda7bea4efa99bffb82ad8600fc.png


②对于每个算法,利用循环将数据量级从101~106进行测试,每次测试时,均生成20组数据,计算时间后将结果再存会result.txt和details.txt文件中。


四、实验结论或体会


①同样问题下不同的数量级有不同的处理方法并应选择不同的算法。

例如对101103 这种小数据的排序可以选择基数排序与合并排序外的六种排序方式。而对数据量大于104

的数据应该选择快速排序,合并排序,基数排序,希尔排序或堆排序。对于数据量巨大例如1012

的数据则应该选择计数排序,并应该考虑内存外存的数据搬运问题。


②既定算法是对某种普遍情况的处理方式,可能存在极端情况。

例如快速排序,当数据大小大致成二分分布时,有很好的性能,但当数据恰好倒序或恰好正序时,则性能很差。因此对于特殊情况需要选择特定算法进行处理。

③不能忽略对现有算法的优化

例如冒泡排序和选择排序,在算法进行中,存在冗余操作,即存在可优化的空间。对算法进行优化可以在算法本质不变的情况下一定程度上提高算法的效率。

④实践是检验算法的唯一标准,应避免“想当然”

例如两种“可行”的冒泡排序优化算法,从理论上都似乎可行,但实际运行起来,一种算法并不能提高运行效率反而降低了效率。这给我的启示是对于算法的学习中,一定要使用数据对算法进行实践,避免理论上的想当然。


五、思考


在本次实验过程中,我也发现了一些问题如下:


1. 冒泡排序算法优化

 传统冒泡排序算法中,排序完成的结束标准为所有循环全部循环结束。在实际算法运行中,会发现,在某次排序之后,部分序列变为有序,此时这部分序列不需进行冒泡排序。基于此,提出如下两个优化算法:

①减少无效循环次数

 不难发现在实际运行中,冒泡排序算法截止的标志是全部循环运行结束,因此可能存在在循环结束前,序列已经有序,但仍需进行循环,此时将造成时间浪费。可以通过定义标志变量判断冒泡的一趟是否进行交换,如果未进行交换则序列已经有序,break出循环减少无效循环。基于这个想法,编写代码并测试:

aefbfdc2c3174c50a8ea2d9bfee1a145.png

 从上表中可以发现,“优化”过的算法时间不仅没有减少,反而增加了。可能是因为算法几乎要全部循环结束才能完成排序,设置标志变量减少的循环次数不多。而且对标志变量赋值判断消耗的时间大于设置标志变量减少的循环消耗时间。因此不能提高算法效率!


②提高有效循环效率

 假如有一个长度为50的数组,在一趟交换后,最后发生交换的位置是10,那么这个位置之后的40个数必定已经有序了,记录下这位置,下一趟交换只要从数组头部到这个位置就可以了

基于这个想法,编写代码并测试

0692af8dc7444be79ad3d1aabe976dc6.png

可以看出,冒泡排序的时间消耗略微缩短了,算法得到了优化。

2.选择排序算法优化

  在正常的选择排序中,每次都需要对所有元素进行比较但仅获得最大/最小值,不妨在选择排序过程中,每次获得最大值和最小值,从而将选择次数缩短一半。

  基于此想法,编写代码并测试

cae788e07ad446a7ac4dddd620c6d55a.png

可以看出,选择排序的时间消耗明显缩短,大致节省了20%的时间,算法得到了优化。


3.(思考题)现在有1万亿的数据,请选择合适的排序算法与数据结构,在有限的时间内完成进行排序。


一万亿数据进行排序即对1012个整数进行排序。一个长整形占4个字节。则1012

个整数占4 × 1012≈4TB。如此巨大的数据量不可能一次放到内存中。因此需要将数据存放在外存中,并在内存外存中搬运数据完成数据的排序处理。

此时,一般的排序方法将由于无法使用,经过查阅资料后,我选择了一种非比较算法进行排序——计数排序。

(1)计数排序介绍与原理

计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为O ( n + k ) Ο(n+k)O(n+k)(其中k是整数的范围),快于任何比较排序算法。

算法具体实现如下:

①开辟一新数组,用来作为桶存每个元素出现的频率

②遍历待排序序列,将每个元素放入对应的桶中(频率值加一)

③遍历频率数组,并将每个元素存回原序列。

下面以排序2,3,8,4,6,1,3,9,4,7这10个数为例

20210601222644356.png

(2)计数排序伪代码

COUNTSORT(A):
    memset(C,sizeof(C),0);       //C数组置零    
for i=1 to n do    
    C[A[i]]++;               //统计输入数组中相同元素的个数    
for i=2 to k do    
    C[i] = C[i]+C[i-1];       //C[i]表示输入数组中小于或者等于i的元素个数    
for i=n downto 1 do    
    B[C[A[i]]] = A[i];       //把每一个A[i]放到输出数组中相应位置上    
    C[A[i]]--;             //如果有几个相同元素时,当然不能放在同一个位置了。

(3)计数排序在相对小数量级下的测试(单位ms)

通过随机数生成器生成不同测试数据,分别使用计数排序和通过实验得出对于大数据最高效的基数排序进行排序并比较时间。

d386371f29ae4fc6862c11b46fbbd8c3.png

可以看出,计数排序的时间消耗比目前最快的算法仍要快出很多。


(4)具体排序1012数据的步骤

①利用文件流创建若干个空文件,用来作为桶存各个数字出现频率。

②利用文件流,从外存中读入数字。并放入桶文件的对应位置。

③清空原数据源文件,并遍历桶文件将对应数字存入数据源文件中。


(5)时间消耗预计

由于计数排序的时间复杂度为O ( n + k ) (其中k是整数的范围)。则当排序1012个数字时,大约需要17 h


六、样例代码


//Code by:DongYunhao  2019284073
#include <algorithm>
#include <cmath>
#include <ctime>
#include <fstream>
#include <iostream>
#include <random>
#include <windows.h>
using namespace std;
堆排序
void minHeapDown(int a[], int start, int end) {
    int current = start;        // 当前(current)节点的位置
    int left = 2 * current + 1; // 为左(left)孩子的位置
    int tmp = a[current];       // 当前(current)节点的值
    for (; left <= end; current = left, left = 2 * left + 1) {
        // "left"是左孩子,"left+1"是右孩子
        if (left < end && a[left] > a[left + 1])
            left++; // 左右两孩子中选择较小者
        if (tmp <= a[left])
            break; // 调整结束
        else       // 交换值
        {
            a[current] = a[left];
            a[left] = tmp;
        }
    }
}
//堆排序(降序):交换数据,将a[1]和a[n]交换,使a[n]是a[1...n]中的最小值;然后将a[1...n-1]重新调整为最小堆。
void Heap_Sort_Desc(int a[], int n) {
    int i, tmp;
    for (i = n / 2 - 1; i >= 0; i--) // 从(n/2-1) --> 0逐次遍历。遍历之后,得到的数组实际上是一个(最小)二叉堆。
        minHeapDown(a, i, n - 1);
    //交换数据
    for (i = n - 1; i > 0; i--) {
        // 交换a[0]和a[i]。交换后,a[i]是a[0...i]中最小的。
        tmp = a[0];
        a[0] = a[i];
        a[i] = tmp;
        // 调整a[0...i-1],使得a[0...i-1]仍然是一个最小堆。
        minHeapDown(a, 0, i - 1);
    }
}
希尔排序
void Shell_Sort(int a[], int n) {
    int i, j, gap;
    // gap为步长,每次减为原来的一半。
    for (gap = n / 2; gap > 0; gap /= 2) {
        // 共gap个组,对每一组都执行直接插入排序
        for (i = 0; i < gap; i++) {
            for (j = i + gap; j < n; j += gap) {
                // 如果a[j] < a[j-gap],则寻找a[j]位置,并将后面数据的位置都后移。
                if (a[j] < a[j - gap]) {
                    int tmp = a[j];
                    int k = j - gap;
                    while (k >= 0 && a[k] > tmp) {
                        a[k + gap] = a[k];
                        k -= gap;
                    }
                    a[k + gap] = tmp;
                }
            }
        }
    }
}
基数排序
int maxbit(int a[], int n) {
    int d = 1; //保存最大的位数
    int p = 10;
    for (int i = 0; i < n; i++) {
        while (a[i] >= p) {
            p *= 10;
            d++;
        }
    }
    return d;
}
void Radix_Sort(int a[], int n) {
    int d = maxbit(a, n);
    int *tmp = new int[n]; //int tmp[n]错误定义,数组长度必须是整数常量或整数符号常量,想要用变量设置大小,必须用动态分配
    int count[10];         //计数器
    int i, j, k;
    int radix = 1;
    for (i = 1; i <= d; i++) //进行d次排序
    {
        for (j = 0; j < 10; j++)
            count[j] = 0; //每次分配前清空计数器
        for (j = 0; j < n; j++) {
            k = (a[j] / radix) % 10; //统计每个桶中的记录数
            count[k]++;
        }
        for (j = 1; j < 10; j++)
            count[j] = count[j - 1] + count[j]; //这时count里的值表示在tmp中的位置(减一为tmp里的存储下标)
        for (j = n - 1; j >= 0; j--)            //将所有桶中记录依次收集到tmp中
        {
            k = (a[j] / radix) % 10;
            tmp[count[k] - 1] = a[j];
            count[k]--; //用于一个桶中有多个数,减一为桶中前一个数在tmp里的位置
        }
        for (j = 0; j < n; j++) //将临时数组的内容复制到data中
            a[j] = tmp[j];
        radix = radix * 10;
    }
    delete[] tmp;
}
快速排序
int quickSortPartition(int s[], int l, int r) {
    //Swap(s[l], s[(l + r) / 2]); //若以中间数为基准,则先将中间的这个数和第一个数交换即可
    int i = l, j = r, x = s[l]; //将最左元素记录到x中
    while (i < j) {
        // 从右向左找第一个<x的数
        // 无需考虑下标越界
        while (i < j && s[j] >= x)
            j--;
        if (i < j)
            s[i++] = s[j]; //直接替换掉最左元素(已在x中存有备份)
        // 从左向右找第一个>x的数
        while (i < j && s[i] <= x)
            i++;
        if (i < j)
            //替换掉最右元素(已在最左元素中有备份)
            //最左元素一定被覆盖过,若没有,则表明右侧所有元素都>x,那么算法将终止
            s[j--] = s[i];
    }
    s[i] = x; //i的位置放了x,所以其左侧都小于x,右侧y都大于x
    return i;
}
void quickSort(int s[], int l, int r) {
    //数组左界<右界才有意义,否则说明都已排好,直接返回即可
    if (l >= r) {
        return;
    }
    // 划分,返回基准点位置
    int i = quickSortPartition(s, l, r);
    // 递归处理左右两部分,i处为分界点,不用管i了
    quickSort(s, l, i - 1);
    quickSort(s, i + 1, r);
}
归并排序
void Merge(int arr[], int l, int q, int r) {
    int n = r - l + 1; //临时数组存合并后的有序序列
    int *tmp = new int[n];
    int i = 0;
    int left = l;
    int right = q + 1;
    while (left <= q && right <= r)
        tmp[i++] = arr[left] <= arr[right] ? arr[left++] : arr[right++];
    while (left <= q)
        tmp[i++] = arr[left++];
    while (right <= r)
        tmp[i++] = arr[right++];
    for (int j = 0; j < n; ++j)
        arr[l + j] = tmp[j];
    delete[] tmp; //删掉堆区的内存
}
void MergeSort(int arr[], int l, int r) {
    if (l == r)
        return; //递归基是让数组中的每个数单独成为长度为1的区间
    int q = (l + r) / 2;
    MergeSort(arr, l, q);
    MergeSort(arr, q + 1, r);
    Merge(arr, l, q, r);
}
选择排序
void Selectsort(int num[], int length) {
    int index;
    for (int i = 0; i < length - 1; i++) {
        index = i;
        for (int j = i + 1; j < length; j++) {
            if (num[index] < num[j]) {
                index = j;
            }
        }
        swap(num[index], num[i]);
    }
}
//冒泡排序
void BubbleSort(int num[], int length) {
    for (int jj = 0; jj < length - 1; jj++) {
        for (int ii = 0; ii < length - 1 - jj; ii++)
            if (num[ii] > num[ii + 1]) {
                swap(num[ii], num[ii + 1]);
            }
    }
}
插入排序
void InsertSort(int num[], int length) {
    for (int ii = 1; ii < length; ii++) {
        int jj = ii;
        int temp = num[ii];
        for (; jj > 0 && temp < num[jj - 1]; jj--) {
            num[jj] = num[jj - 1];
        }
        num[jj] = temp;
    }
}
/*主函数
*/
int main() {
    //cout << "Please input the level of quantity: " << endl;
    int level; //输入数量级
    ofstream details("details.txt");
    ofstream logs("logs.txt");
    for (level = 1; level <= 6; level++) {
        //cin >> level;
        //cout << "Please input the number of tests: " << endl;
        int numOfData;
        numOfData = 20;
        long long int length = pow(10, level);
        details << "===============================" << endl;
        logs << "===============================" << endl;
        details << "Level:" << level << " Quantity:" << length << " TestNumber:" << numOfData << endl;
        logs << "Level:" << level << " Quantity:" << length << " TestNumber:" << numOfData << endl;
        cout << "Running on " << level << endl;
        int *num = new int[length];
        /*
        选择排序
        */
        double total_time = 0;
        for (int t = 0; t < numOfData; t++) {
            time_t seed = time(nullptr);
            default_random_engine eng(seed);
            uniform_int_distribution<int> dist(1, length);
            for (int i = 0; i < length; i++) {
                num[i] = dist(eng);
            }
            LARGE_INTEGER nFreq;
            LARGE_INTEGER nBeginTime;
            LARGE_INTEGER nEndTime;
            QueryPerformanceFrequency(&nFreq);
            QueryPerformanceCounter(&nBeginTime);
            Selectsort(num, length);
            QueryPerformanceCounter(&nEndTime);
            details << "Select_sort Test Data " << t + 1 << " time cost:"
                    << (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart * 1000 << "ms"
                    << endl;
            total_time += (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart;
        }
        details << "Select_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        logs << "Select_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        /*
        冒泡排序
        */
        total_time = 0;
        for (int t = 0; t < numOfData; t++) {
            time_t seed = time(nullptr);
            default_random_engine eng(seed);
            uniform_int_distribution<int> dist(1, length);
            for (int i = 0; i < length; i++) {
                num[i] = dist(eng);
            }
            LARGE_INTEGER nFreq;
            LARGE_INTEGER nBeginTime;
            LARGE_INTEGER nEndTime;
            QueryPerformanceFrequency(&nFreq);
            QueryPerformanceCounter(&nBeginTime);
            BubbleSort(num, length);
            QueryPerformanceCounter(&nEndTime);
            details << "Bubble_sort Test Data " << t + 1 << " time cost:"
                    << (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart * 1000 << "ms"
                    << endl;
            total_time += (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart;
        }
        details << "Bubble_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        logs << "Bubble_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        /*
        插入排序
        */
        total_time = 0;
        for (int t = 0; t < numOfData; t++) {
            time_t seed = time(nullptr);
            default_random_engine eng(seed);
            uniform_int_distribution<int> dist(1, length);
            for (int i = 0; i < length; i++) {
                num[i] = dist(eng);
            }
            LARGE_INTEGER nFreq;
            LARGE_INTEGER nBeginTime;
            LARGE_INTEGER nEndTime;
            QueryPerformanceFrequency(&nFreq);
            QueryPerformanceCounter(&nBeginTime);
            InsertSort(num, length);
            QueryPerformanceCounter(&nEndTime);
            details << "Insert_sort Test Data " << t + 1 << " time cost:"
                    << (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart * 1000 << "ms"
                    << endl;
            total_time += (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart;
        }
        details << "Insert_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        logs << "Insert_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        /*
        快速排序
        */
        total_time = 0;
        for (int t = 0; t < numOfData; t++) {
            time_t seed = time(nullptr);
            default_random_engine eng(seed);
            uniform_int_distribution<int> dist(1, length);
            for (int i = 0; i < length; i++) {
                num[i] = dist(eng);
            }
            LARGE_INTEGER nFreq;
            LARGE_INTEGER nBeginTime;
            LARGE_INTEGER nEndTime;
            QueryPerformanceFrequency(&nFreq);
            QueryPerformanceCounter(&nBeginTime);
            quickSort(num, 0, length - 1);
            QueryPerformanceCounter(&nEndTime);
            details << "Quick_sort Test Data " << t + 1 << " time cost:"
                    << (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart * 1000 << "ms"
                    << endl;
            total_time += (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart;
        }
        details << "Quick_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        logs << "Quick_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        /*
        归并排序
        */
        total_time = 0;
        for (int t = 0; t < numOfData; t++) {
            time_t seed = time(nullptr);
            default_random_engine eng(seed);
            uniform_int_distribution<int> dist(1, length);
            for (int i = 0; i < length; i++) {
                num[i] = dist(eng);
            }
            LARGE_INTEGER nFreq;
            LARGE_INTEGER nBeginTime;
            LARGE_INTEGER nEndTime;
            QueryPerformanceFrequency(&nFreq);
            QueryPerformanceCounter(&nBeginTime);
            MergeSort(num, 0, length - 1);
            QueryPerformanceCounter(&nEndTime);
            details << "Merge_sort Test Data " << t + 1 << " time cost:"
                    << (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart * 1000 << "ms"
                    << endl;
            total_time += (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart;
        }
        details << "Merge_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        logs << "Merge_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        /*
        基数排序
        */
        total_time = 0;
        for (int t = 0; t < numOfData; t++) {
            time_t seed = time(nullptr);
            default_random_engine eng(seed);
            uniform_int_distribution<int> dist(1, length);
            for (int i = 0; i < length; i++) {
                num[i] = dist(eng);
            }
            LARGE_INTEGER nFreq;
            LARGE_INTEGER nBeginTime;
            LARGE_INTEGER nEndTime;
            QueryPerformanceFrequency(&nFreq);
            QueryPerformanceCounter(&nBeginTime);
            Radix_Sort(num, length);
            QueryPerformanceCounter(&nEndTime);
            details << "Radix_sort Test Data " << t + 1 << " time cost:"
                    << (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart * 1000 << "ms"
                    << endl;
            total_time += (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart;
        }
        details << "Radix_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        logs << "Radix_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        /*
        希尔排序
        */
        total_time = 0;
        for (int t = 0; t < numOfData; t++) {
            time_t seed = time(nullptr);
            default_random_engine eng(seed);
            uniform_int_distribution<int> dist(1, length);
            for (int i = 0; i < length; i++) {
                num[i] = dist(eng);
            }
            LARGE_INTEGER nFreq;
            LARGE_INTEGER nBeginTime;
            LARGE_INTEGER nEndTime;
            QueryPerformanceFrequency(&nFreq);
            QueryPerformanceCounter(&nBeginTime);
            Shell_Sort(num, length);
            QueryPerformanceCounter(&nEndTime);
            details << "Shell_sort Test Data " << t + 1 << " time cost:"
                    << (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart * 1000 << "ms"
                    << endl;
            total_time += (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart;
        }
        logs << "Shell_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        details << "Shell_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        /*
        堆排序
        */
        total_time = 0;
        for (int t = 0; t < numOfData; t++) {
            time_t seed = time(nullptr);
            default_random_engine eng(seed);
            uniform_int_distribution<int> dist(1, length);
            for (int i = 0; i < length; i++) {
                num[i] = dist(eng);
            }
            LARGE_INTEGER nFreq;
            LARGE_INTEGER nBeginTime;
            LARGE_INTEGER nEndTime;
            QueryPerformanceFrequency(&nFreq);
            QueryPerformanceCounter(&nBeginTime);
            //排序源代码
            Heap_Sort_Desc(num, length);
            QueryPerformanceCounter(&nEndTime);
            details << "Heap_sort Test Data " << t + 1 << " time cost:"
                    << (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart * 1000 << "ms"
                    << endl;
            total_time += (double) (nEndTime.QuadPart - nBeginTime.QuadPart) / (double) nFreq.QuadPart;
        }
        details << "Heap_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
        logs << "Heap_sort Average Time Cost:" << total_time * 1000 / numOfData << "ms" << endl;
    }
    details.close();
    logs.close();
    return 0;
}
相关文章
|
27天前
|
机器学习/深度学习 人工智能 监控
AI算法分析,智慧城管AI智能识别系统源码
AI视频分析技术应用于智慧城管系统,通过监控摄像头实时识别违法行为,如违规摆摊、垃圾、违章停车等,实现非现场执法和预警。算法平台检测街面秩序(出店、游商、机动车、占道)和市容环境(垃圾、晾晒、垃圾桶、路面不洁、漂浮物、乱堆物料),助力及时处理问题,提升城市管理效率。
AI算法分析,智慧城管AI智能识别系统源码
|
1月前
|
算法
经典控制算法——PID算法原理分析及优化
这篇文章介绍了PID控制算法,这是一种广泛应用的控制策略,具有简单、鲁棒性强的特点。PID通过比例、积分和微分三个部分调整控制量,以减少系统误差。文章提到了在大学智能汽车竞赛中的应用,并详细解释了PID的基本原理和数学表达式。接着,讨论了数字PID的实现,包括位置式、增量式和步进式,以及它们各自的优缺点。最后,文章介绍了PID的优化方法,如积分饱和处理和微分项优化,以及串级PID在电机控制中的应用。整个内容旨在帮助读者理解PID控制的原理和实际运用。
72 1
|
1月前
|
算法 调度
【算法设计与分析】— —基础概念题(one)可作为日常联系或期末复习
【算法设计与分析】— —基础概念题(one)可作为日常联系或期末复习
47 1
|
1月前
|
算法 C语言 C++
嵌入式PID算法理论+实践分析
嵌入式PID算法理论+实践分析
24 0
|
1月前
|
算法
关联规则分析(Apriori算法2
关联规则分析(Apriori算法2
34 0
|
2天前
|
算法 数据可视化 Python
Python中LARS和Lasso回归之最小角算法Lars分析波士顿住房数据实例
Python中LARS和Lasso回归之最小角算法Lars分析波士顿住房数据实例
11 0
|
3天前
|
算法 定位技术 Windows
R语言最大流最小割定理和最短路径算法分析交通网络流量拥堵问题
R语言最大流最小割定理和最短路径算法分析交通网络流量拥堵问题
10 4
|
25天前
|
算法
TOP-K问题和向上调整算法和向下调整算法的时间复杂度问题的分析
TOP-K问题和向上调整算法和向下调整算法的时间复杂度问题的分析
17 1
|
28天前
|
算法
PID算法原理分析及优化
这篇文章介绍了PID控制方法,一种广泛应用于机电、冶金等行业的经典控制算法。PID通过比例、积分、微分三个部分调整控制量,以适应系统偏差。文章讨论了比例调节对系统响应的直接影响,积分调节如何消除稳态误差,以及微分调节如何减少超调。还提到了数字PID的实现,包括位置式、增量式和步进式,并探讨了积分饱和和微分项的优化策略。最后,文章简述了串级PID在电机控制中的应用,并强调了PID控制的灵活性和实用性。
38 1
|
1月前
|
存储 人工智能 算法
大数乘法的几种算法分析及比较(2014腾讯南京笔试题)
大数乘法的几种算法分析及比较(2014腾讯南京笔试题)

热门文章

最新文章