大数据排序;冒泡排序优化方案

随机数写入文件

随机100000个数,写入到文件中,读取出来从小到大排序,写入文件。

写入文件中十万个数。

C语言做法:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <windows.h>   // 为了用Sleep。


int main(int argc, char* argv[])
{
	srand((unsigned int)time(NULL));
	clock_t StartTime, EndTime;
	StartTime = clock();
	FILE* fp = fopen("F:/Practice/ori", "w");
	if (!fp)
	{
		printf("打开文件失败。");
		return -1;
	}
	int sNum;

	printf("StartTime = %ld\n", StartTime);
	for (int i = 0; i < 100000; i++)
	{
		sNum = rand() % 100000 + 1;
		fprintf(fp, "%d\n", sNum);
	}
	fclose(fp);
	//Sleep(2000);
	EndTime = clock();
	printf("EndTime = %ld\n", EndTime);
	double UsedTime = (double)(EndTime - StartTime) * 1.0/ CLOCKS_PER_SEC;
	printf("写入十万个数耗时:%lf\n", UsedTime);   // 79ms


	getchar();
	return 0;
}

C#做法 

using System;
using System.Diagnostics;
using System.IO;

namespace 写入文件用时测试
{
    class Program
    {
        static void Main(string[] args)
        {
            //Console.WriteLine("Hello World!");
            Stopwatch sw = new Stopwatch();
            sw.Start();
            FileStream file = new FileStream(@"F:/Practice/Sharp", FileMode.OpenOrCreate, FileAccess.Write);
            StreamWriter wf = new StreamWriter(file);
            Random rd = new Random(Environment.TickCount);
            int sjs = rd.Next(1, 10000);
            for (int i = 0; i < 100000; i++)
            {
                sjs = rd.Next(1, 100000);
                wf.WriteLine(sjs);
            }
            wf.Flush();
            wf.Close();
            file.Close();
            sw.Stop();
            TimeSpan ts2 = sw.Elapsed;
            Console.WriteLine("span time {0}ms", ts2.TotalMilliseconds);
            Console.ReadLine();// 15.7ms

        }
    }
}

结果发现C还不如C#快,我也不知道怎么回事。但是我想fprintf这个函数是不是不如C#的WriteLine快呀。我们把fprintf也换成C语言的写入写入行fputs。

但是需要将整数修改为string类型。用_itoa函数。试试。

for (int i = 0; i < 100000; i++)
{
	sNum = rand() % 100000 + 1;
	//fprintf(fp, "%d\n", sNum);
	//_itoa(sNum, num, 10);  // 这个无法自动换行。
	sprintf(num, "%d\n", sNum);
	fputs(num, fp);
}

这次是64ms。没办法了,尽力了。

试试大哥C++版本的。

#include <fstream>
#include <iostream>
#include <windows.h>
using namespace std;

int main()
{

	srand(unsigned(time(0)));
	int number = rand() % 100000 + 1;
	
	DWORD start, end;
	start = GetTickCount64();
	ofstream ofs;
	ofs.open("F:/Practice/Cplus", ios::out);

	for (int i = 0; i < 100000; i++)
	{
		number = rand() % 100000 + 1;
		ofs << number << endl;
	}
	ofs.close();

	end = GetTickCount64();
	cout << end - start << endl;

	system("pause");
	return 0;
}

1069ms更拉垮了。算了。咱们继续学C。


排序和排序优化

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main01(int argc, char* argv[])
{
	srand((unsigned int)time(NULL));
	FILE* fp = fopen("F:/Practice/ori", "w");
	if (!fp)
	{
		printf("打开文件失败。");
		perror("打开文件失败。");
		return -1;
	}

	for (int i = 0; i < 100000; i++)
	{
		fprintf(fp, "%d\n", rand() % 10000 + 1);
	}
	fclose(fp);

	//getchar();
	return 0;
}

int main()
{
	unsigned int start_time = time(NULL);
	FILE* fp = fopen("F:/Practice/ori", "r");
	if (!fp)
	{
		printf("打开文件失败。");
		return -1;
	}
	int* p = (int*)malloc(sizeof(int) * 100000);
	for (int i = 0; i < 100000; i++)
	{
		fscanf(fp, "%d\n", &p[i]);
	}
	//for (int i = 0; i < 100000; i++)
	//{
	//	printf("%d\n", p[i]);
	//}
	//printf("排序前打印结束。\n");
	//getchar();
	for (int i = 0; i < 100000 - 1; i++)
	{
		int count = 0;

		for (int j = 0; j < 100000 - i - 1; j++)
		{
			if (p[j] > p[j + 1])
			{
				int temp = p[j];
				p[j] = p[j + 1];
				p[j + 1] = temp;
				count = 1;
			}
		}
		if (count == 0)	//如果某一趟没有交换位置,则说明已经排好序,直接退出循环
			break;
	}

	fclose(fp);
	fp = fopen("F:/Practice/ori", "w");
	if (!fp)
	{
		printf("打开文件失败。");
		return -1;
	}
	for (int i = 0; i < 100000; i++)
	{
		//printf("%d\n", p[i]);
		fprintf(fp, "%d\n", p[i]);
	}

	fclose(fp);
	free(p);
	//printf("程序运行结束。");
	unsigned int end_time = time(NULL);
	printf("运行时间:%d(s)\n", end_time - start_time);
	getchar();
	return 0;
}


对冒泡排序的优化

对于冒泡排序,并非一定需要全数全序遍历完,只要一次排序成功,后续都是重复,可以提前终止。加入某次排序没有移动数据,那么可以认为排序终止。

for (int i = 0; i < 100000 - 1; i++)
{
	int count = 0;

	for (int j = 0; j < 100000 - i - 1; j++)
	{
		if (p[j] > p[j + 1])
		{
			int temp = p[j];
			p[j] = p[j + 1];
			p[j + 1] = temp;
			count = 1;
		}
	}
	if (count == 0)	//如果某一趟没有交换位置,则说明已经排好序,直接退出循环
		break;
}

用时22s。 



另一种优化方案:

int main()
{
	unsigned int start_time = time(NULL);
	FILE* fp = fopen("F:/Practice/ori", "r");
	if (!fp)
	{
		return -1;
	}

	int pos[10000] = { 0 };
	int value = 0;
	for (int i = 0; i < 100000; i++)
	{
		fscanf(fp, "%d\n", &value);
		pos[value - 1]++;
	}// 相当于完成了排序。
	fclose(fp);

	fp = fopen("F:/Practice/ori", "w");
	if (!fp)
	{
		return -1;
	}

	int sum = 0;
	// 打印输出
	for (int i = 0; i < 10000; i++)
	{
		sum += pos[i];
		for (int j = 0; j < pos[i]; j++)
		{
			fprintf(fp, "%d\n", i + 1);
		}
	}
	printf("总数为:%d\n", sum);

	fclose(fp);
	unsigned int end_time = time(NULL);
	printf("运行时间:%d(s)\n", end_time - start_time);

	getchar();
	return 0;
}

知道是每个数都会出现,然后统计个数。不用搬运move运算。省时省力。算法执行时间1秒。

一下子,提升了是几十倍不止。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值