数据结构(排序)

一、插入排序

1.直接插入排序

#define SIZE 100

//数据结点 --  数据结构定义
typedef struct DataNode{
int key;
int data;
}DataNode;

//表  --- 数据结构
typedef struct Table{
DataNode *table;
int length;
}Table,*LinkTable;

//表的初始化
void init(LinkTable &l){
l=new Table;
l->table=new DataNode[SIZE];
l->length=0;
}

//对顺序表做插入排序
void InsertSort(LinkTable l){
int i,j;
	//进行n-1次插入
for(i=2;i<=l->length;i++)
if(l->table[i].key<l->table[i].key){   //逆序则插     正序不管它
//将待插数据记录在0号位置
	*l->table[0]=*l->table[i];
	for(j=i-2;l->table[0].key<l->table[j].key;j--)   //找要插入的位置
	*l->table[j+1]*l->table[j];   //没找到就后移

	//插入到他该去的地方
	*l->table[j+1]=*l->table[0];
}

}

2.折半插入排序

//对表折半插入排序-----------------大致意思就是----
//----找刺头(逆序) -》 找插入位置  -》 都往后稍一稍 -》 插个队
void BInsertSort(LinkTable l){
int i,j,low,high,mid;
	//找刺头
	for(i=2;i<=l->length;i++)
		if(l->table[i].key<l->table[i-1].key){
			//抓住它
			*l->table[0]=*l->table[i];
			//找插入位置
			low=1;high=i-1;
			while(low<=high){
			mid=(low+high)/2;
			 //需要插入的位置在high的前面
			if(l->table[mid].key<l->table[0].key)high=mid-1;   
			else low=mid+1;
			}

			//往后稍一稍
			for(j=i-1;j>=high+1;j--)*l->table[j+1]=*l->table[j];

			//偷摸插个队
			*l->table[j+1]=*l->table[0];
		}
}

3.希尔排序

//希尔排序    ----   根据增量dk排序  思路就是把直接插入排序的1换成了dk
//不信你看-----》》》
void ShellInsert(LinkTable l,int dk){
int i,j;
	//找刺头--跳着找
	for(i=dk+1;i<l->length;i+=dk)
		
		if(l->table[i].key<l->table[i-dk].key){
		
			//抓住它
			*l->table[0]=*l->table[i];
			//找插入位置
			for(j=i-dk;j>0 && l->table[j].key<l->table[0].key;j-=dk)
				*l->table[j+dk]=*l->table[j];
		*l->table[j+dk]=*l->table[0];
		}
}


//希尔排序 -----   按增量序列dt[0,1,2....t-1]对顺序表进行t次希尔排序
void  ShellSort(LinkTable l,int dt[],int t){

	//进行t次希尔排序
	for(int k=0;k<t;k++)ShellInsert(l,dt[k]);
}

二、交换排序

1.冒泡排序

//冒泡排序
void BubbleSort(LinkTable l){
int m,flag,j;
flag=1;
m=l->length-1;

//列表记录数大于1 并且逆序时
while((m>0) && flag==1){
flag=0;        //现在假设列表正序

//进行一次冒泡-------向高地址冒泡
for(j=1;j<=m;j++){
	//逆序
	if(l->table[j].key>l->table[j+1].key){
		flag=1;   //更新标志位
		//交换两个记录的位置
		*l->table[0]=*l->table[j];  
		*l->table[j]=*l->table[j+1]; 
		*l->table[j+1]=*l->table[0];
	}
	m--;//冒泡位置更新
}

}

}

2.快速排序

//将表中的数据一分为二,并返回中枢位置
int Partion(LinkTable l,int low,int high){ 
//这里选择第一个记录作为中枢   可以选三个记录或者五个记录的平均值作为中枢值
int key=l->table[low].key;  
	l->table[0]=l->table[low];

	while(low<high){
		
		//比中枢key值大的直接绕过---把比中枢值小的转移到左边
		while(l->table[high].key>=key)--high;
		*l->table[low]=*l->table[high];
		//比中枢key小的绕过,比中枢大的转移到右边
		while(l->table[low].key<=key)--low;
		*l->table[high]=*l->table[low];
	}

	*l->table[low]=*l->table[0];
	return low;
}


//对表中low到high位置记录进行快速排序
void QSort(LinkTable l,int low,int high){
int mid;
if(low<high){

	//将表分为两部分----小的移到左子表  大的移到右子表
mid=Partion(l,low,high);

//左子表排序
QSort(l,low,mid-1);
//右子表排序
QSort(l,mid+1,high);

}	
}

//对表进行快排
void QuickSort(LinkTable l){
	QSort(l,1,l->length);
}

三、选择排序

1.简单选择排序

//简单选择排序
void SelectSort(LinkTable t){
int i,j,k;
//进行n-1次的选择
for(i=1;i<t->length;i++){
k=i;   //假装i号位置记录是最小的
for(j=i+1;j<=t->length;j++)     //咱们比一比
if(t->table[j].key<t->table[k].key)k=j;


//看看假设成立不成立
if(k!=i){ //不成立   ---   交换
*t->table[0]=*t->table[i];
*t->table[i]=*t->table[k];
*t->table[k]=*t->table[0];
}

}

}

2.树形选择排序

3.堆排序

堆调整

