数据结构资料(十)——内排序

排序的基本概念

  • 排序就是整理表中的元素,使之按关键字递增或递减有序排序。
  • 如果待排序的表中存在有多个关键字相同的元素,经过排序后这些具有相同关键字的元素之间的相对次序保持不变,则称这种排序方法是稳定的;反之,若具有相同关键字的元素之间的相关次序发生变化,则称这种排序方法是不稳定的
  • 在排序过程中,若整个表都放在内存中处理,排序时不涉及数据的内,外存交换,则称之内排序;反之,若在排序过程要进行数据的内,外存交换,则称之为外排序

待排序的顺序表中数据元素的类型声明:

typedef int KeyType;		//定义关键字类型为int
typedef struct{				//元素类型
	KeyType key;			//关键字项
	InfoType data;			//其他数据项,类型为InfoType
} RecType;					//排序元素的类型

插入排序

直接插入排序

void InsertSort(RecType R[],int n){				//对R[0……n-1]按递增有序进行直接插入排序
	int i,j;
	RecType tmp;
	for(i=1;i<n;i++){
		if(R[i].key<R[i-1].key){				//反序时
			tmp=R[i];
			j=i-1;
			do{									//找R[i]的插入位置
			R[j+1]=R[j];						//将关键字大于R[i].key的记录后移
			j--;	
			}while	(j>=0&&R[j].key>tmp.key);		
			R[j+1]=tmp;							//在j+1处插入R[i]
		}	
	}
}

折半插入排序

void BinInsertSort(RecType R[],int n){
	int i,j,low,high,mid;
	RecType tmp;
	for(i=1.i<n;i++){
		if(R[i].key<R[i-1].key){			//反序时
			tmp=R[i];						//将R[i]保存到tmp中
			low=0;
			high=i-1;
			while(low<=high){				//在R[low……high]中查找插入的位置
				mid=(low+high)/2;			//取中间位置
				if(tmp.key<R[mid].key)
					high=mid-1;				//插入点在左半区
				else
					low=mid+1;				//插入点在右半区
			}								//找位置high
			for(j=i-1;j>=high+1;j--)		//集中进行元素后移
				R[j+1]=R[j];
			R[high+1]=tmp;					//插入tmp
		}	
	}
}

希尔排序

void ShellSort(RecType R[],int n){			//希尔排序算法
	int i,j,d;
	RecType tmp;
	d=n/2;									//增量置初值
	while(d>0){
		for(i=0;i<n;i++){					//对所有组采用直接插入排序
			tmp=R[i];						//对相隔d个位置一组采用直接插入排序
			j=i-d;
			while(j>=0&&tmp.key<R[i].key){
				R[j+d]=R[j];
				j=j-d;	
			}	
			R[j+d]=tmp;
		}	
		d=d/2;								//减小增量
	}
}

交换排序

冒泡排序

void BubbleSort(RecType R[],int n){
	int i,j;
	for(i=0;i<n-1;i++)
		for(j=n-1;j>i;j--)				//将R[i]元素归位
			if(R[j].key<R[j-1].key)		//相邻的两个元素反序时
				swap(R[j],R[j-1]);		//将R[j]和R[j-1]两个元素交换
}

快速排序

int partition(RecType R[],int s,int t){		//一趟划分
	int i=s,j=t;
	RecType tmp=R[i];						//以R[i]为基准
	while(i<j){								//从两端交替向中间扫描,直至i=j为止
		while(j>i&&R[i].key>=tmp.key)
			j--;							//从右向左扫描,找一个小于tmp.key的R[i]
		R[i]=R[j];							//找到这样的R[j],放在R[i]处
		while(i<j&&R[i].key<=tmp.key)
			i++								//从左向右扫描,找一个大于tmp.key的R[i]
		R[j]=R[i];							//找到这样的R[i],放入R[j]处
	}
	R[i]=tmp;
	return i;
}
void QuickSort(RecType R[],int s,int t){	//对R[s……t]的元素进行快速排序
	int i;
	if(s<t){								//区间内至少存在两个元素的情况
		i=partition(R,s,t);
		QuickSort(R,s,i-1);					//对左区间递归排序
		QuickSort(R,i+1,t);					//对右区间递归排序
	}
}

