内部排序->其它->地址排序(地址重排算法)
文字描述
当每个记录所占空间较多,即每个记录存放的除关键字外的附加信息太大时,移动记录的时间耗费太大。此时,就可以像表插入排序、链式基数排序,以修改指针代替移动记录。但是有的排序方法,如快速排序和堆排序,无法实现表排序。这种情况下就可以进行“地址排序”,即另设一个地址向量指示相应记录的位置;同时在排序过程中不移动记录而移动记录地址向量中相应分量的内容。见示意图,(b)是排序结束后的地址向量,地址相连adr[1,…,8]中的值表示排序后的记录的次序,r[adr[1]]为最小记录,r[adr[8]]为最大记录。
如果需要的话,可根据adr的值重排记录的物理位置。重排算法如下:
比如要根据示意图中的(b)中地址向量重排原记录的话,由于(b)中的adr[1]=6, 则在暂存R(49)后,需要将R(13)从r[6]的位置移动到r[1]。又因为adr[6]=2,则将R(65)从r[2]的位置移至r[6]的位置。同理,将R(27)移至r[2]的位置,此时因adr[4]=1,则之前暂存的R(49)应该放在r[4]的位置上。至此完成一个调整记录位置的小循环,此小循环完成后的记录及地址向量的状态如示意图(c)所示。
示意图

算法分析
地址排序不能算是独立的算法,只是在之前讨论的内部排序算法中,另设一个地址向量,用移动地址向量中的分量值代替移动记录而已。
地址重排算法中,因为每个小循环要暂存一个记录,所以辅助空间为1
地址重排算法中,除需要暂存的记录外,所有记录均一次到位。而每个小循环至少移动两个记录,则这样的小循环最多n/2个,所以重排算法中至多移动记录[3n/2]次,其时间复杂度为n。
代码实现
#include <stdio.h>
#include <stdlib.h> #define DEBUG #define EQ(a, b) ((a) == (b))
#define LT(a, b) ((a) < (b))
#define LQ(a, b) ((a) <= (b)) #define MAXSIZE 100
#define INF 1000000
typedef int KeyType;
typedef char InfoType;
typedef struct{
KeyType key;
InfoType otherinfo;
}RedType; typedef struct{
RedType r[MAXSIZE+];
//地址向量
int adr[MAXSIZE+];
int length;
}SqList; void PrintList(SqList L){
int i = ;
printf("下标值:");
for(i=; i<=L.length; i++){
printf("[%d] ", i);
}
printf("\n关键字:");
for(i=; i<=L.length; i++){
if(EQ(L.r[i].key, INF)){
printf(" %-3c", '-');
}else{
printf(" %-3d", L.r[i].key);
}
}
printf("\n其他值:");
for(i=; i<=L.length; i++){
printf(" %-3c", L.r[i].otherinfo);
}
printf("\n地址值:");
for(i=; i<=L.length; i++){
printf(" %-3d", L.adr[i]);
}
printf("\n\n");
return ;
} //堆采用顺序存储表示
typedef SqList HeapType; /*
*已知H->r[s,...,m]中记录的关键字除H->r[s].key之外均满足的定义
*本函数调整H-r[s]的关键字,使H->r[s,...,m]成为一个大顶堆(对其中
*记录的关键字而言)
*/
void HeapAdjust(HeapType *H, int s, int m)
{
// RedType rc = H->r[s];
RedType rc = H->r[H->adr[s]];
int rc_adr = H->adr[s];
int j = ;
//沿key较大的孩子结点向下筛选
for(j=*s; j<=m; j*=){
//j为key较大的纪录的下标
if(j<m && LT(H->r[H->adr[j]].key, H->r[H->adr[j+]].key))
j+=;
//rc应该插入位置s上
if(!LT(rc.key, H->r[H->adr[j]].key))
break;
H->adr[s] = H->adr[j];
s = j;
}
//插入
H->adr[s] = rc_adr;
} /*
* 对顺序表H进行堆排序
*/
void HeapSort(HeapType *H)
{
#ifdef DEBUG
printf("开始堆排序,和之前的堆排序不同之处在于,移动地址向量代替移动记录。\n");
#endif
int i = ;
//把H->r[1,...,H->length]建成大顶堆
for(i=H->length/; i>=; i--){
HeapAdjust(H, i, H->length);
}
#ifdef DEBUG
printf("由一个无序序列建成一个初始大顶堆:\n");
PrintList(*H);
#endif
int tmp;
for(i=H->length; i>; i--){
//将堆顶记录和当前未经排序子序列H->r[1,...,i]中最后一个记录相互交换
tmp = H->adr[];
H->adr[] = H->adr[i];
H->adr[i] = tmp;
//将H->r[1,...,i-1]重新调整为大顶堆
HeapAdjust(H, , i-);
#ifdef DEBUG
printf("调整1至%d的元素,使其成为大顶堆:\n", i-);
PrintList(*H);
#endif
}
} /*
* adr给出顺序表H的有序次序,即L->r[adr[i]]是第i小的记录
* 本算法按adr重排H,使其有序
*/
void Rearrange(HeapType *H, int adr[])
{
int i = , j =, k = ;
for(i=; i<=H->length; i++){
if(adr[i] != i){
//暂存记录H->r[i]
H->r[] = H->r[i];
j = i;
//调整L->r[adr[j]]的记录到位直到adr[j] == i为止
while(adr[j] != i){
k = adr[j];
H->r[j] = H->r[k];
adr[j] = j;
j = k;
}
//记录到序
H->r[j] = H->r[];
adr[j] = j;
#ifdef DEBUG
printf("第%d躺调整:\n", i);
PrintList(*H);
#endif
}
}
} int main(int argc, char *argv[])
{
if(argc < ){
return -;
}
HeapType H;
int i = ;
for(i=; i<argc; i++){
if(i>MAXSIZE)
break;
H.r[i].key = atoi(argv[i]);
H.r[i].otherinfo = 'a'+i-;
H.adr[i] = i;
}
H.length = (i-);
H.r[].key = H.adr[] = ;
H.r[].otherinfo = '';
printf("输入数据:\n");
PrintList(H);
//对顺序表H作堆排序
HeapSort(&H);
#ifdef DEBUG
printf("对排序后的顺序表按照地址向量重新调整记录位置,使其有序\n");
#endif
Rearrange(&H, H.adr);
PrintList(H);
return ;
}
堆排序(采用地址排序)_地址重排算法
运行