//筛选法调整堆
void HeapAdjust(LinkTable l,int s,int m){
int j;
	//假设R[s+1...... m]已经是堆,将R[s,s+1.... m]调整为R[s]为根的大根堆
*l->table[0]=*l->table[s];

//向下找找是不是逆序---找其插入位置
for(j=2*s;j<=m;j*=2){   //沿着key较大的孩子结点向下删选
if(j<m && l->table[j].key<l->table[j+1].key)++j;

//下面的都是堆   正序
if(l->table[0].key>=l->table[j].key)break;

//逆序 将较大的给S号位置
*l->table[s]=*l->table[j];
s=j;   //继续向下找 看看是不是逆序    -- 
//    沿着结点修改的位置向下找 没有修改的肯定还是堆  修改过的就不一定了
}
//将其插入到找到的s号位置
*l->table[s]=*l->table[0];
}

堆创建

//堆的创建
void createHeap(LinkTable &l){
int n=l->length,i;

//i=n/2是根据树的结点的特性  叶子结点的个数不会少于所有结点的一半
for(i=n/2;i>=1;i--)
HeapAdjust(l,i,n);

}

堆排序

//堆排序
void HeapSort(LinkTable l){
	int i;
	//先将列表调整为大根堆   --- 然后依次将大根放到后面的位置  -- 
	createHeap(l);
	for(i=l->length;i>1;i--){  //进行n-1次的交换调整
	*l->table[0]=*l->table[1];
	*l->table[1]=*l->table[i];
	*l->table[i]=*l->table[0];
	HeapAdjust(l,1,i-1);   //重新调整
	}
}

四、归并排序

#define SIZE 100

//数据结点 --  数据结构定义
typedef struct DataNode{
int key;
int data;
}DataNode;

//表  --- 数据结构
typedef struct Table{
DataNode *table;
int length;
}Table,*LinkTable;

//表的初始化
void init(LinkTable l){
l=new Table;
l->table=new DataNode[SIZE];
l->length=0;
}


void merge(DataNode *r,DataNode *t,int low,int mid,int high){
//将有序表 r[low   mid] r[mid+1   high]  归并为有序表 t[low .. high]
	int i,j,k;
	i=low; j=mid+1; k=low;

	while(i<=mid && j<=high){    //将R中记录由小到大并入T中
	if(r[i].key<=r[j].key)t[k++]=r[i++];
	else t[k++]=r[j++];
	}

	while(i<=mid)t[k++]=r[i++];
	while(j<=mid)t[k++]=r[j++];
}


//将R[low ...  high]归并排序后放入T[low ... high]
void MSort(DataNode *r,DataNode *t,int low,int high){

//辅助数组
DataNode *s;
s=new DataNode[SIZE];        //借助辅助数组进行合并

if(low==high)t[low]=r[low];
else{    //当前序列一分为二
int mid=(low+high)/2;
//分别对两个子序列排序
MSort(r,s,low,mid);
MSort(r,s,mid+1,high);
Merge(s,t,low,mid,high);
}

}


//对顺序表L做归并排序
void mergeSort(LinkTable l){

MSort(l->table,l->table,1,l->length);
}

五、基数排序

#define MAXNUM_KEY 10     //关键字项数的最大值
#define RADIX 10          //关键字基数,此时是十进制整数的基数
#define MAX_SPACE 10000

typedef struct{
	int keys[MAXNUM_KEY];     //关键字
	int data;
	int next;
}SLCell;     //静态链表结点类型

typedef struct{
SLCell r[MAX_SPACE]; //静态链表的可利用空间
int  keyNum;    //记录的当前关键字个数
int length;     //静态链表的长度
}SLList;        //静态链表类型

typedef int ArrType[RADIX];


//静态链表的初始化
void init(SLList* &l){
l=new SLList;
l->keyNum=0;
l->length=0;
}


//进行第i次分配---- 将所有结点按照关键字映射  挂在挂件上的对应链上
void Distribute(SLCell* r,int i,ArrType &f,ArrType &e){//f e为挂件头尾
//静态链表的r域已按keys[0,1...i-1]有序
int k,p,j;

//将 f挂件 清空
for(j=0;j<RADIX;j++)f[j]=0;

for(p=r[0].next;p;p=r[p].next){

	//根据关键字进行映射
	j=r[p].keys[i];
	//如果当前链为空  则将其挂在头部
	if(!f[j])f[j]=p;
	else e[j]=p;   //挂在链尾

	//更新链尾结点
	e[j]=p;
}

}


//进行第i次收集   ----   其实就是把所有挂件上的链串起来然后挂在头结点上
void Collect(SLCell* r,int i,ArrType &f,ArrType &e){//f e为挂件头尾
int j=0,k;
	//先找到第一个不为空的链
	while(!f[j])j++;
	//将第一个链挂在头结点上
	r[0].next=f[j];
	//记录链尾
	k=e[j];
	while(j<RADIX-1){   //将其余的链也收集起来---串上去
		j++;
		if(f[j]){  //当前链非空
		r[k].next=f[j];
		k=e[j];
		}
	}
	
	//最后一个结点后继指向头结点
	r[k].next=0;
}

void RadixSort(SLList* l){
//L做基数排序 使得L成为按关键字从小到大的有序静态链表   l->r[0]为头结点
	int i;ArrType f,e;
	for(i=0;i<l->length;i++)l->r[i].next=i+1;    //初始化数组为静态链表
	//最后一个结点的后继为头结点
	l->r[i].next=0;
	
	for(i=0;i<l->keyNum;i++){   //按最低为优先依次对各关键字进行分配和收集
	Distribute(l->r,i,f,e);
	Collect(l->r,i,f,e);
	}
}

六、外部排序

1.多路平衡归并

2.置换选择排序

3.最佳归并树

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值