1. 程式人生 > >歸併排序和快速排序比較【演算法設計與分析實驗報告】

歸併排序和快速排序比較【演算法設計與分析實驗報告】

       下面的原始碼是修改的了時間差精確到了納秒級別的了,但是還是感覺很有誤差。無論怎麼測,總是快排比歸併快,即使是測試資料的陣列長度在10以內。

        前面一樣的程式寫的是時間精確到微秒級的,陣列長度大概在一萬以內的,就是歸併排序快了,大於這個長度的快速排序比較快。綜合上面的情況,陣列小時,二者時間差也不會太多,所以個人認為還是快速排序比較好了,唉還是覺得歸併比較簡單好寫,弱爆了啊。。。

#include<cstdio>
#include<Windows.h>
#include<ctime>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;

const int maxn = 100000000;     /* maxn 為陣列最大值 */
/*
*a[]為隨機產生的陣列 , b[]複製隨機陣列,t[]用於歸併排序,暫時儲存a[]
*/
int a[maxn];
int b[maxn], t[maxn];
int n;                        /* n為要比較的數的個數 */

/*
*對陣列下標從 p到r之間的數進行排序
*使得前面的數全都不大於基準元, 後面的數不小於基準元
*/
int partition(int p, int r)
{
	int i = p;
	int j = r+1;
	int x = a[p];

	while(true)
	{
		while(a[++i] < x && i < r);
		while(a[--j] > x);

		if(i >= j) break;

		//swap(a, i, j);
		int temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}

	a[p] = a[j];
	a[j] = x;
	return j; /* 返回基準元排好序後的位置 */
}

int randomizedPartition(int p, int r) /* 對基準元進行處理 */
{
	int i = rand() % (r-p+1) + p; /* 產生p 到 q 之間的隨機數 i */

	int temp = a[i];    /* 交換隨機位置到開始位置,使其成為基準元 */
	a[i] = a[p];
	a[p] = temp;

	return partition(p, r);
}

void randomizedQuickSort(int p, int r) /* 快速排序 */
{
	if(p < r)
	{
		int q = randomizedPartition(p, r); /* 分割 */
		randomizedQuickSort(p, q-1);      /* 從兩邊分別排序 */
		randomizedQuickSort(q+1, r);
	}
}

void merge_sort(int *a, int x, int y, int *t) /* 歸併排序 */
{
	if(y-x > 1)
	{
		int m = (y-x)/2 + x;       /* 取中間 */
		int p = x, q = m, i = x;

		merge_sort(b, p, m, t);   /* 兩邊分別排序 */
		merge_sort(b, m, y, t);

		while(p < m && q < y)
		{
			if(b[p] <= b[q]) t[i++] = b[p++];
			else t[i++] = b[q++];
		}

		while(p < m) t[i++] = b[p++];
		while(q < y) t[i++] = b[q++];

		for(i = x; i < y; i++) /* 將排序好的部分重新存入陣列 a[]*/
			b[i] = t[i];
	}
}

int main()
{
    printf("請輸入要排序比較的個數 n ( n <= 100000000 ): ");
    while(scanf("%d", &n) != EOF)
    {
        LARGE_INTEGER begin, end;
        //double tstart, tend, MergeSortCost, QuickSortCost;
        long long  MergeSortCost, QuickSortCost;

        memset(a, 0, sizeof(a));       /* 清空陣列為0 */
        for(int i = 0; i < n; i++)    /* 生成隨機數 */
        {
            a[i] = rand();
            b[i] = a[i];
        }

        QueryPerformanceCounter(&begin); // tstart = clock();
        randomizedQuickSort(0, n-1); /* 快速排序 */
        QueryPerformanceCounter(&end); //tend = clock();

        QuickSortCost = end.QuadPart - begin.QuadPart; //tend - tstart;
        //for(int i = 0; i < n; i++) printf("%d ", a[i]);


        QueryPerformanceCounter(&begin); //tstart = clock();
        merge_sort(b, 0, n, t); /* 歸併排序 */
        QueryPerformanceCounter(&end); //tend = clock();

        MergeSortCost = end.QuadPart - begin.QuadPart; //tend - tstart;
        //for(int i = 0; i < n; i++) printf("%d ", b[i]);

        printf("快速排序耗時:%lld ns,歸併排序耗時:%lldns\n\n\n", QuickSortCost*100, MergeSortCost*100);


        printf("如果要繼續比較請繼續輸入比較的個數 n : ");

    }
    return 0;
}
下面截個納秒級別的,感覺不是很精確的圖吧.

通過此次演算法分析兩種排序方法的比較,我還學到了一些簡單的頭函式的使用.

一、關於隨機數的產生。

/*
*產生區間[a , b]之間的隨機整數
*/
#include<cstdio>
#include<cstdlib>
int main()
{
	int a,b;
	while(scanf("%d%d", &a, &b) != EOF)
	{
		int ans = rand()%(b-a+1) + a;
		printf("%d\n", ans);
	}
	return 0;
	
}


二、如何測試系統當前時間。

/*
*微秒級時間測試
*/
#include <time.h>  //time.h是C/C++中的日期和時間標頭檔案
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
    double tstart, tend, tcost;

    tstart = clock();
    for(int i=0;i<10000000;i++); //do something
        tend = clock();
    tcost = (double)(tend-tstart)/CLOCKS_PER_SEC;

    printf("%lf\n", tcost);
    cout<<CLOCKS_PER_SEC; // == 1000 ms
    return 0;
}


/*
*納秒級時間測試一 ,來自周杰學長
*/
#include <Windows.h>
#include <stdio.h>

int main()
{
	LARGE_INTEGER li;
	QueryPerformanceCounter(&li);
	printf("%lld\n", li);
	QueryPerformanceCounter(&li);
	printf("%lld\n", li);
	return 0;
}


/*
*納秒級時間測試二 :測試用時 ,來自周杰學長
*/
#include <Windows.h>
#include <stdio.h>

int main()
{
	LARGE_INTEGER begin, end;
	QueryPerformanceCounter(&begin);
	Sleep(0); // do something
	QueryPerformanceCounter(&end);
	long long duration = end.QuadPart - begin.QuadPart;
	printf("duration: %lldns\n", duration * 100);
    return 0;
}


相關推薦

歸併排序快速排序比較演算法設計分析實驗報告

       下面的原始碼是修改的了時間差精確到了納秒級別的了,但是還是感覺很有誤差。無論怎麼測,總是快排比歸併快,即使是測試資料的陣列長度在10以內。         前面一樣的程式寫的是時間精確到微秒級的,陣列長度大概在一萬以內的,就是歸併排序快了,大於這個長度的快速排

演算法設計分析實驗報告

實驗一 集合的表示與操作演算法設計 https://www.cnblogs.com/31415926535x/p/10963938.html 實驗目的 通過這次實驗瞭解體會並掌握基本的遞迴分治演算法以及貪心演算法的思想,並有能力解決一些具體的問題,通過c++來實現解題的過程,進一步的熟悉演算法的流程。 實驗內

演算法設計分析6、最大欄位

/** * 書本:《演算法分析與設計》 * 功能:若給定n個整陣列成的序列a1, a2, a3, ......an, 求該序列形如ai+a(i+1)+......+an的最大值 * 檔案:MaxSum.cpp * 時間:2014年11月30日17:37:26 * 作者:cu

演算法設計分析作業題第十一週:20. Valid Parentheses

題目 C++ solution class Solution { public: bool isValid(string s) { stack<char> cstack; for (int i = 0; i < s.si

演算法設計分析作業題第二週:1. Two Sum

題目 C++ solution class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { ve

演算法設計分析作業題第九周:17. Letter Combinations of a Phone Number

題目 C++ solution class Solution { public: vector<string> letterCombinations(string digits) { vector<string>

演算法設計分析作業題第十週:19. Remove Nth Node From End of List

題目 C++ solution /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListN

演算法設計分析貪心策略——最佳郵局設定問題

//總是感覺生活很空虛,就只能寫寫部落格看看書上上課這樣子。想出去,去一個遙遠的地方。先來看一下題目:有n戶人家坐落在從西向東的一條街上。從街西頭向東數,第i戶的房子與街西頭的距離是H[i]米,(1≤i≤n), H[1]< H[2] < H[3] … < H

Kruskal演算法求最小生成樹-演算法設計分析實驗3

題目: 求如圖所示,用kruskal演算法求下面圖的最小生成樹: 話不多說,程式如下: #include<iostream> #include<stdlib.h> #define N 7 using namespace std; typedef

資料結構演算法內部排序之四:歸併排序快速排序(含完整原始碼)

前言      之所以把歸併排序和快速排序放在一起探討,很明顯兩者有一些相似之處:這兩種排序演算法都採用了分治的思想。下面來逐個分析其實現思想。歸併排序實現思想       歸併的含義很明顯就是將兩個或者兩個以上的有序表組合成一個新的有序表。歸併排序中一般所用到的是2-路歸併

排序演算法中——歸併排序快速排序

氣泡排序、插入排序、選擇排序這三種演算法的時間複雜度都為 O (

排序演算法總結-選擇排序、插入排序歸併排序快速排序

  前言:   感覺好久沒寫部落格了,十月份的計劃是:要開始深入攻克資料結構和演算法,耽誤好久了,這都月末了,抓緊時間又學習了一波,趕緊來分享了一下,使用的語言是C++,最開始學資料結構一定要用C,掌握紮實之後,想學演算法,用C++比較好,C封裝沒有那麼好,寫起來沒有那麼容易了。   一、準備工作   

算法系列(四)排序演算法中篇--歸併排序快速排序

在算法系列(三)排序演算法上篇 一文中,介紹了氣泡排序,插入排序和選擇排序演算法。這篇文章繼續講解排序演算法。 概述 氣泡排序,插入排序和選擇排序演算法這些演算法的時間複雜度都是O(N^2),是否有更

歸併排序快速排序比較

1 . 歸併排序和快速排序 1.1 歸併排序 歸併排序的思想就是講陣列分為兩部分然後對兩部分進行排序,然後講排序後的兩部分進行合併,主要的難度在於合併部分,合併的時候需要重新開一個臨時陣列儲存合併的結果,然後再複製到原陣列. 下面是歸併排序的pytho

精華排序演算法彙總——氣泡排序快速排序

日常說明:有錯誤歡迎大家指正。另外本部落格所有的程式碼博主編寫後均除錯通過。重要提醒!!!!博主使用的是VS2017,如果有低版本的小夥伴最好新建空專案將此程式碼複製上去。 更多演算法請關注我的演算

歸併排序快速排序(三十二)

        上節我們學習了氣泡排序和希爾排序,本節我們繼續學習歸併排序和快速排序。         1、歸並排序:將兩個或兩個以上的有序序列

資料結構 筆記:歸併排序快速排序

歸併排序的基本思想 -將兩個或兩個以上的有序序列合併成一個新的有序序列 template < typename T> static void Merge(T src[] , T helper[],int begin,int mid,int end, bool mi

歸併排序快速排序計時計算——誰更快?

今天覆習了歸併和快排,突然想計算一下他們的速度差別到底有多大~結果還是挺令人意外的,哈哈。 話不多說,看程式碼。 let arr = []; for (let i = 0; i < 500000; i++) { arr.push(Math.r

排序演算法:氣泡排序、插入排序快速排序

筆試中經常有排序的演算法題,關於氣泡排序,這裡就不再細講了,具體方法很多種,直接上程式碼: //氣泡排序 (個人實現方法)         static void BubbleSort(int[] dataArray) {     &n

演算法分析設計實驗 分治策略 兩路合併排序快速排序

實驗目的理解分治法的演算法思想,閱讀實現書上已有的部分程式程式碼並完善程式, 加深對分治法 的演算法原理及實現過程的理解。實驗內容用分治法實現一組無序序列的兩路合併排序和快速排序。要求清楚合併排序及快速排序 的基本原理, 程式設計實現分別用這兩種方法將輸入的一組無序序列排序