堆排序和歸併排序筆記

堆排序

堆排序是對選擇排序的改進 時間複雜度是 O(nlogn),大概思路是:

  1. 將待排序的數列構造成大頂堆或者小頂堆 大頂堆就是每個結點的值大於左右孩子的值
  2. 此時,整個數列的最大值就是堆頂的根節點(將其與末尾交換)
  3. 然後將剩餘的n-1個序列重新構造成一個堆
  4. 反覆進行
    上代碼:
/*
 ============================================================================
 Name        : HeapSort.c
 Author      : liuxin
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include<stdio.h>

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

void HeapAdjust(int a[],int s,int n)
{
	int i,temp;
	temp = a[s];  //temp存放雙親結點
	for(i=2*s;i<=n;i=i*2)    //2*s代表左結點
	{
		if(i<n && a[i]<a[i+1])   //i+1代表右結點
		{
			i++;
		}
		if(temp>a[i])
		{
			break;
		}
		a[s] = a[i];
		s = i;

	}
	a[s] = temp;
}

void HeapSort(int a[],int n)
{
	int i;

	for(i=n/2;i>0;i--)
	{
		HeapAdjust(a,i,n);  //構建大頂堆,其中i是雙親結點,n是總個數
	}


	for(i=1;i<9;i++)              //把第一次構建出來的大頂堆打印出來了
	{
		printf("%d ",a[i]);
	}
	printf("\n");

	for(i=n;i>1;i--)
	{
		swap(a,1,i);    //構建完大頂堆之後,第一個元素是最大的了,把他和最後的互換,然後在重新把剩下的構建大頂堆
		HeapAdjust(a,1,i-1);  //重新從第一個頂點開始構建
	}
}

int main()
{
	int i;
	int a[]={-1,1,3,2,6,5,4,8,7};         //從第一個元素開始排,因爲這樣正好2*i是左結點,2*i+1是右結點
	HeapSort(a,8);
	for(i=1;i<9;i++)
	{
		printf("%d ",a[i]);
	}
	return 0;
}

歸併排序

歸併排序(Merge Sort)就是利用歸併思想實現的排序算法,他的原理是假設初始序列有n個元素,可以看成有n個有序的子序列,每個子序列的長度是1,然後歸併,得到n/2個長度爲2或者1的子序列,然後再兩輛歸併,反覆如此,直到得到一個長度爲n的有序序列位置。上圖:
在這裏插入圖片描述
遞歸實現代碼:

#include<stdio.h>
#define MAXSIZE 8

void merging(int *list1,int list1_size,int *list2,int list2_size)    //給兩個數組排序然後放一起放在list1中
{
	int i,j,k,m;
	i=j=k=0;
	int temp[MAXSIZE];

	while(i < list1_size && j < list2_size)
	{
		if(list1[i]<list2[j])
		{
			temp[k++] = list1[i++];
		}
		else
		{
			temp[k++] = list2[j++];
		}
	}
	while(i < list1_size)
	{
		temp[k++] = list1[i++];
	}
	while(j < list2_size)
	{
		temp[k++] = list2[j++];
	}
	for(m = 0;m < (list1_size+list2_size);m++)    
	{
		list1[m]=temp[m];
	}

}

void MergeSort(int a[],int n)    //遞歸實現
{
	if(n>1)
	{
		int *list1 = a;
		int list1_size = n/2;
		int *list2 = a+n/2;
		int list2_size = n - list1_size;

		MergeSort(list1,list1_size);
		MergeSort(list2,list2_size);

		merging(list1,list1_size,list2,list2_size);

	}	

}

int main()
{
	int a[]={5,2,9,1,4,7,8,3};
	int i;
	MergeSort(a,8);

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

把這兩個排序算法放在一起寫是因爲這兩個排序算法無論是在最壞情況,最好情況,平均情況下時間複雜度都是O(nlogn),都是十分好的排序算法,則兩個相比而言,歸併排序穩定,堆排序不穩定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章