1. 程式人生 > >資料結構與演算法學習--排序

資料結構與演算法學習--排序

排序是最基本的演算法,在專案開發中經常遇到,也是面試環節中考察最多的。 在這裡插入圖片描述 1、冒泡、插入、選擇三種排序的比較及程式碼實現 “有序度”和“逆序度”:對於一個不完全有序的陣列,如4,5,6,3,2,1,有序元素對為3個(4,5),(4,6),(5,6),有序度為3,逆序度為12;對於一個完全有序的陣列,如1,2,3,4,5,6,有序度就是n*(n-1)/2,也就是15,稱作滿有序度;逆序度=滿有序度-有序度;氣泡排序、插入排序交換(或移動)次數=逆序度。 最好情況下初始有序度為n*(n-1)/2,最壞情況下初始有序度為0,則平均初始有序度為n*(n-1)/4,即交換次數為n*(n-1)/4,因交換次數<比較次數<最壞情況時間複雜度,所以平均時間複雜度為O(n^2)。 在這裡插入圖片描述

思考題: 1、氣泡排序和插入排序時間複雜度都是0(n^2),都是穩定性及原地排序。為什麼插入排序效率更高一些。 從資料分析,原始資料的逆序度時固定的。兩種排序在交換和移動的次數是一致的。 從程式碼分析上看,氣泡排序的資料交換要比插入排序的資料移動要複雜,氣泡排序需要3個賦值操作,而插入排序只需要1個,所以在對相同陣列進行排序時,氣泡排序的執行時間理論上要長於插入排序。 2、我們一般排序都是使用陣列來實現的,如果使用連結串列,排序工作如果實現呢。 覺得應該有個前提,是否允許修改連結串列的節點value值,還是隻能改變節點的位置。一般而言,考慮只能改變節點位置,氣泡排序相比於陣列實現,比較次數一致,但交換時操作更復雜;插入排序,比較次數一致,不需要再有後移操作,找到位置後可以直接插入,但排序完畢後可能需要倒置連結串列;選擇排序比較次數一致,交換操作同樣比較麻煩。綜上,時間複雜度和空間複雜度並無明顯變化,若追求極致效能,氣泡排序的時間複雜度係數會變大,插入排序係數會減小,選擇排序無明顯變化。

/*************************************************************************
 > File Name: sorts_jinshaohui.c
 > Author:  jinshaohui
 > Mail:    [email protected]
 > Time:    18-10-19
 > Desc:    
 ************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define SWAP(a,b) \
do{\
	(a) ^= (b);\
	(b) ^= (a);\
	(a) ^= (b);\
}while(0)

/*氣泡排序*/
void bubble_sort(int a[],int size)
{
	int i = 0;
	int j = 0;
	int swap_flg = 0;

	if (size < 1)
	{
		return;
	}

	for (i = size - 1; i > 0; i--)/*排序的趟數*/
	{
		swap_flg = 0;/*每次設定交換標識為0*/
		for (j = 0; j < i; j++)/*本趟排序的遍歷元素個數*/
		{
			if (a[j] > a[j + 1])
			{
				SWAP(a[j],a[j+1]);
				swap_flg = 1;
			}
		}
        /*本趟數,無資料交換的話,說明已經有序,直接退出*/
		if (swap_flg == 0)
		{
			break;
		}
	}
	return;
}

/*插入排序*/
void insert_sort(int a[],int size)
{
	int i = 0;
	int j = 0;
	int key = 0;

	for (i = 1; i < size; i ++)/*需要插入的元素個數*/
	{
		key = a[i];/*儲存插入的元素資料*/
		j = i - 1;
        /* i 之前的元素都是有序的,找到比key小的插入到他後面,
		 * 比key大的,需要往後挪一個位置*/
		while((j >= 0) && (a[j] > key))
		{
		    a[j + 1] = a[j];
			j--;
		}
		a[j + 1] = key;
	}

    return;
}
/*選擇排序*/
void select_sort(int a[],int size)
{
	int i = 0;
	int j = 0;
	int min = 0;

	for (i = 0; i < size - 1; i++) 
	{
		min = i;
        for (j = i + 1; j < size; j++)
		{
			if (a[j] < a[min])
			{
				min = j;
			}
		}

		if (min != i)
		{
			SWAP(a[i],a[min]);
		}
	}
	return;
}

void dump(int a[],int size)
{
	int i = 0;

	printf("\r\n");
	for (i = 0; i < size; i++ )
	{
		printf("%d ",a[i]);
	}
	printf("\r\n");
    return;
}

int main()
{
	int a[10] = {9,11,4,15,16,3,20,44,5,10};

    //bubble_sort(a,sizeof(a)/sizeof(int));
    //insert_sort(a,sizeof(a)/sizeof(int));
    select_sort(a,sizeof(a)/sizeof(int));
    
    dump(a,sizeof(a)/sizeof(int));

	return 0;
}