表排序的适用情况
待排序的元素庞大(例如要排序多部电影),这个时候可以通过间接排序的方法进行排序,即只需要在排序的时候改变元素的指针所指向的位置即可,这个时候可以运用表排序。
代码中所运用到的结构体
typedef struct
{
int elem;//待排元素
int pos;//待排元素的指针
}SLNode;//一个结点
typedef struct
{
SLNode r[SIZE];//待排元素的存储位置
int length;//待排元素的个数
}SLinkListType;
表插入排序的主要思想
- 适用于要移动的元素庞大,可以通过改变位置指针的指向来实现移动元素的次数为O(n)复杂度的排序
- 通过对比待排元素的大小,来改变位置指针的指向,而不改变元素本身的位置,直到位置的指针全部排序完成
- 排序完成后可以通过直接顺序输出位置的指针所指向的位置就可以得到待排元素顺序排序好的序列,到目前为止,还尚移动待排元素
SLinkListType Arrange(SLinkListType SL)//对指针域进行排序
{
int i,p,temp;
for(i=0;i<SL.length;i++)//对指针域初始化
{
SL.r[i].pos=i;
}
for(i=0;i<SL.length;i++)//开始对指针域进行排序
{
p=i;
if(i==0)//为第一个结点时
{
SL.r[i].pos=i;
}
else//不为第一个结点时
{
while(p!=0)//当比较到第一个时停止
{
p--;
if(SL.r[SL.r[p].pos].elem<SL.r[i].elem)
{
break;
}
else if(SL.r[SL.r[p].pos].elem>=SL.r[i].elem)
{
temp=SL.r[p].pos;
SL.r[p].pos=SL.r[p+1].pos;
SL.r[p+1].pos=temp;
}
}
}
}
return SL;
}
进行物理排序
- 结论:N个数字的排列由若干个独立的环组成
- 那什么是环呢?下图中处于同一个环的数字被相同颜色的笔圈起来了(图片来自于浙江大学的数据结构MOOC)
- - 故进行物理排序的时候,对一个一个环进行排序
- 判断一个环的结束可以通过当table【i】(即上文的位置指针)= i 时,即判断为环结束。
- 最坏的情况为一个环只包含了两个元素。
SLinkListType ReMerge(SLinkListType SL)
{
int i,next,p=0,temp,mark=0;
while(mark!=SL.length)//当列表里的数字都排序完成时结束
{
mark=0;//标记初始化
temp=SL.r[p].elem;//记录环起始位置的数据
while(1)
{
next=SL.r[p].pos;//记录起始位置的next
if(SL.r[next].pos==next)//如果当圈走完时结束
{
SL.r[p].elem=temp;
SL.r[p].pos=p;
break;
}
else//当圈未走完时
{
SL.r[p].elem=SL.r[next].elem;
SL.r[p].pos=p;
p=next;
}
}
for(i=0;i<SL.length;i++)//判断是否全部排序完
{
if(SL.r[i].pos!=i)
{
p=i;
break;
}
if(SL.r[i].pos==i)
{
mark++;
}
}
}
return SL;
}
源代码
#include <stdio.h>
#include <stdlib.h>
#define SIZE 100
typedef struct
{
int elem;//待排元素
int pos;//待排元素的指针
}SLNode;//一个结点
typedef struct
{
SLNode r[SIZE];//待排元素的存储位置
int length;//待排元素的个数
}SLinkListType;
SLinkListType Arrange(SLinkListType SL)//对指针域进行排序
{
int i,p,temp;
for(i=0;i<SL.length;i++)//对指针域初始化
{
SL.r[i].pos=i;
}
for(i=0;i<SL.length;i++)//开始对指针域进行排序
{
p=i;
if(i==0)//为第一个结点时
{
SL.r[i].pos=i;
}
else//不为第一个结点时
{
while(p!=0)//当比较到第一个时停止
{
p--;
if(SL.r[SL.r[p].pos].elem<SL.r[i].elem)
{
break;
}
else if(SL.r[SL.r[p].pos].elem>=SL.r[i].elem)
{
temp=SL.r[p].pos;
SL.r[p].pos=SL.r[p+1].pos;
SL.r[p+1].pos=temp;
}
}
}
}
return SL;
}
SLinkListType ReMerge(SLinkListType SL)
{
int i,next,p=0,temp,mark=0;
while(mark!=SL.length)//当列表里的数字都排序完成时结束
{
mark=0;//标记初始化
temp=SL.r[p].elem;//记录环起始位置的数据
while(1)
{
next=SL.r[p].pos;//记录起始位置的next
if(SL.r[next].pos==next)//如果当圈走完时结束
{
SL.r[p].elem=temp;
SL.r[p].pos=p;
break;
}
else//当圈未走完时
{
SL.r[p].elem=SL.r[next].elem;
SL.r[p].pos=p;
p=next;
}
}
for(i=0;i<SL.length;i++)//判断是否全部排序完
{
if(SL.r[i].pos!=i)
{
p=i;
break;
}
if(SL.r[i].pos==i)
{
mark++;
}
}
}
return SL;
}
int main()
{
SLinkListType SL;
int i;
printf("Please input the number of number you wanted to arrange:\n");
scanf("%d",&SL.length);
getchar();
printf("PLease input the data:\n");
for(i=0;i<SL.length;i++)
{
scanf("%d",&SL.r[i].elem);
getchar();
}
SL=Arrange(SL);
SL=ReMerge(SL);
printf("Result:\n");
for(i=0;i<SL.length;i++)
{
printf("%d ",SL.r[i].elem);
}
return 0;
}