您的位置:首页 > 其它

交换排序与冒泡排序

2014-11-13 19:57 197 查看
今天在读公司的平台代码的时候发现了一处排序的地方,令我意外的是居然还在用最原始的时间复杂度为的 O(n的平方) 排序方式。

刚看到那些代码无法分清究竟是 交换排序 还是 冒泡排序,记得有一次面试的时候让写冒泡排序呢结果写成交换排序了,当时怎么想也想不起来惭愧,

回来后看了一眼才恍然大悟。其实这两个都是课堂上学过的。这里有必要再分析下它们的区别:

首先说冒泡排序:

将被排序的记录数组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;
		}
	}
}


另外还有优化的余地,那就是把排序方式改成快速排序。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: