數據結構-內部排序

內部排序算法

時間複雜度: O(n^2)  O(n^2)   O(n^2)

空間複雜度: O(1)    O(1)      O(1)

算法名稱:   插入     選擇     冒泡

 

算法名稱:   希爾    堆        快速         歸併     基數

空間複雜度:O(1)     O(1)       O(logn)     O(n)    O(2rd)

時間複雜度:O(nlogn) O(nlogn)  O(nlogn)    O(nlogn) O(d(n+rd))

 

穩定的:插入 冒泡 歸併 基數

其它:不穩定排序。

示列代碼:

#include<iostream>
#include<stdlib.h>
using namespace std;
#define MAXSIZE 500
typedef int KeyType;////定義關鍵字類型
typedef char InfoType;
struct RecType
{
	KeyType key;//關鍵字項
	InfoType data;//其他數據項,類型爲InfoType
}R[MAXSIZE],R1[MAXSIZE];

//插入排序

void StrInsSort(RecType R[],int n)//直接插入排序
{
	//時間複雜度O(n2)
	for(int i=2;i<=n;i++)
	{
		R[0]=R[i];//將待排序記錄放進監視哨
		int j=i-1;
		while(R[0].key<R[j].key)
		{
			R[j+1]=R[j];//記錄後移
			j--;
		}
		R[j+1]=R[0];//將待排序記錄放到合適位置
	}
}

void BinsSort(RecType R[],int n)//折半插入排序
{
	//折半插入排序僅僅是減少了關鍵字間的比較次數,
	//但是記錄移動的次數不變,所以時間複雜度仍然爲:O(n2)
	for(int i=2;i<=n;i++)
	{
		R[0]=R[i];
		int low=1,high=i-1;//設置折半查找的範圍
		while(low<=high)//折半查找插入位置
		{
			int m=(low+high)/2;
			if(R[0].key<R[m].key)high=m-1;
			else low=m+1;
		}
		for(int j=i-1;j>=high+1;j--)
			R[j+1] = R[j];//記錄後移
		R[high+1] = R[0];//插入
	}
}

void ShellSort(RecType R[],int n)//希爾排序
{
	//時間複雜度爲:O(n1.3)
	//Shell:d1=  n/2 , di+1=  di/2 ,最後一個取1
	for(int d=n/2;d>=1;d=d/2)
	{
		for(int i=1+d;i<=n;i++)
		{
			//將R[i]插入到所屬組的有序列段中,直接插入排序
			R[0]=R[i];
			int j=i-d;
			while(j>0&&R[0].key<R[j].key)
			{
				R[j+d]=R[j];//記錄後移,查找插入位置
				j=j-d;
			}
			R[j+d]=R[0];//將第i個元素插入到合適位置
		}
	}

}


//交換排序

void BubbleSort(RecType R[],int n)//起泡排序
{
	//時間複雜度O(n2)
	for(int i=1;i<n;i++)//最多n-1趟起泡
	{
		for(int j=1;j<=n-i;j++)//每趟都把最大的放在最後面
		{
			//兩兩比較,發現逆序立即交換
			if(R[j].key>R[j+1].key)
			{
				RecType temp = R[j];
				R[j]=R[j+1];
				R[j+1]=temp;
			}
		}
	}
}

void BubbleSort1(RecType R[],int n)//改進的起泡排序
{
	//時間複雜度O(n2)

	int i =n;//i指示無序序列中最後一個記錄的位置
	while(i>1)//冒泡排序的結束條件爲:最後一趟沒有進行交換
	{
		int lastExchange = 1;//記錄最後一次交換髮生的位置
		for(int j=1;j<i;j++)
		{
			if(R[j].key>R[j+1].key)
			{
				RecType temp = R[j];
				R[j]=R[j+1];
				R[j+1]=temp;
				lastExchange=j;
			}
		}
		i = lastExchange;
	}
}

//快速排序也叫分區交換排序

int Partition(RecType R[],int low,int high)
{
	//交換記錄子序列R[low..high]中的記錄,使樞軸記錄
	//到位並返回其 所在位置,此時,在它之前(後)的記錄均不大(小)於它
	R[0] = R[low];//以子表的第一個記錄作樞軸,將其暫存到記錄R[0]中
	int pivotkey = R[low].key;//樞軸記錄關鍵字
	while(low<high)
	{
		//從表的兩端交替地向中間掃描
		while(low<high && R[high].key>=pivotkey)high--;
		R[low] = R[high];//將比樞軸小的記錄移到低端
		while(low<high && R[low].key<=pivotkey)low++;
		R[high]=R[low];//將比樞軸大的記錄移到高端
	}
	R[low]=R[0];//樞軸記錄到位
	return low;//返回樞軸位置
}
void change(RecType R[],int low,int high)//快速排序前進行預處理
{
	//比較R[s].key和R[t].key和R[(s+t)/2].key,
	//然後取關鍵字爲“三者之中值”的記錄作爲樞軸記錄,將其與R[s]互換即可
	if(R[low].key>=R[high].key)
	{
		if(R[low].key>=R[(low+high)/2].key)
		{
			if(R[(low+high)/2].key>=R[high].key)
			{
				RecType temp = R[(low+high)/2];
				R[(low+high)/2] = R[low];
				R[low] = temp;
			}
			else
			{
				RecType temp = R[high];
				R[high] = R[low];
				R[low] = temp;
			}
		}
	}
	else
	{
		if(R[high].key>=R[(low+high)/2].key)
		{
			if(R[(low+high)/2].key>=R[low].key)
			{
				RecType temp = R[(low+high)/2];
				R[(low+high)/2] = R[low];
				R[low] = temp;
			}
		}
	}
}
void QSort(RecType R[],int low,int high)
{
	//對記錄序列R[low..high]進行快速排序
	if(low<high)//長度大於1
	{
		change(R,low,high);	//爲了避免出現一趟排序後記錄集中在樞軸一側的情況,快速排序前進行預處理
		int location = Partition(R,low,high);//獲得樞軸位置,將R[low..high]分成兩部分
		QSort(R,low,location-1);
		QSort(R,location+1,high);
	}
}

void QuickSort(RecType R[],int n)
{
	//時間複雜度nlogn
	//對記錄序列進行快速排序
	QSort(R,1,n);
}

//選擇排序

void SelectSort(RecType R[],int n)//直接選擇排序
{
	//時間複雜度O(n2)
	for(int i=1;i<n;i++)
	{
		//選擇第i小的記錄,並交換到位
		int k=i;//假定第i個元素的關鍵字最小
		for(int j=i+1;j<=n;j++)//找最小元素的下標
		{
			if(R[j].key<R[k].key)k=j;
		}
		if(i!=k)
		{
			RecType temp = R[i];
			R[i]=R[k];
			R[k]=temp;
		}
	}
}

void Sift(RecType R[],int i,int m)//調整堆的算法,篩選
{
	//假設R[i+1..m]中各元素滿足堆的定義,
	//本算法調整R[i]使序列R[i..m]中各元素滿足堆的性質
	R[0]=R[i];//暫存“根”記錄R[i]
	for(int j=2*i;j<=m;j*=2)//j<=m時,R[2i]是R[i]的左孩子
	{
		//若R[i]的右孩子存在,且關鍵字大於左孩子,j指向R[i]的右孩子
		//j指向關鍵字最大的孩子
		if(j<m&&R[j].key<R[j+1].key)j++;
		if(R[0].key<R[j].key)//孩子結點關鍵字較大
		{
			R[i]=R[j];//將R[j]換到雙親位置
			i=j;
		}
		else break;//調整完畢,退出循環
	}
	R[i]=R[0];//最初被調整結點放入正確位置
}
void HeapSort(RecType R[],int n)//堆排序
{
	//時間複雜度O(nlogn),待排序數目小的話不提倡用堆排序,因爲建堆太費時

	//對記錄序列R[1..n]進行堆排序。
	for(int i=n/2;i>0;i--)//把R[1..n]建成大頂堆,對於完全二叉樹,n/2正好是最後一個非葉子結點
	{
		Sift(R,i,n);
	}
	for(int j=n;j>1;j--)
	{
		//將堆頂記錄和當前未經排序子序列R[1..i]中
		//最後一個記錄相互交換
		RecType temp=R[1];
		R[1]=R[j];
		R[j]=temp;
		Sift(R,1,j-1);//將R[1..i-1]重新調整爲大頂堆
	}
}


//歸併排序

void Merge(RecType R[],RecType R1[],int i,int l,int h)
{
	//將有序的R[i..l]和R[l+1..h]歸併爲有序的R1[i..h]
	int j,k;
	for(j=l+1,k=i;i<=l&&j<=h;k++)
	{
		//將R中記錄由小到大地併入R1
		if(R[i].key<=R[j].key)R1[k]=R[i++];
		else R1[k]=R[j++];
	}
	if(i<=l)//將剩餘的R[i..l]複製到R1
	{
		for(;i<=l;i++)
		{
			R1[k++]=R[i];
		}
	}
	if(j<=h)//將剩餘的R[j..h]複製到R1
	{
		for(;j<=h;j++)
		{
			R1[k++]=R[j];
		}
	}
}
void Msort(RecType R[],RecType R1[],int s,int t)
{
	//將R[s..t]進行2-路歸併排序爲R1[s..t]
	RecType R2[MAXSIZE];
	if(s==t)R1[s]=R[s];//長度爲1
	else
	{
		int m=(s+t)/2;//將R[s..t]平分爲R[s..m]和R[m+1..t]
		Msort(R,R2,s,m);//遞歸地將R[s..m]歸併爲有序的R2[s..m]
		Msort(R,R2,m+1,t);//遞歸地將R[m+1..t]歸併爲有序的R2[m+1..t]
		Merge(R2,R1,s,m,t);//將R2[s..m]和R2[m+1..t]歸併到R1[s..t]
	}
}
void MergeSort(RecType R[],int n)//2-路歸併排序
{
	//時間複雜度O(nlogn)
	//對記錄序列R[1..n]作2-路歸併排序。
	//RecType R1[MAXSIZE];
	Msort(R,R1,1,n);
}
void select()
{
	cout<<"歡迎進入排序操作界面"<<endl;
	cout<<"1,初始化待排序的序列"<<endl;
	cout<<"2,直接插入排序"<<endl;
	cout<<"3,折半插入排序"<<endl;
	cout<<"4,希爾排序"<<endl;
	cout<<"5,起泡排序"<<endl;
	cout<<"6,改進的起泡排序"<<endl;
	cout<<"7,快速排序"<<endl;
	cout<<"8,直接選擇排序"<<endl;
	cout<<"9,堆排序"<<endl;
	cout<<"10,二路歸併排序"<<endl;
	cout<<"11,輸出序列"<<endl;
	cout<<"0,退出"<<endl;
}
int main()
{
	int n,i=0,flg=0,op;
	select();
	while(1)
	{
		cout<<"輸入操作序號"<<endl;
		cin>>op;
		switch(op)
		{
		case 0:exit(0);break;
		case 1:
			cout<<"輸入待排序的數字的個數:"<<endl;
			cin>>n;
			cout<<"依此輸入數字"<<endl;
			for(i=1;i<=n;i++)
			{
				cin>>R[i].key;
			}
			cout<<"序列初始化完成"<<endl;break;
		case 2:StrInsSort(R,n);cout<<"直接插入排序完成"<<endl;break;
		case 3:BinsSort(R,n);cout<<"折半插入排序完成"<<endl;break;
		case 4:ShellSort(R,n);cout<<"希爾排序完成"<<endl;break;
		case 5:BubbleSort(R,n);cout<<"起泡排序完成"<<endl;break;
		case 6:BubbleSort1(R,n);cout<<"改進後的起泡排序完成"<<endl;break;
		case 7:QuickSort(R,n);cout<<"快速排序完成"<<endl;break;
		case 8:SelectSort(R,n);cout<<"直接選擇排序完成"<<endl;break;
		case 9:HeapSort(R,n);cout<<"堆排序完成"<<endl;break;
		case 10:MergeSort(R,n);cout<<"二路歸併排序完成"<<endl;flg=1;break;
		case 11:cout<<"序列爲"<<endl;
				if(flg==0)
				{
					for(int j=1;j<=n;j++)
					{
						cout<<R[j].key<<" ";
					}
				}
				else
				{
					for(int j=1;j<=n;j++)
					{
						cout<<R1[j].key<<" ";
					}
					flg=0;
				}
				cout<<endl;break;
		default:cout<<"輸入操作錯誤"<<endl;break;
		}
	}
}


 

 

 

發佈了32 篇原創文章 · 獲贊 5 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章