选择排序

简单选择排序

void SelectSort(RecType R[],int n){
	int i,j,k;
	for(i=0;i<n-1;i++){					//做第i趟排序
		k=i;
		for(j=i+1;j<n;j++)				//在当前无序区R[i……n-1]中选key最小的R[k]
			if(R[j].key<R[k].key)	
				k=j;					//k记下目前找到的最小关键字所在的位置
		if(k!=i)						//R[i]和R[k]两个元素交换
			swap(R[i],R[K]);
	}
}

堆排序

void HeapSort(RecType R[],int n){
	int i;
	for(i=n/2;i>=1;i--)				//循环建立初始堆,调用sift算法(n/2)次
		sift(R,i,n);
	for(i=n;i>=2;i--){				//进行n-1趟完成堆排序,每一趟堆中元素个数减1
		swap(R[1],R[i]);			//将最后一个元素与根R[1]交换
		sift(R,1,i-1);				//对R[1……i-1]进行筛选,得到i-1个结点的堆
	}
}

归并排序

归并排序是多次将两个或两个以上的有序表合并成一个新的有序表。最简单的归并是直接将两个有序的子表合并成一个有序的表,即二路归并。

void Merge(RecType R[],int low,int mid,int high) 归并R[low……high]
{
	RecType *R1;
	int i=low,j=mid+1,k=0;				//k是R1的下标,i,j分别为第1,2段的下标
	R1=(RecType *)malloc((high-low+1)*sizeof(RecType));
	while(i<=mid&&j<=high)				//在第1段和第2段均未扫描完时循环
		if(R[i].key<=R[j].key){			//将第1段中的元素放入R1中
			R1[k]=R[i];
			i++;
			k++;	
		}
		else{							//将第2段中的元素放入R1中
			R1[k]=R[j];
			j++;
			k++;	
		}
	while(i<=mid){						//就第1段余下的部分复制到R1
		R1[k]=R[j];
		i++;
		k++;	
	}
	while(j<=high){						//将第2段余下的部分复制到R1
		R1[k]=R[j];
		j++;
		k++;	
	}
	for(k=0,i=low;i<=high;k++,i++)		//将R1复制到R[low……high]中
		R[i]=R1[k];
	free(R1);
}

基数排序

基数排序是通过分配和收集过程来实现排序,不需要进行关键字间的比较,是一种借助于多关键字排序的思想对单关键字排序的方法。

typedef struct node{
	char data[MAXD];		//MAXD为最大的关键字位数
	struct node *next;		//指向下一个结点
} NodeType;					//基数排序数据的结点类型

void RadixSort(NodeType *&p,int r,int d){	//LSD基数排序算法
	NodeType *head[MAXR],*tail[MAXR],*t;	//定义各链队的首尾指针
	int i,j,k;
	for(i=0;i<=d-1;i++){					//从低位到高位循环
		for(j=0;i<r;j++)					//初始化各链队的首,尾指针
			head[j]=tail[j]=NULL;
		while(p!=NULL){						//分配:对于原链表中的每个结点循环
			k=p->data[i]-'0';				//找第k个链队
			if(head[k]==NULL){				//第k个链队空时,队头,队尾均指向结点p
				head[k]=p;
				tail[k]=p;	
			}	
			else{							//第k个链队非空时结点p进队
				tail[k]->next=p;
				tail[k]=p;
			}
			p=p->next;						//取下一个待排序的元素
		}	
		p=NULL;								//重新用p来收集所有结点
			for(j=0;j<r;j++)				//收集:对于每一个链队循环
				if(head[j]!=NULL){			//若第j个链队是第一个非空链队
					if(p==NULL){
						p=head[j];
						t=tail[j];	
					}	
					else{					//若第j个链队是其他非空链队
						t->next=head[j];
						t=tail[j];	
					}
				}
		t->next=NULL;						//最后一个结点的next域置NULL
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FFFPAG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值