【資料結構】 各種排序演算法的實現

球王武磊發表於2020-12-23

資料結構實驗 各種排序演算法的實現

實驗內容
本人完成了直接插入排序,折半插入排序,希爾排序,氣泡排序,快速排序,選擇排序,歸併排序(分別用迭代和遞迴兩種方式實現),堆排序。程式能夠輸出各種排序的中間步驟變化情況,以及最後得到正確的排序結果。

實驗程式碼:

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
typedef int T;

void print(T a[],const int n)
{
	for(int i=0;i<n;i++)
		printf("%d ",a[i]);
	printf("\n");
}

void insert_sort(T a[],int n)//直接插入排序 
{
	for(int i=1;i<n;i++)
	{
		if(a[i]<a[i-1])
		{
			T t=a[i];
			a[i]=a[i-1];
			int j;
			for(j=i-2;j>=0&&t<a[j];j--)
				a[j+1]=a[j];
			a[j+1]=t;
		}
	print(a,n);
	}
}


void binary_insert_sort(T a[],int n)//折半插入排序 
{
	int l,h,m,j;
	for(int i=1;i<n;i++)
	{
		T t=a[i];
		if(a[i]<a[i-1])
		{
			l=0;h=i-1;
			while(l<=h)
			{
				m=(l+h)/2;
				if(t<a[m])
					h=m-1;
				else
					l=m+1;
			}
			for(j=i-1;j>=h+1;j--)
				a[j+1]=a[j];
			a[h+1]=t;
		}
		print(a,n);
	}
}//二分插入 


void shell_insert(T a[],int n,int d)
{
	for(int i=d;i<n;i++) 
	{
		if(a[i]<a[i-d])
		{
			T t=a[i];
			a[i]=a[i-d];
			int j;
			for (j=i-2*d;j>=0&&t<a[j];j-=d)
				a[j+d]=a[j];
			a[j+d]=t;
		}
	}//對順序表a作一趟希爾插入排序,和直接插入排序的區別是前後記錄位置的增量是d而不是1 
}

void shell_sort(T a[], int n)//希爾排序 
{
	int d[]={5,3,1};//增量序列 
	for(int i=0;i<3;i++)
	{
		shell_insert(a,n,d[i]);
		print(a,n);
	}
}


void swap(T &a, T &b)
{
	//T t=a;a=b;b=t;
	a=a^b;
	b=a^b;
	a=a^b;//用位運算交換兩個變數的值,則不需要用到額外的變數t 
}

void bubble_sort(T a[],int n)//氣泡排序 
{
	for(int i=n-1;i>0;i--)
	{
		int flag=0;
		for(int j=0;j<i;j++)
			if(a[j+1]<a[j])
			{
				swap(a[j+1],a[j]);
				flag=1;
			}
		if(flag==0) break;
		print(a,n);
	}
}


int partition(T a[],int L,int H)
{
	T t=a[L];
	while(L<H)//從表的兩端交替地向中間掃描 
	{
		while(L<H&&a[H]>=t)
			H--;
		a[L]=a[H];//將比樞軸記錄小的記錄移到低端 
		while(L<H&&a[L]<=t)
			L++;
		a[H]=a[L];//將比樞軸記錄大的記錄移到高階 
	}
	a[L]=t;
	return L;
}//交換順序表a中子表a[L-H]的記錄,樞軸記錄到位,並返回其所在位置 

void Qsort(T a[],int L,int H)
{
	if(L<H)
	{
		int loc=partition(a,L,H);//樞軸位置,將當前陣列一分為二 
		Qsort(a,L,loc-1);//對低子表遞迴排序 
		Qsort(a,loc+1,H);//對高子表遞迴排序 
	}
}

void quick_sort(T a[],int n)//快速排序 
{
	Qsort(a,0,n-1);
}


void select_sort(T a[], int n)//選擇排序 
{
	int minn=0;
	for (int i=0;i<n-1;i++)
	{
		minn=i;
		for(int j=i+1;j<n;j++)
			if(a[j]<a[minn]) minn=j;
		if (minn!=i)
			swap(a[i],a[minn]);
		print(a,n);
	}
}


void merge(const T data[],T out[],int s,int M,int N)
{
	int i=s,j=M+1,k=s;
	while (i<=M&&j<=N)
	{
		if(data[i]<data[j])
			out[k++]=data[i++];
		else 
			out[k++]=data[j++];
	}
	while(i<=M) out[k++]=data[i++];
	while(j<=N) out[k++]=data[j++];
}

int min(int a,int b)
{
	return a<b?a:b;
}

void copy(T A[],T B[],int n)
{
	for(int i=0;i<n;i++)
		B[i]=A[i];
}

void merge_sort_iter(T A[],T B[],int n)//迭代歸併排序 
{
	for(int width=1;width<n;width*=2)
	{
		for(int i=0;i<n;i=i+2*width)
			merge(A,B,i,i+width-1,min(i+2*width-1,n-1));
		copy(B,A,n);
		print(B,n);
	}
}

void copy2(T A[],T B[],const int s,const int t)
{
	for(int i=s;i<=t;i++)
		B[i]=A[i];
}

void merge_sort_recursive(T A[],T B[],const int s,const int t)//遞迴歸併排序 
{
	if(s==t) return;
	merge_sort_recursive(A,B,s,(s+t)/2);
	merge_sort_recursive(A,B,(s+t)/2+1,t);
	merge(A,B,s,(s+t)/2,t);
	copy2(B,A,s,t);
}


void heap_adjust(T data[],int s,int n)
{
	if(2*s+1>=n) return;
	T t=data[s];
	int m=n-1;
	for(int j=2*s+1;j<n;)
	{
		if(j<m&&data[j]<data[j+1])
			j++;//j指向較大的孩子 
		if(!(t<data[j])) break;
		data[s]=data[j];
		s=j;j=2*j+1;
	}
	data[s]=t;
}

void heap_sort(T a[],int n)
{
	for(int i=floor((n-1-1)/2);i>=0;i--)
		heap_adjust(a,i,n);
	for(int i=n-1;i>0;i--)
	{
		swap(a[0],a[i]);//將a[0]和a[i]交換 
		heap_adjust(a,0,i);
	}
}

int main()
{
	int num[]={49,38,65,97,76,13,27};//資料測試 
	int arr[7];
	
	for(int i=0;i<7;i++)
		arr[i]=num[i];
	printf("原陣列為:");
	print(arr,7);
	printf("直接插入排序:\n");
	insert_sort(arr,7);//直接插入排序 
	printf("直接插入排序的結果為:");
	print(arr,7);
	printf("\n");
	
	for(int i=0;i<7;i++)
		arr[i]=num[i];
	printf("原陣列為:");
	print(arr,7);
	printf("折半插入排序:\n");
	binary_insert_sort(arr,7);//折半插入排序 
	printf("折半插入排序的結果為:");
	print(arr,7);
	printf("\n");
	
	for(int i=0;i<7;i++)
		arr[i]=num[i];
	printf("原陣列為:");
	print(arr,7);
	printf("希爾排序:\n");
	shell_sort(arr,7);//希爾排序 
	printf("希爾排序的結果為:");
	print(arr,7);
	printf("\n");
	
	for(int i=0;i<7;i++)
		arr[i]=num[i];
	printf("原陣列為:");
	print(arr,7);
	printf("氣泡排序:\n");
	bubble_sort(arr,7);//氣泡排序 
	printf("氣泡排序的結果為:");
	print(arr,7);
	printf("\n");
	
	for(int i=0;i<7;i++)
		arr[i]=num[i];
	printf("原陣列為:");
	print(arr,7);
	printf("快速排序:\n");
	quick_sort(arr,7);//快速排序 
	printf("快速排序的結果為:");
	print(arr,7);
	printf("\n");
	
	for(int i=0;i<7;i++)
		arr[i]=num[i];
	printf("原陣列為:");
	print(arr,7);
	printf("選擇排序:\n");
	select_sort(arr,7);//選擇排序 
	printf("選擇排序的結果為:");
	print(arr,7);
	printf("\n");
	
	T out[7];
	for(int i=0;i<7;i++)
		arr[i]=num[i];
	printf("原陣列為:");
	print(arr,7);
	printf("迭代歸併排序:\n");
	merge_sort_iter(arr,out,7);//迭代歸併排序 
	printf("迭代歸併排序的結果為:");
	print(arr,7);
	printf("\n");
	
	for(int i=0;i<7;i++)
		arr[i]=num[i];
	printf("原陣列為:");
	print(arr,7);
	merge_sort_recursive(arr,out,0,6);//遞迴歸併排序 
	printf("遞迴歸併排序的結果為:");
	print(arr,7);
	printf("\n");
	
	for(int i=0;i<7;i++)
		arr[i]=num[i];
	printf("原陣列為:");
	print(arr,7);
	printf("堆排序:\n");
	heap_sort(arr,7);//堆排序 
	printf("堆排序的結果為:");
	print(arr,7);
	printf("\n");
	
	return 0;
}

執行結果截圖:
在這裡插入圖片描述
在這裡插入圖片描述

各種常用排序演算法的比較:
在這裡插入圖片描述

問題解決和心得記錄

這是我的第十次資料結構課程實驗,也是本學期的最後一次資料結構實驗了。本人完成了各種排序方式的比較,包括直接插入排序,折半插入排序,希爾排序,氣泡排序,快速排序,選擇排序,歸併排序(分別用迭代和遞迴兩種方式實現),堆排序。程式能夠輸出各種排序的中間步驟變化情況,以及最後得到正確的排序結果。通過程式碼實現這些排序演算法,讓我對其有了更深入的認識和理解。

不知不覺中,本學期已經臨近尾聲。一個學期的學習和積累讓我能夠感受到自己程式設計能力的提升,真的非常有收穫。資料結構是非常重要的專業核心課程,要感謝老師用心的指導,我將在後續的學習中再接再厲,認真複習準備期末考試,爭取能夠以一個理想的成績為本學期畫上一個圓滿的句號。

相關文章