交换排序与冒泡排序
2014-11-13 19:57
197 查看
今天在读公司的平台代码的时候发现了一处排序的地方,令我意外的是居然还在用最原始的时间复杂度为的 O(n的平方) 排序方式。
刚看到那些代码无法分清究竟是 交换排序 还是 冒泡排序,记得有一次面试的时候让写冒泡排序呢结果写成交换排序了,当时怎么想也想不起来惭愧,
回来后看了一眼才恍然大悟。其实这两个都是课堂上学过的。这里有必要再分析下它们的区别:
首先说冒泡排序:
将被排序的记录数组R[1..n]垂直排列,每个记录 R[i] 看作是 重量 为R[i].key的气泡。根据轻气泡不能在重气泡之下的原则,从下往上扫数组R:
凡扫描到违反本原则的轻气泡,就使其向上"飘浮"。如此反复进行,直到最后任何两个气泡都是轻者在上,重者在下(所谓 清者为天 浊者为地 )为止
code示例如下:(从小到大)
然后就是交换排序:
交换法的程序最清晰简单,每次用当前的元素一一的同其后的元素比较并交换。 (从小到大)
上面的两种排序可以用如下验证:
其实严格来说冒泡排序也属于交换排序的一种,它们的时间复杂度都是 O(n的平方) 。它们的不同点:
冒泡排序在 内部的一个循环 比较连续的2个元素,如果不等则交换。
交换排序是 在内部的一个循环中把每个元素跟外部循环的元素相比较 ,如果不等则交换。
代码优化
最后 pServiceInfo 是无用的,有用的仅仅是channel数组(pServiceInfo 通过一定规则排序之后ID与channel对应)
再看下 sk_char_service_id 函数
3次 memcpy 的过程仅仅是让指针 service_info[j] 和指针 service_info[j+1] 指向的内容一致,这3次memcpy可能需要大量的cpu周期,如果采用别的办法,
比如说交换 service_info[j] 和 service_info[j+1] 的指针值那么则可以大大减少cpu周期,采用这种方式之后 sk_char_service_id 函数如下所示:
另外还有优化的余地,那就是把排序方式改成快速排序。
刚看到那些代码无法分清究竟是 交换排序 还是 冒泡排序,记得有一次面试的时候让写冒泡排序呢结果写成交换排序了,当时怎么想也想不起来惭愧,
回来后看了一眼才恍然大悟。其实这两个都是课堂上学过的。这里有必要再分析下它们的区别:
首先说冒泡排序:
将被排序的记录数组R[1..n]垂直排列,每个记录 R[i] 看作是 重量 为R[i].key的气泡。根据轻气泡不能在重气泡之下的原则,从下往上扫数组R:
凡扫描到违反本原则的轻气泡,就使其向上"飘浮"。如此反复进行,直到最后任何两个气泡都是轻者在上,重者在下(所谓 清者为天 浊者为地 )为止
code示例如下:(从小到大)
void BubbleSort(int *vInt, size_t size ) { int temp; size_t i,j; for (i = 0; i < size; i++) { for (j = size - 1; j > i; j--) { if (vInt[j] < vInt[j-1]) { temp = vInt[j-1]; vInt[j-1] = vInt[j]; vInt[j] = temp; } } } }
然后就是交换排序:
交换法的程序最清晰简单,每次用当前的元素一一的同其后的元素比较并交换。 (从小到大)
void ExchangeSort(int* pData,size_t Count) { int iTemp; size_t i,j; for(i=0;i<Count-1;i++) { for(j=i+1;j<Count;j++) { if(pData[j]<pData[i]) { iTemp = pData[i]; pData[i] = pData[j]; pData[j] = iTemp; } } } }
上面的两种排序可以用如下验证:
int main(void) { int i; int array[] = {12,18,81,-14,-1,0,33,38,46}; int len = sizeof(array)/sizeof(int); printf("len is %d\n",len); for(i = 0;i< len;i ++) printf("%d ",array[i]); printf("\n"); BubbleSort(array,len); for(i = 0;i < len; i ++) printf("%d ",array[i]); printf("\n\n"); return 0; }
其实严格来说冒泡排序也属于交换排序的一种,它们的时间复杂度都是 O(n的平方) 。它们的不同点:
冒泡排序在 内部的一个循环 比较连续的2个元素,如果不等则交换。
交换排序是 在内部的一个循环中把每个元素跟外部循环的元素相比较 ,如果不等则交换。
代码优化
int i = 0; SKY_SERVICE_INFO *pServiceInfo[MAX_TOTAL_PROGRAM_NUM] = {NULL}; for (i = 0; i < iProgramTotal; i++) { pServiceInfo[i] = sk_mem_malloc(sizeof(SKY_SERVICE_INFO)); memset(pServiceInfo[i], 0, sizeof(SKY_SERVICE_INFO)); sky_DM_Service_Get(channel[i], pServiceInfo[i]); } if (tpye == SORT_SERVICE_ID) { sk_char_service_id(pServiceInfo, iProgramTotal); for (i = 0; i < iProgramTotal; i++) { channel[i] = pServiceInfo[i]->id; } SendMessage(hWndGrid[PROGRAL_LIST_GRID], LMSG_SETCONTROLDATA, 0, iProgramTotal); } for (i = 0; i < iProgramTotal; i++) { if (pServiceInfo[i] != NULL) { sk_mem_free(pServiceInfo[i]); pServiceInfo[i] = NULL; } }上面代码的目的是把指针数组(一个数组,数组的每个元素是指向 SKY_SERVICE_INFO 结构体类型的指针)pServiceInfo 所指向的结构体 按照结构体某个成员来排列,
最后 pServiceInfo 是无用的,有用的仅仅是channel数组(pServiceInfo 通过一定规则排序之后ID与channel对应)
再看下 sk_char_service_id 函数
void sk_char_service_id(SKY_SERVICE_INFO *service_info[], int n)//沉底法则 { int i = 0, j = 0, iFlag = 0; SKY_SERVICE_INFO tmpe_service_info = {0}; for (i = 0; i < n - 1; i++) { iFlag = 1; memset(&tmpe_service_info, 0, sizeof(SKY_SERVICE_INFO)); for (j = 0; j < n - i - 1; j++) { if (str_order_service_id(service_info[j]->svid, service_info[j+1]->svid) == 0) { memcpy(&tmpe_service_info, service_info[j], sizeof(SKY_SERVICE_INFO)); memcpy(service_info[j], service_info[j+1], sizeof(SKY_SERVICE_INFO)); memcpy(service_info[j+1], &tmpe_service_info, sizeof(SKY_SERVICE_INFO)); iFlag = 0; } } if (1 == iFlag) { break; } } }这里用的只是简单的冒泡排序,而且if里面的交换也有很大优化空间
3次 memcpy 的过程仅仅是让指针 service_info[j] 和指针 service_info[j+1] 指向的内容一致,这3次memcpy可能需要大量的cpu周期,如果采用别的办法,
比如说交换 service_info[j] 和 service_info[j+1] 的指针值那么则可以大大减少cpu周期,采用这种方式之后 sk_char_service_id 函数如下所示:
void sk_char_service_id(SKY_SERVICE_INFO *service_info[], int n)//沉底法则 { int i = 0, j = 0, iFlag = 0; SKY_SERVICE_INFO *ptmp_service_info = NULL; for (i = 0; i < n - 1; i++) { iFlag = 1; for (j = 0; j < n - i - 1; j++) { if (str_order_service_id(service_info[j]->svid, service_info[j+1]->svid) == 0) { ptmp_service_info = service_info[j]; service_info[j] = service_info[j+1]; service_info[j+1] = ptmp_service_info; iFlag = 0; } } if (1 == iFlag) { break; } } }
另外还有优化的余地,那就是把排序方式改成快速排序。
相关文章推荐
- 排序算法(交换排序)——冒泡排序
- 交换排序------冒泡排序
- 交换排序(冒泡排序,快速排序)
- 交换排序(冒泡排序)
- 简单排序算法:冒泡排序(交换排序)
- 交换排序-冒泡排序
- 交换排序——冒泡排序
- 交换排序之冒泡排序与快速排序
- 交换排序实现(冒泡排序,快速排序)
- 简单的排序算法——插入排序,选择排序,交换排序(冒泡排序,快速排序)
- Java排序算法(六)--冒泡排序(交换排序)
- C/C++ 排序之一(冒泡排序、选择排序、交换排序)
- 简单的排序算法——插入排序,选择排序,交换排序(冒泡排序,快速排序)
- 交换排序(冒泡排序—改进、快速排序)
- 交换排序--冒泡排序和快速排序
- 交换排序—冒泡排序(Bubble Sort)
- 简单的排序算法——插入排序,选择排序,交换排序(冒泡排序,快速排序)
- 排序:交换排序(冒泡排序、快速排序)
- 交换排序中冒泡排序和快速排序的简单比较
- 交换排序——冒泡排序