C语言练习02:搜索质数之一

这个练习中,我们将基于《C语言练习01:单向链表的实现》中实现的链表程序实现一个搜索某一范围内所有质数的程序。

假定我们搜索的范围在DWORD(unsigned __int32)范围内。

2是唯一的偶数质数,2以后所以后的质数都是奇数。所以我们程序中搜索质数的时候没有从2开始,而是从3开始,并且每次递增的步长是2。

没有用埃拉托色尼筛选法。如果用埃拉托色尼筛选法的话速度更快,但是在这个练习中我用自己写的一个小小的算法作为一次锻炼。


以下是代码:


先给出现关的类型定义,免得读者简单那个奇怪的 Item 类型不知道是什么东西。

/*
 * CustomizedTypes.h
 * 
 * Customized types definition
 *
 * By Yaping Xin 110929
 *
 */

#ifndef _CustomizedTypes_H_
#define _CustomizedTypes_H_

/* typedef unsigned __int32 Item; */

typedef unsigned __int32 UInt32;

struct Item_Struct
{
	UInt32 data;
	UInt32 offset;
};

typedef struct Item_Struct Item;

Item CreateEmptyItem();
Item CreateItem(unsigned __int32 data);
int CompareItems(Item value0, Item value1);

typedef struct
{
	UInt32 x;
	UInt32 y;
} ItemPair;


#endif /* _CustomizedTypes_H_ */

/*
 * CustomizedTypes.c
 * 
 * Customized types implementation
 *
 * By Yaping Xin 110929
 *
 */

#include <string.h>
#include "CustomizedTypes.h"

Item CreateEmptyItem()
{
	Item result;
	result.data = 0;
	result.offset = 0;

	return result;
}

Item CreateItem(unsigned __int32 data)
{
	Item result;
	result.data = data;
	result.offset = data;

	return result;
}

int CompareItems(Item value0, Item value1)
{
	return memcmp(&value0, &value1, sizeof(Item));
}

好,下面就是正式的计算了:


// SearchPrime.c : Defines the entry point for the console application.
//

#include <stdio.h>
#include "CustomizedTypes.h"
#include "List.h"
#include <time.h>

UInt32 SqrtUInt32(UInt32 n)
{
	UInt32 a;
    for (a=0; n>=(2*a)+1; n-=(2*a++)+1);
    return a;
}

void SearchPrime(List *list, UInt32 vCurrent, UInt32 maxRange)
{
	UInt32 vNext;
	UInt32 vLimit;
	UInt32 vLimitRange;
	Node * node;

	if(vCurrent < 13)
	{
		vCurrent = 13;
	}

	if(vCurrent >= 0xFFFFFFFD)
	{
		return;
	}

	vNext = vCurrent + 2;
	if(vNext > maxRange)
	{
		return;
	}

	if(vNext >= 0xFFFE0001)
	{
		vLimit = 0x0000FFFF;
		vLimitRange = 0xFFFFFFFF;
	}
	else
	{
		vLimit = SqrtUInt32(vNext);
		vLimitRange = (vLimit + 1) * (vLimit + 1);
	}

	while(vNext <= maxRange)
	{
		for(node = list->begin; node != list->end; node = node->next)
		{
			if(node->item.data > vLimit)
			{
				break;
			}

			while(node->item.offset < vNext)
			{
				node->item.offset += node->item.data;
			}

			if(node->item.offset == vNext)
			{
				goto NEXT_INT;
			}
			
			/*
			if(vNext % node->item.data == 0)
			{
				goto NEXT_INT;
			}
			*/
		}

		ListAppendNode(list, CreateItem(vNext));

NEXT_INT:
		vNext += 2;
		if(vNext > vLimitRange)
		{
			vLimit ++;
			vLimitRange = (vLimit + 1) * (vLimit + 1);
		}
	}
}

int main(int argc, char* argv[])
{
	List list;
	long time_start;
	long time_end;
	UInt32 rangeBegin;
	UInt32 range;

	InitializeList(&list);

	ListAppendNode(&list, CreateItem(3));
	ListAppendNode(&list, CreateItem(5));
	ListAppendNode(&list, CreateItem(7));
	ListAppendNode(&list, CreateItem(11));
	ListAppendNode(&list, CreateItem(13));

	range = 0x0000FFFF;
	rangeBegin = 13;

	time_start = clock();
	SearchPrime(&list, rangeBegin, range);
	time_end = clock();

	printf("[R:%8X][C:%8X][V:%8X][T:%6ld]\n", range, list.count + 1, list.end->item.data, time_end - time_start);

	DisposeList(&list);
	return 0;
}

计算结果:

搜索 3 -- 0x0000FFFF 范围内的质数,在一台很普通的计算机上耗时3ms。(我相信绝大多数读者的计算机配置都不低于这台机器)


把 SearchPrime.c 中的变量range的值改为 0x000FFFFF,耗时65ms。


把 range 的值改为 0x00FFFFFF,耗时1862ms。


这个程序还能够继续优化吗?让我们把这项工作留到以后吧。

算法的解释暂略。这个计算速度比C语言入门教科书上的那些程序要高出好几个数量级,但相对于那些算法设计精良的程序来说,这个运算速度毫无可夸耀之处。仅仅是一次小练习而已。


你可能感兴趣的:(c,算法,struct,list,语言,Types)