内排序算法小结

告别CPU空转!用STC8的SPI+DMA高效驱动上百颗WS2812B灯珠 本文详细解析了如何利用STC8单片机的SPI+DMA外设高效驱动WS2812B全彩灯珠,解决传统软件延时驱动方式在长灯带应用中的性能瓶颈。通过硬件方案设计、数据格式转换和DMA传输配置,实现高达400Hz的刷新率和低于5%的CPU占用率,适用于大规模灯光项目。 阅读详情

从以下几个方面来比较排序算法:

1. 算法的时间和空间复杂度

2. 排序的稳定性

3. 算法结构的复杂度

4. 参加排序的数据规模


排序的稳定性:

稳定排序方法: 插入排序、冒泡排序、二路归并排序、基数排序是稳定排序算法;

不稳定排序方法: 选择排序、谢尔排序、快速排序、堆积排序是不稳定排序算法。


算法复杂度比较:

各种内排序算法的时间、空间复杂度
排序方法平均时间最坏情况辅助空间
插入排序O(n*n)O(n*n)O(1)
谢尔排序O(n*log2n)O(n*log2n)O(1)
泡排序O(n*n)O(n*n)O(1)
快速排序O(n*log2n)O(n*n)O(log2n)
选择排序O(n*n)O(n*n)O(1)
堆积排序O(n*log2n)O(n*log2n)O(1)
归并排序O(n*log2n)O(n*log2n)O(n)
基数排序O(d*(n+r))O(d*(n+r))O(n+r)


有结论如下:

1. 平均情况下,谢尔排序、快速排序、堆积排序、归并排序都能达到较快的排序速度,快速排序最快,堆积排序空间消费最省。

2. 平均情况下,插入排序和泡排序的排序速度较慢,但当参加排序的序列开始就局部有序时,这两种排序算法就能够达到较快的排序速度。最后情况下速度为O(n), 比情况 1 中叙述的4中方法都好,辅助空间消费也少。所以当 n 较小或者序列开始就局部有序时,可选择这两种方法。

3. 基数排序方法消费的辅助空间较多,但其时间复杂度可简化为O(dn); 当元素的位数较少时,可继续简化为O(n), 这种情况下也能达到较快的排序速度,另外,归并排序需要的辅助空间也较多。

4. 从算法结构的简单性来看,插入排序、泡排序、选择排序比较简单和直接;而谢尔排序、快速排序、堆积排序以及归并排序都可以看做对某一种排序算法的进一步改进,相对而言,改进后的算法都比较复杂。

5. 从参加排序的数据序列的规模大小来看,n越小,采用简单排序方法就越合适;n越大,采用改进的排序方法越合适。这是因为n越小,n*n 与 log2n 的差距越小。


以下是在考虑内排序算法的优缺点后,在某些情况下比较适合的算法选择:

1. 当参加排序的数据规模较大,关键字元素分布比较随机,并且不要求排序稳定性时,宜采用快速排序法。

2. 当参加排序的数据规模较大,内存空间又允许,并且有排序稳定性要求,宜采用归并排序法。

3. 当参加排序的数据规模较大,元素分布可能出现升序或者逆序的情况,并且对排序的稳定性无要求时,宜采用插入排序方法。

4. 当参加排序的数据规模较小(如小于100),元素基本有序(升序),或者分布也比较随机,并且有排序稳定性要求时,宜采用插入排序方法。

5. 当参加排序的数据规模n较小,对排序稳定性又不要求时,宜采用选择排序。


插入排序、选择排序、归并排序都比较容易在链表上实现,当利用链表作为存储结构时,可以避免将大量时间花费在元素的位置移动上。


算法描述:

1. 插入排序:

  1. /* 简单插入排序 
  2.  * |data|中存储数组元素 
  3.  * |len|是数组大小 
  4.  * 1.  
  5.  *  需要 |len - 1| 趟排序,每一趟排序将未排序的序列中第一个元素插入到已排序的序列中 
  6.  * 2. 
  7.  *  每一趟排序寻找插入位置的比较次数不定,但是至少需要一次 
  8.  * 3. 
  9.  *  最好的情况,原序列已是升序排列,则需要|n-1|趟排序,每一趟排序进行一次元素间的比较,时间复杂度O(n) 
  10.  * 4. 
  11.  *  最坏的情况,原序列是降序排列,同样需要|n-1|趟排序,第 i(i>=1 && i<len)趟排序需进行 i 次元素间比较,时间复杂度O(n*n) 
  12.  * 5. 
  13.  *  平均时间复杂度O(n*n) 
  14.  * 6. 
  15.  *  插入排序是稳定性排序 
  16.  * */  
  17. void simple_insert(int *data, int len)  
  18. {  
  19.     if(data == NULL || len < 1)  
  20.         return;  
  21.   
  22.     int temp, i, j;  
  23.     for(i = 1; i < len; ++i) {  
  24.         temp = data[i];  
  25.         j = i - 1;  
  26.         while(j >= 0 && temp < data[j]) {  
  27.             data[j+1] = data[j--];  
  28.         }  
  29.         data[j+1] = temp;  
  30.     }  
  31. }  
  32.   
  33. /* 折半插入排序 
  34.  * 与简单插入排序相比 
  35.  *  1. 折半插入排序减少了寻找插入位置时的元素之间的比较次数 
  36.  *  2. 并未减少元素的移动次数和排序所需的趟数 
  37.  *  3. 时间复杂度降为O(n*log2n) 
  38.  */  
  39. void binary_insert(int *data, int len)  
  40. {  
  41.     if(data == NULL || len < 1)  
  42.         return;  
  43.   
  44.     int temp, i, j, low, mid, high;  
  45.     for(i = 1; i < len; ++i) {  
  46.         temp = data[i];  
  47.         low = 0;  
  48.         high = i - 1;  
  49.         while(low <= high) {  
  50.             mid = (low + high)/2;  
  51.             if(temp < data[mid])  
  52.                 high = mid - 1;  
  53.             else  
  54.                 low = mid + 1;  
  55.         }  
  56.   
  57.         for(j = i; j > low; --j)  
  58.             data[j] = data[j-1];  
  59.   
  60.         data[low] = temp;  
  61.     }  
  62. }  

2. 谢尔排序

  1. /* 谢尔排序,又称缩小增量排序法,是对直接插入排序法的一种改进 
  2.  * 1. 
  3.  *  时间复杂度在O(n*log2n) 和 O(n*n)之间 
  4.  * 2. 
  5.  *  谢尔排序是一种不稳定排序,不适合在链表结构上实现的排序算法 
  6.  * */  
  7. void shellSort(int *data, int len)  
  8. {  
  9.     if(data == NULL || len < 1)  
  10.         return;  
  11.   
  12.     unsigned int gap = len;  
  13.     int i,j,temp;  
  14.     while(gap > 0) {  
  15.         gap >>= 1;  
  16.         for(i = gap; i < len; ++i) {  
  17.             j = i - gap;  
  18.             temp = data[i];  
  19.             while(j >= 0 && temp < data[j]) {  
  20.                 data[j+gap] = data[j];  
  21.                 j -= gap;  
  22.             }  
  23.   
  24.             data[j+gap] = temp;  
  25.         }  
  26.     }  
  27. }  

3. 泡排序

  1. /* 冒泡排序 
  2.  * 1. 
  3.  *  至少需要进行一趟排序,此时是原始序列已经升序排列的情况,需进行|len - 1|次元素间的比较,时间复杂度O(n) 
  4.  * 2. 
  5.  *  最多进行|len - 1|趟排序(最小值处于原始序列最后),第 i(i>=1 && i<=len-1) 趟排序需要进行|len - i|次元素间的比较, 时间复杂度O(n*n) 
  6.  * 3. 
  7.  *  平均时间复杂度是O(n*n) 
  8.  * 4. 
  9.  *  冒泡排序是稳定性排序,适用于参加排序的数据量较小并且序列的初始状态为基本有序的情况 
  10.  * */  
  11. void bubbleSort(int *data, int len)  
  12. {  
  13.     if(data == NULL || len < 1)  
  14.         return;  
  15.   
  16.     int flag = 1;  
  17.     int i, j, temp;  
  18.     i = len - 1;  
  19.     while(i > 0 && flag == 1) {  
  20.         flag = 0;  
  21.         for(j = 0; j < i; ++j) {  
  22.             if(data[j] > data[j+1]) {  
  23.                 temp = data[j];  
  24.                 data[j] = data[j+1];  
  25.                 data[j+1] = temp;  
  26.   
  27.                 flag = 1;  
  28.             }  
  29.         }  
  30.   
  31.         --i;  
  32.     }  
  33. }  

4. 快速排序

  1. /* randomInRange函数: 
  2.  * 产生[start, end] 之间的随机数,包括start, end两个数 
  3.  * */  
  4. int randomInRange(int start, int end)  
  5. {  
  6.     srand(time(NULL));  
  7.   
  8.     return start + rand()%(end-start+1);  
  9. }  
  10.   
  11. /*  
  12.  * 交换elem1, elem2的值 
  13.  */  
  14. void swapElem(int *elem1, int *elem2)  
  15. {  
  16.     int temp = *elem1;  
  17.     *elem1 = *elem2;  
  18.     *elem2 = temp;  
  19. }  
  20.   
  21. /* partition函数: 
  22.  * 在data序列的[start, end]之间随机选取一个元素值作为分界元素vp, 
  23.  * 该分界元素vp左边的值都小于等于vp, 右边的值都大于等于vp, 
  24.  * 函数返回该分界元素在序列中的索引位置 
  25.  * */  
  26. int partition(int *data, int len, int start, int end)  
  27. {  
  28.     if(data == NULL || len < 1 || start < 0 || end >= len) {  
  29.         printf("invalid parameters.");  
  30.         exit(1);  
  31.     }  
  32.   
  33.     int index = randomInRange(start, end);  
  34.     swapElem(&data[index], &data[end]);  
  35.     int small = start - 1;  
  36.   
  37.     for(index = start; index < end; ++index) {  
  38.         if(data[index] < data[end]) {  
  39.             ++small;  
  40.             if(small != index)  
  41.                 swapElem(&data[index], &data[small]);  
  42.         }  
  43.     }  
  44.     swapElem(&data[++small], &data[end]);  
  45.   
  46.     return small;  
  47. }  
  48.   
  49. /* 快速排序递归算法: 
  50.  * 1.  
  51.  *  时间复杂度是O(n*log2n) 
  52.  * 2.  
  53.  *  快速排序是不稳定排序,不适合在链表结构上实现的排序算法 
  54.  * 3. 
  55.  *  每次排序时如果各个部分的分界元素恰好就是最大值元素时,快速排序就会倒退为"慢速排序", 此时并未把序列分界为两个子序列 
  56.  * */  
  57. void quickSort(int *data, int len, int start, int end)  
  58. {  
  59.     if(start == end)  
  60.         return;  
  61.   
  62.     int index = partition(data, len, start, end);  
  63.     if(index > start)  
  64.         quickSort(data, len, start, index - 1);  
  65.     if(index < end)  
  66.         quickSort(data, len, index + 1, end);  
  67. }  

5. 选择排序

  1. /* 选择排序 
  2.  * 1.  
  3.  *  总共需要|len - 1|趟排序,且第 i(i>=1 && i<=len-1) 趟排序需要进行 |len - i|次元素间的比较 
  4.  * 2. 
  5.  *  时间复杂度与初始序列的状态无关,都是O(n*n) 
  6.  * 3. 
  7.  *  选择排序是不稳定排序,例如(49, 38, 65, 97, 49, 13, 27) 
  8.  * */  
  9. void selectSort(int *data, int len)  
  10. {  
  11.     if(data == NULL || len < 1)  
  12.         return;  
  13.   
  14.     int i, j, minIndex;  
  15.     for(i = 0; i < len - 1; ++i) {  
  16.         minIndex = i;  
  17.         j = i + 1;  
  18.         while(j < len) {  
  19.             if(data[j] < data[minIndex])  
  20.                 minIndex = j;  
  21.             ++j;  
  22.         }  
  23.   
  24.         if(minIndex != i) {  
  25.             int temp = data[i];  
  26.             data[i] = data[minIndex];  
  27.             data[minIndex] = temp;  
  28.         }  
  29.     }  
  30. }  

6. 堆积排序

  1. /* adjust函数: 
  2.  * |len| 数组序列的大小 
  3.  * |root| 数组中某一元素的索引 
  4.  * 以结点root为根结点的子树不是堆积,但结点root的左右子树都是堆积, 
  5.  * adjust函数将把第root个结点作为根结点的子树调整为一个新的堆积 
  6.  * */  
  7. void adjust(int *data, int len, int root)  
  8. {  
  9.     int temp = data[root];  
  10.     int i = root * 2;  
  11.   
  12.     while(i <= len) {  
  13.         if(i < len && data[i] < data[i + 1])  
  14.             ++i;  
  15.   
  16.         if(temp >= data[i])  
  17.             break;  
  18.   
  19.         data[i/2] = data[i];  
  20.         i *= 2;  
  21.     }  
  22.   
  23.     data[i/2] = temp;  
  24. }  
  25.   
  26. /* 堆排序: 
  27.  * |len| data序列中最后一个元素的索引号, 也是参加排序的元素个数, 
  28.  * 注意不是data序列的元素个数 
  29.  * 1.  
  30.  *  data序列中第1个元素(data[0])不参加排序 
  31.  * 2.  
  32.  *  总共执行|len - 1|趟排序,每一趟排序确定未排序序列中的最大值的位置,并执行一次adjust函数 
  33.  * 3. 
  34.  *  无论是最坏情况还是平均情况,堆积排序的时间复杂度都是O(n*log2n) 
  35.  * 4. 
  36.  *  堆积排序的空间复杂度是O(1), 适合于len较大的序列排序 
  37.  * 5. 
  38.  *  堆积排序不适合在链表上实现 
  39.  * 6. 
  40.  *  堆积排序是不稳定排序,例如(5, 4, 3, 2, 2, 2, 1) 
  41.  */  
  42. void heapSort(int *data, int len)  
  43. {  
  44.     if(data == NULL || len < 1)  
  45.         return;  
  46.   
  47.     int i;  
  48.     for(i = len/2; i > 0; --i) {  
  49.         adjust(data, len, i);  
  50.     }  
  51.   
  52.     int temp;  
  53.     for(i = len; i > 1; --i) {  
  54.         temp = data[1];  
  55.         data[1] = data[i];  
  56.         data[i] = temp;  
  57.   
  58.         adjust(data, i-1, 1);  
  59.     }  
  60. }  

7. 归并排序

  1. /* merge函数: 
  2.  * 将source[start..mid]和source[mid+1..end]中的元素归并有序序列des[start..end] 
  3.  * 
  4.  * */  
  5. void merge(int *source, int *des, int start, int mid, int end)  
  6. {  
  7.     int i = start;  
  8.     int j = mid + 1;  
  9.     int k = start;  
  10.   
  11.     while(i <= mid && j <= end) {  
  12.        // if(source[i] <= source[j])  
  13.        //     des[k++] = source[i++];  
  14.        // else  
  15.        //     des[k++] = source[j++];  
  16.         des[k++] = source[i] <= source[j] ? source[i++] : source[j++];  
  17.     }  
  18.   
  19.     while(i <= mid)  
  20.         des[k++] = source[i++];  
  21.     while(j <= end)  
  22.         des[k++] = source[j++];  
  23. }  
  24.   
  25. /* mpass函数: 
  26.  * 将参加排序的序列分成若干个长度为t的,且各自按值有序的子序列, 
  27.  * 然后多次调用归并子算法merge将所有两两相邻成对的子序列合并成 
  28.  * 若干个长度为2t的,且各自按值有序的子序列。 
  29.  *  
  30.  * 若最后一趟排序时,剩下的元素不足2t个元素: 
  31.  * 1. 
  32.  *  若剩余元素个数大于t,则再调用一次merge算法将剩余的两个不等长子序列合并为一个子序列 
  33.  * 2. 
  34.  *  若剩余元素个数小于等于t,则直接将所有剩余元素依次复制到前一个子序列的后面 
  35.  * */  
  36. void mpass(int *source, int *des, int len, int t)  
  37. {  
  38.     int i = 0;  
  39.     if(len - i >= 2*t) {  
  40.         merge(source, des, i, i + t - 1, i + 2 * t - 1);  
  41.         i += 2 * t;  
  42.     }  
  43.   
  44.     if(len - i > t)  
  45.         merge(source, des, i, i + t - 1, len - 1);  
  46.     else {  
  47.         for(; i < len; ++i)  
  48.             des[i] = source[i];   
  49.     }  
  50. }  
  51.   
  52. /* mergeSort排序: 
  53.  * |flag|,若flag = -1,则表示输入参数错误; 
  54.  * 若flag = 1, 则表示排好序的元素存放于data序列中 
  55.  * 若flag = 0,则表示排好序的元素存放于des序列中 
  56.  * 1.  
  57.  *  总共会进行log2n趟排序,每趟排序调用mpass函数,mpass的时间复杂度为O(n),二路归并排序的时间复杂度为O(nlog2n) 
  58.  * 2. 
  59.  *  排序过程中需要同原始序列同等大小的辅助空间,空间复杂度为O(n) 
  60.  * 3. 
  61.  *  二路归并排序是稳定性排序 
  62.  * 4. 
  63.  *  二路归并排序的时间复杂度与序列的初始状态无关 
  64.  */  
  65. int mergeSort(int *data, int *des, int len)  
  66. {  
  67.     int flag = -1;  
  68.     if(data == NULL || len < 1)  
  69.         return flag;  
  70.   
  71.     int t = 1;  
  72.     flag = 1;  
  73.     while(t < len) {  
  74.         mpass(data, des, len, t);  
  75.         flag = 0;  
  76.   
  77.         t *= 2;  
  78.         if(t < len) {  
  79.             mpass(des, data, len, t);  
  80.             t *= 2;  
  81.             flag = 1;  
  82.         }  
  83.     }  
  84.   
  85.     return flag;  
  86. }  

8. 基数排序
  1. /* 
  2.  * 定义的存储数据元素的结点 
  3.  */  
  4. typedef struct Node {  
  5.     int data;  
  6.     struct Node *next;  
  7. }QLink;  
  8.   
  9. /* maxDig函数: 
  10.  * 找出data序列所有元素中最长的位数maxd并返回 
  11.  * */  
  12. int maxDig(int *data, int len)  
  13. {  
  14.     int maxd = 0;  
  15.     int maxCurD = 1;  
  16.   
  17.     int base = 10;  
  18.     for(int i = 0; i < len; ++i) {  
  19.         maxCurD = 1;  
  20.         base = 10;  
  21.         while(data[i] >= base) {  
  22.             ++maxCurD;  
  23.             if(maxd < maxCurD)  
  24.                 maxd = maxCurD;  
  25.             base *= 10;  
  26.         }  
  27.     }  
  28.   
  29.     return maxd;  
  30. }  
  31.   
  32. /* 
  33.  * 将data序列中所有元素均存储到链表中,并返回链表头结点head 
  34.  */  
  35. QLink* transferArrToQLink(int *data, int len)  
  36. {  
  37.     if(data == NULL || len < 1)  
  38.         return NULL;  
  39.   
  40.     QLink *head = NULL;  
  41.     QLink *rear = NULL;  
  42.   
  43.     for(int i = 0; i < len; ++i) {  
  44.         QLink *cur = (QLink *)malloc(sizeof(QLink));  
  45.         cur->data = data[i];  
  46.         cur->next = NULL;  
  47.         if(head == NULL)  
  48.             head = cur;  
  49.         else  
  50.             rear->next = cur;  
  51.         rear = cur;  
  52.     }  
  53.   
  54.     return head;  
  55. }  
  56.   
  57. /* 
  58.  * 释放链表中所有元素结点 
  59.  */  
  60. void freeQLink(QLink *phead)  
  61. {  
  62.     QLink *toFree = NULL;  
  63.     while(phead != NULL) {  
  64.         toFree = phead;  
  65.         phead = phead->next;  
  66.         free(toFree);  
  67.     }  
  68. }  
  69.   
  70. /* 
  71.  * 获取num 中从右边数第index位的数字,index从0 开始计数 
  72.  * 
  73.  */  
  74. int getCurPlaceV(int num, int index)  
  75. {  
  76.     int placeValue;  
  77.     int i = 0;  
  78.     while(i <= index) {  
  79.         placeValue = num%10;  
  80.         num /= 10;  
  81.         ++i;  
  82.     }  
  83.   
  84.     return placeValue;  
  85. }  
  86.   
  87. /* 
  88.  * |data| 数据元素序列,|len|数据元素的个数,|radix|是基数 
  89.  */  
  90. void radixSort(int *data, int len, int radix)  
  91. {  
  92.     int maxd = maxDig(data, len);  
  93.     printf("maxd = %d\n", maxd);  
  94.     QLink *phead = transferArrToQLink(data, len);  
  95.   
  96.     QLink *Front[radix], *End[radix];  
  97.     QLink *q, *rear;  
  98.     int i, j, curplaceV;  
  99.     for(i = 0; i < maxd; ++i) {  
  100.         printf("the %d times sort\n", i);  
  101.         for(j = 0; j < radix; ++j)  
  102.             Front[j] = End[j] = NULL;  
  103.   
  104.         q = phead;  
  105.         while(q != NULL) {  
  106.             curplaceV = getCurPlaceV(q->data, i);  
  107.             if(Front[curplaceV] == NULL)  
  108.                 Front[curplaceV] = q;  
  109.             else  
  110.                 End[curplaceV]->next = q;  
  111.             End[curplaceV] = q;  
  112.   
  113.             q = q->next;  
  114.         }  
  115.   
  116.         j = 0;  
  117.         while(Front[j] == NULL)  
  118.             ++j;  
  119.   
  120.         phead = Front[j];  
  121.         rear = End[j];  
  122.         ++j;  
  123.         for(; j < radix; ++j) {  
  124.             if(Front[j] != NULL) {  
  125.                 rear->next = Front[j];  
  126.                 rear = End[j];  
  127.             }  
  128.         }  
  129.         rear->next = NULL;  
  130.     }  
  131.   
  132.     q = phead;  
  133.     i = 0;  
  134.     while(q != NULL) {  
  135.         data[i++] = q->data;  
  136.         q = q->next;  
  137.     }  
  138.   
  139.     freeQLink(phead);  
  140.     phead = NULL;  
  141. }  