内部排序->其它->地址排序(地址重排算法)的更多相关文章
- JavaScript按IP地址排序
JavaScript按IP地址列表排序,主要思路就是分割每个点号部分,然后ip1和ip2分别对不够三位数的进行补0操作,然后转换为数字类型进行一一比较. 上代码: 正序: var arr=[ {ip: ...
- python对ip地址排序、对列表进行去重
一:使用python对ip地址排序所用代码示例一: import socket iplist = ['10.5.11.1','192.168.1.33','10.5.2.4','10.5.1.3',' ...
- 算法与数据结构(十三) 冒泡排序、插入排序、希尔排序、选择排序(Swift3.0版)
本篇博客中的代码实现依然采用Swift3.0来实现.在前几篇博客连续的介绍了关于查找的相关内容, 大约包括线性数据结构的顺序查找.折半查找.插值查找.Fibonacci查找,还包括数结构的二叉排序树以 ...
- Stooge排序与Bogo排序算法
本文地址:http://www.cnblogs.com/archimedes/p/stooge-bogo-sort-algorithm.html,转载请注明源地址. Stooge排序算法 Stooge ...
- JavaScript 数据结构与算法之美 - 桶排序、计数排序、基数排序
1. 前言 算法为王. 想学好前端,先练好内功,只有内功深厚者,前端之路才会走得更远. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 JavaScript ,旨在入门数据结构与算 ...
- java排序算法(八):希尔排序(shell排序)
java排序算法(八):希尔排序(shell排序) 希尔排序(缩小增量法)属于插入类排序,由shell提出,希尔排序对直接插入排序进行了简单的改进,它通过加大插入排序中元素之间的间隔,并在这些有间隔的 ...
- 排序算法的C语言实现(下 线性时间排序:计数排序与基数排序)
计数排序 计数排序是一种高效的线性排序. 它通过计算一个集合中元素出现的次数来确定集合如何排序.不同于插入排序.快速排序等基于元素比较的排序,计数排序是不需要进行元素比较的,而且它的运行效率要比效率为 ...
- Java排序 - 不实用的几个排序算法 -- 睡眠排序、猴子排序、面条排序、珠排序
介绍几个不实用的排序算法,一来可以在学习时增加一些乐趣,放松一下自己,二来可以学习一下.思考一下这些算法失败在哪里,又是否存在一些好的地方? 睡眠排序 这是一个思想比较简单,脑洞巨大的算法 -- 我们 ...
- 内部排序->选择排序->树形选择排序
文字描述 树形选择排序又称锦标赛排序; 比如,在8个运动员中决出前3名至多需要11场比赛, 而不是7+6+5=18场比赛(它的前提是甲胜乙,乙胜丙,则甲必能胜丙) 首先对n个记录的关键字进行两两比较, ...
随机推荐
- 【MongoDB】MongoDb的“not master and slaveok=false”错误及解决方法 mongo连接从库出现问题
链接mongodb报错如下 2016-03-14T16:26:00.912+0800 E QUERY [thread1] Error: listDatabases failed:{ "ok& ...
- rsync用于数据迁移/备份的几个细节
上周我们的一个GitLab服务频繁出现web页面卡死问题,得重启虚拟机才可恢复,但重启之后没多久又会卡死.后来发现是虚拟机的磁盘大小超过了2T,而虚拟机管理那层的文件系统是ext3,最大单文件只能支持 ...
- Java知多少(49)throw:异常的抛出
到目前为止,你只是获取了被Java运行时系统抛出的异常.然而,程序可以用throw语句抛出明确的异常.Throw语句的通常形式如下: throw ThrowableInstance;这里,Thr ...
- R语言reads.table 自动将字符串变成了逻辑值
今天遇到了一个问题,文件中有一列的值为全为F, 用read.table 读取的时候,自动将F 变成了false 对于这样的转换,可以通过 colClass 参数控制 colClass 参数指定每一列的 ...
- linux环境中,top命令中,对command的命令进行扩展查看详情?
需求说明: 在使用top命令进行资源情况使用查看时,经常出现以下情况: 备注:也就是说,在COMMAND列中,有多个java进程,想要知道每个java具体的对应的是哪个程序的进程. 通过top命令的c ...
- [Android Studio] Using API of OpenCV DNN
前言 一.故事背景 NDK方法人脸识别 OpenCV4Android系列: 1. OpenCV4Android开发实录(1):移植OpenCV3.3.0库到Android Studio 2.OpenC ...
- 【SQLSERVER】How to check current pool size
SELECT des.program_name , des.login_name , des.host_name , COUNT(des.session_id) [Connections] FROM ...
- 【应用安全】S-SDLC安全开发生命周期
0x01 S-SDLC简介 OWASP Secure Software Development Lifecycle Project(S-SDLC)是OWASP组织首个由OWASP中国团队独立发布并主导 ...
- PS脚本博客
http://blog.csdn.net/fzhlee/article/category/2718489
- 【zheng环境准备】安装zookeeper
1.zookeeper下载 wget http://mirrors.hust.edu.cn/apache/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar ...