排序算法

#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


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值