手把手教你用u-center配置ublox GPS模块:从波特率到报文频率全流程 本文提供了一份详细的u-center软件配置ublox GPS模块的完整指南。从硬件连接到软件设置,逐步讲解了如何探测并设置正确的波特率、选择与启用关键的NMEA和UBX报文,以及配置输出频率。文章特别强调了配置固化的重要性,并分享了使用UBX协议进行高效数据解析等高级技巧,帮助开发者快速上手并优化GPS模块性能。 阅读详情

相关推荐

Altium Designer铺铜陷阱:为什么你的死铜总是清除不干净?

本文深入探讨Altium Designer中铺铜操作导致死铜无法清除的常见问题,分析死铜形成的五大诱因,并提供高级参数优化和网络连接性验证技巧。通过调整边界计算精度和泪滴算法设置,有效解决死铜残留问题,提升PCB设计质量与制造良率。

weixin_29169505的博客 359

常见七种排序算法对比(超全!!!)

一,冒泡排序 最常见的排序实现起来很简单,不过实际应用很少,复杂度O(n²)。 原理:一趟一趟的比,每一趟中,循环剩余的数,和后一个进行比较,若比它小则交换。这样一趟下来最小的在第一个,最大的在最后一个。总共需要比n-1趟。 public static void BubbleSort(int []array){ for(int i=1;i<array.length;i++) { for(int j=0;j<array.length-1;j++) .

qq_54850622的博客 1万+

2024高教社杯数学建模国赛B题丨国一原创论文解析及源码超详细分享!

继续分享一篇2024国赛B题的国奖论文,包含可运行源代码jupyter,国赛B题通常比较聚焦实际复杂系统的多目标优化决策,主要偏重算法实现与概率建模解决开放性的管理问题。而且高度开放,无标准答案,学科交叉复杂,如资源调度、交通优化、海洋探测等。比较建议有一定统计学基础的同学参加。

ihui永不放弃 6739

排序算法的详解和分析对比(详细讲解)

排序算法各式各样,每种排序算法的思想也大同小异。读者应该深度了解每种算法的基本思想、排序每一步过程细节和每种排序的特性,看到特定的序列,应该立马想到最适合的排序方法。一些简单的排序算法中,虽然效率不高,但是在低数量规模情况下,就比如一万数量级以下,一般运行时间还能可以被人们所接受,零点几秒左右很难被察觉出来。但是如果到了十万数量级,排序就需要非常久的时间,可能会导致我们一些系统会出现误差,从而引起巨大的麻烦和问题。

gongjunbox的博客 9593

基于FPGA低频方波测量-频率与占空比

基于FPGA低频方波测量-频率与占空比

DRAXY的博客 6733

18650电池组流体直冷热管理仿真:COMSOL多物理场耦合建模路线与实战策略

在动力电池与储能系统的热管理设计中,多物理场耦合仿真已成为平衡性能与成本的关键工具。液冷方案的换热极限促使行业转向制冷剂直冷技术,而两相流与电池产热的强耦合特性,使得基于COMSOL的数值建模成为评估系统温升与流动分配的重要手段。工程实践中,电化学-热-流场全耦合模型与集总电池-流场简化模型各有适用场景,前者揭示电池内部微观机理,后者则以高计算效率支撑包级方案迭代。通过合理简化几何、标定内阻与熵热系数、设置等效换热边界,仿真能够准确预测直冷系统在快充或大倍率放电下的温度均匀性与压降特性,从而指导流道优化与制

weixin_33585822的博客 314

【数据结构从青铜到王者】第九篇:数据结构之排序

系列文章目录 文章目录系列文章目录前言一、排序的概念1.排序的概念二、常见排序算法的实现1.插入排序1.基本思想2.代码实现2.希尔排序1.基本思想2.代码实现3.选择排序1.基本思想2.代码实现4.堆排序1.基本思想2.代码实现5.冒泡排序1.基本思想2.代码实现6.快速排序递归思想1.左右指针法1.基本思想2.代码实现2.挖坑法1.基本思想2.代码实现3.前后指针法1.基本思想2.代码实现4.快速排序优化方法1.三数取中法2.小区间排序优化7.快速排序非递归思想1.基本思想2.代码实现8.归并排序递.

森明帮大于黑虎帮的博客 2324

SAP PP工艺路线Routing保姆级配置指南:从CA01创建到替代/并行顺序实战

本文详细解析SAP PP模块中工艺路线(Routing)的配置与应用,从基础创建(CA01)到高级功能如替代顺序和并行顺序的实战操作。通过真实案例演示,帮助用户掌握SAP PP工艺路线的精细化管理,提升生产流程效率。

weixin_30898555的博客 389

9种排序算法对比

本文章中所有代码均为本人原创,能力有限,若有错误,请指正!

m0_74133913的博客 1516

亚马逊商品评论爬取与情感分析实战:Python+BeautifulSoup高效解析(附反爬技巧)

本文详细介绍了使用Python和BeautifulSoup库高效爬取亚马逊商品评论并进行情感分析的完整实战流程。文章从环境搭建、核心代码编写入手,重点讲解了如何通过设置请求头、添加延迟等防封策略应对反爬机制,确保数据抓取的稳定性。最后,利用TextBlob库对评论文本进行情感分析,并通过可视化图表直观展示产品口碑,为电商选品与市场调研提供数据支持。

weixin_29046611的博客 1164

OpenEarthMap 与 xBD 数据集合并

整合好的数据:链接: https://pan.baidu.com/s/1uJ_Zg6n-s3u1D49OW52D7Q?pwd=2vwx 提取码: 2vwx完整整合步骤与代码如下。

qq_60293814的博客 1596

算法设计(1)--内排序算法小结

内排序算法 William Yi 完成于2016/10/18 Email: williamyi96@gmail.com 排序算法可以大致分为两种类型: 内排序 外排序 两者之间的区别是内排序是在内存中进行的排序,而外排序则可以借助磁盘空间。我们通过之前的学习了解到:内存中的排序时间代价与空间代价是成反比的,也就是说时间的缩短是以空间增长为代价的,空间的减少是以时间延长为代价的;而磁盘中

博观而约取,深研而广求 1423

基于Multisim的三相桥式全控整流电路建模、仿真与综合分析

本文基于Multisim 14.2平台,系统研究了三相桥式全控整流电路的建模与仿真方法。首先阐述了电路拓扑结构和工作原理,建立了数学模型。重点介绍了在Multisim中搭建主电路、设计六脉冲触发系统(含两种实现方案)的关键步骤,以及参数设置技巧。通过仿真分析了不同负载(阻性、阻感性)和触发角(0°-90°)下的输出特性,包括电压波形、电流谐波等性能指标。研究为电力电子教学提供了直观的仿真范例,并探讨了模型改进方向与实际工程应用价值。

huanghm88的专栏 354

排序算法小结(五)——在线性时间内排序(Java实现):计数排序、基数排序。

1.计数排序 一文弄懂计数排序算法! 2.基数排序

xx2014301318的博客 307

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

内部排序算法小结

排序算法大体上可分为内部排序和外部排序。所谓外部排序,就是指计算机的内存有限,不能将庞大的序列全部加载到内存中进行排序,就需要访问外部存储设备来进行排序。内部排序,当数据量不是非常大时,可以一次性加载到内存中进行排序的统称。 按照排序依据的不同原则,可将内部排序算法分为插入排序、交换排序、选择排序、归并排序和基数排序。下面我主要讲各种排序算法的原理,实现由小到大的排序,具体的实现方式可以参见我的

在路上...... 918

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

NJUPT南京邮电大学数据结构实验四(各种内排序算法的实现及性能比较)

仅提供思路,请勿照抄!!!

AZCJXT的博客 1697

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

[数据结构] 排序算法小结

排序算法

shengxia_lx的博客 361

【数据结构】内排序小结

“ Ctrl AC!一起 AC!”目录排序码与关键码插入排序直接插入排序二分法插入排序 表插入排序Shell插入排序(希尔排序)选择排序直接选择排序树型选择排序堆排序 交换排序冒泡排序快速排序快速排序归并排序基数排序排序码:以此码作为比较进行排序 关键码:能唯一标识一个记录的字段称为关键码比如(可能不恰当)a b c d 这一序列排序码是它们在字母表中的顺序关键码是它们本身"a" "b" "c" "d"插入排序的基本方法是:将待排序文件中的记录,逐个地按其排序码值的大小插入到目前已经排好序的若干个记录组成的

Ctrl AC的博客 480

内排序小结

冒泡排序是一种交换排序,基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。

辉 951

数据结构与算法之排序

不同的排序算法适用于不同的场景,选择合适的排序算法可以提高程序的效率。例如,插入排序适用于部分有序的数据,而归并排序适用于大规模数据的排序.外排序适用于数据量较大的情况,通常需要将数据分块处理,然后合并排序结果。设待排序的表有10个元素,其关键字分别为(9,8,7,6,5,4,3,2,1,0):每次从未排序区取出一个元素,插入到有序区的适当位置,使得有序区仍然保持有序。:初始时,有序区只有一个元素(通常是第一个元素),无序区包含其余所有元素。:将数据分成多个小部分进行排序,然后将排序好的部分合并。

yuange1666的博客 1326

内部排序算法总结-第一篇

内部排序算法总结-第一篇 首先看一下内部排序分类以及各个算法的时间复杂度、空间复杂度和稳定性 一、插入排序   1、直接插入排序 (Straight Insertion Sort)的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表。开始时有序表中只包含1个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一...

hequnwang10的博客 315

【算法】排序算法小结(上)

        排序算法是算法中的基础,通常是解决其他算法的第一步。排序是将一组对象按照某种逻辑顺序重新排列的过程,本文将经典的排序算法根据《算法第四版》进行整理。以备复习使用。最后,结合leetcode经典题目,进行应用。另外值得注意的是,排序算法有内排序和外排序之分,在排序过程中,全部记录存放在内存,则称为内排序,如果排序过程中需要使用外存,则称为外排序。外排序一般来说外排序分为两个步骤:预处...

Biyoner的博客 464
上一篇: 数组分割问题-详细版
下一篇: 应聘时最漂亮的回答! 留着 早晚用的上
otuhacker
博客等级 码龄18年 21粉丝 84原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值