排序算法

#include<iostream>
#include<fstream>
#include<sstream>
#include<string>
using namespace std;

#define MAXSIZE 20
typedef int KeyType;


typedef struct{
	KeyType key;
	string otherinfo;
}RedType;

typedef struct{
	RedType r[MAXSIZE+1];
	int length;
	void print();
}SqList;

typedef SqList HeapType;/*堆採用順序表存儲表示*/

void SqList::print()
{
	for(int i=1;i<=length;i++)
		cout<<r[i].key<<'\t'<<r[i].otherinfo<<endl;
}

/*直接插入排序*/
/*其時間複雜度爲O(n**2)*/
void InsertSort(SqList &L)
{
	for(int i=2;i<=L.length;i++)/*length-1次迭代*/
		if(L.r[i].key<L.r[i-1].key)/*從最後一個先左比較,若大,則保持位置不變*/
		{
			L.r[0]=L.r[i];/*r[0]作爲哨兵*/
			L.r[i]=L.r[i-1];
			for(int j=i-2;L.r[j].key>L.r[0].key;j--)/*找到比哨兵值小的位置,其前的元素後移*/
				L.r[j+1]=L.r[j];
			L.r[j+1]=L.r[0];/*插入正確的位置*/
		}
}

/*其它插入排序*/
/*折半插入排序*/
/*利用折半查找來實現查找操作*/
/*時間複雜度還是O(n**2)*/
/*雖然查找省了時間,但仍然需要移位*/
void BInsertSort(SqList &L)
{
	for(int i=2;i<=L.length;i++)
		if(L.r[i].key<L.r[i-1].key)
		{
			L.r[0]=L.r[i];/*與直接插入排序的區別在於查找位置*/
			int low=1,high=i-1,m;
			while(low<=high)
			{
				m=(low+high)/2;//折半
				if(L.r[m].key>L.r[0].key)//插入點在低半區 
					high=m-1;
				else//插入點在高半區
					low=m+1;
			}
			for(int j=i-1;j>=high+1;j--)//記錄後移
				L.r[j+1]=L.r[j];
			L.r[high+1]=L.r[0];//插入
		}
}

void ShellInsert(SqList &L,int dk)
{
	for(int i=dk+1;i!=L.length;i++)
		if(L.r[i].key<L.r[i-dk].key)/*需將L.r[i]插入有序增量子序列中*/
		{
			L.r[0]=L.r[i];/*暫存在L.r[0]中*/
			for(int j=i-dk;j>0 && L.r[j].key>L.r[0].key;j-=dk)
				L.r[j+dk]=L.r[j];/*記錄後移,查找插入位置*/
			L.r[j+dk]=L.r[0];/*插入*/
		}
}

/*希爾排序,又稱縮小增量排序,插入排序的一種*/
/*先將整個待排記錄序列分割成如干子序列進行直接插入排序,
待整個序列基本有序的時候,再對全體記錄進行一次直接插入排序*/
void ShellSort(SqList &L,int dlta[],int t)
{
	for(int k=0;k<t;k++)
		ShellInsert(L,dlta[k]);
}

/*快速排序*/
/*基本思想:通過一趟排序將代排記錄分割成獨立的兩部分,
其中一部分記錄關鍵字均比另一部分記錄的關鍵字小,
則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序*/
/*
快速排序是O(nlogn)的排序方法中,其平均性能最好。但初始記錄順序有序時,快排將退化爲氣泡排序
其時間複雜度變成O(n**2)
但快速排序需要一個棧空間來實習遞歸,若每一趟排序都將記錄序列均勻的分割成長度相近的
兩個子序列,則棧的最大深度爲[log2n+1];
最壞的時候,若每趟排序均偏向子序列的一端,則爲最壞情況,棧的最大深度爲n
*/
int Partition(SqList &L,int low,int high)
{
	L.r[0]=L.r[low];/*用子表的第一個記錄作扭軸記錄*/
	int pivotkey=L.r[low].key;/*扭軸記錄關鍵字*/
	while(low<high)/*從表的兩端交替向中間掃描*/
	{
		while(low<high && L.r[high].key>=pivotkey) --high;
		L.r[low]=L.r[high];/*將比扭軸記錄小的記錄移到低端*/
		while(low<high && L.r[low].key<=pivotkey) ++low;
		L.r[high]=L.r[low];/*將比扭軸記錄大的記錄移到高端*/
	}
	L.r[low]=L.r[0];/*扭軸記錄到位*/
	return low;
}

/*遞歸形式的快速排序*/
void QSort(SqList &L,int low,int high)
{
	if(low<high)/*長度大於1*/
	{
		int pivocloc=Partition(L,low,high);/*一分爲二*/
		QSort(L,low,pivocloc-1);/*對低子表遞歸排序*/
		QSort(L,pivocloc+1,high);/*對高子表遞歸排序*/
	}
}

void QuickSort(SqList &L)
{
	QSort(L,1,L.length);
}


/*簡單選擇排序*/
/*通過n-i次關鍵字的比較,從n-i+1個記錄中選出關鍵字最小的記錄,並和第i個記錄交換*/
/*簡單選擇排序,所需記錄移動的操作次數較少,其最小值爲“0”,最大值爲3(n-1)*/
/*比較次數相同,均爲n(n-1)/2。總的時間複雜度爲O(n**2)*/
int SelectMinKey(SqList &L,int i)
{
	int imin=i;
	for(int j=i+1;j!=L.length;j++)
	{
		if(L.r[j].key<L.r[imin].key)
		{
			imin=j;
		}
	}
	return imin;
}

void SelectSort(SqList &L)
{
	for(int i=1;i!=L.length;i++)
	{
		int j=SelectMinKey(L,i);
		if(i!=j)
		{
			RedType temp;
			temp=L.r[i];
			L.r[i]=L.r[j];
			L.r[j]=temp;
		}
	}
}

/*堆排序*/
/*只需要一個記錄大小的輔助空間,每個待排序的記錄僅佔一個存儲空間*/
/*由於堆排序最壞情況下,其時間複雜度也爲O(nlogn)。相對於快速排序,這是堆排序最大優點*/
/*堆排序僅需要一個記錄大小供交換用的輔助空間*/
void HeapAdjust(HeapType &H,int s,int m)
{
	RedType rc=H.r[s];
	for(int j=2*s;j<=m;j=j*2)/*沿key較大的孩子結點向下篩選*/
	{
		if(j<m && (H.r[j].key<H.r[j+1].key)) ++j;//j爲key較大的記錄的下標
		if(!(rc.key<H.r[j].key)) break;//rc應插入在位置s
		H.r[s]=H.r[j];
		s=j;
	}
	H.r[s]=rc;//插入
}

void HeapSort(HeapType &H)
{
	for(int i=H.length/2;i>0;--i)
		HeapAdjust(H,i,H.length);/*建成大頂堆*/
	for(i=H.length;i>1;--i)
	{
		RedType temp;/*將堆頂記錄和當前未經排序子序列中最後一個記錄相互交換*/
		temp=H.r[i];
		H.r[i]=H.r[1];
		H.r[1]=temp;
		HeapAdjust(H,1,i-1);/*將H.r[1..i-1]調整爲大頂堆*/
	}
}

int main()
{
	ifstream infile;
	infile.open("data.txt");
	if(!infile)
	{
		cerr<<"error:unable to open input file:"<<infile<<endl;
		return -1;
	}
	string line;
	SqList L;
	L.length=0;
	while(getline(infile,line))/*讀一行數據到line*/
	{
		L.length++;	
		istringstream stream(line);/*讀string功能*/
		stream>>L.r[L.length].key>>L.r[L.length].otherinfo;
	}
	//InsertSort(L);
	//BInsertSort(L);
	//int dlta[3]={5,3,1};
	//ShellSort(L,dlta,3);
	//QuickSort(L);
	//SelectSort(L);
	HeapSort(L);
	L.print();
	return 0;
}


數據文件 data.txt

49 zhoujielun
38 xiaoshengyang
65 zhouxinchi
97 caiyilin
76 tangwei
13 liangcaowei
27 wujinru
49 yaoming


 

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