我们用不带头结点的单链表实现简单选择排序。
递增:每次从原链表中找出一个最大(最小)元素,然后头插(尾插)到结果链表中。
递减:每次从原链表中找出一个最小(最大)元素,然后头插(尾插)到结果链表中。
//单链表实现简单选择排序(递增)
void SelectSort(LinkList &L){//此方法采用不带头结点的头插法
LNode *h = L,*p,*q,*r,*s;//h指针指向原链表
L = NULL;//L为结果链表
while(h != NULL) {//原链表不能为空
p = s = h;//p为工作指针,s指向最大结点,每一趟都指向原链表的表头的第一个结点
q = r = NULL;//q为p的前驱,r为s的前驱
while (p != NULL) {//扫描原链表,寻找最大结点s
if (p->data > s->data) {//若找到最大结点,则用s记录,r记录其前驱结点
s = p;
r = q;
}
q = p;//未找到,继续寻找
p = p->next;
}
if (s == h) {//若最大结点在链表的第一个结点位置
h = h->next;//也即让s加入结果链表,h指针后移,下一趟不再考虑这一趟的s
} else {//若最大结点在链表的表内
r->next = s->next;//也即在s加入到结果链表之前,让其前驱r的next指针指向s的下一个结点,防止断链
}
//以下是头插法的步骤
s->next = L;
L = s;
}
}
只需要把头插法递增代码中的if (p->data > s->data)
改为if (p->data < s->data)
即可。
//单链表实现简单选择排序(递减)
void SelectSort2(LinkList &L){//此方法采用不带头结点的头插法
LNode *h = L,*p,*q,*r,*s;//h指针指向原链表
L = NULL;//L为结果链表
while(h != NULL) {//原链表不能为空
p = s = h;//p为工作指针,s指向最小结点,每一趟都指向原链表的表头的第一个结点
q = r = NULL;//q为p的前驱,r为s的前驱
while (p != NULL) {//扫描原链表,寻找最小结点s
if (p->data < s->data) {//若找到最小结点,则用s记录,r记录其前驱结点
s = p;
r = q;
}
q = p;//未找到,继续寻找
p = p->next;
}
if (s == h) {//若最小结点在链表的第一个结点位置
h = h->next;//也即让s加入结果链表,h指针后移,下一趟不再考虑这一趟的s
} else {//若最小结点在链表的表内
r->next = s->next;//也即在s加入到结果链表之前,让其前驱r的next指针指向s的下一个结点,防止断链
}
//以下是头插法的步骤
s->next = L;
L = s;
}
}
//单链表实现简单选择排序(递增)
void SelectSort3(LinkList &L){//此方法采用不带头结点的尾插法
LNode *h = L,*p,*q,*r,*s,*t = L;//h指针指向原链表,t为结果链表尾指针
L = NULL;//L为结果链表
while(h != NULL) {//原链表不能为空
p = s = h;//p为工作指针,s指向最小结点,每一趟都指向原链表的表头的第一个结点
q = r = NULL;//q为p的前驱,r为s的前驱
while (p != NULL) {//扫描原链表,寻找最小结点s
if (p->data < s->data) {//若找到最小结点,则用s记录,r记录其前驱结点
s = p;
r = q;
}
q = p;//未找到,继续寻找
p = p->next;
}
if (s == h) {//若最小结点在链表的第一个结点位置
h = h->next;//也即让s加入结果链表,h指针后移,下一趟不再考虑这一趟的s
} else {//若最小结点在链表的表内
r->next = s->next;//也即在s加入到结果链表之前,让其前驱r的next指针指向s的下一个结点,防止断链
}
//以下是尾插法的步骤
if(L == NULL){//插入第一个结点时需要特殊处理
L = s;
t = s;
}else{
t -> next = s;
t = s;//t指向新的表尾结点
}
}
t -> next = NULL;//尾结点指针置空
}
同样,只需要把尾插法递增中的if (p->data < s->data)
改为p->data > s->data
即可。
//单链表实现简单选择排序(递减)
void SelectSort4(LinkList &L){//此方法采用不带头结点的尾插法
LNode *h = L,*p,*q,*r,*s,*t = L;//h指针指向原链表,t为结果链表尾指针
L = NULL;//L为结果链表
while(h != NULL) {//原链表不能为空
p = s = h;//p为工作指针,s指向最大结点,每一趟都指向原链表的表头的第一个结点
q = r = NULL;//q为p的前驱,r为s的前驱
while (p != NULL) {//扫描原链表,寻找最大结点s
if (p->data > s->data) {//若找到最大结点,则用s记录,r记录其前驱结点
s = p;
r = q;
}
q = p;//未找到,继续寻找
p = p->next;
}
if (s == h) {//若最大结点在链表的第一个结点位置
h = h->next;//也即让s加入结果链表,h指针后移,下一趟不再考虑这一趟的s
} else {//若最大结点在链表的表内
r->next = s->next;//也即在s加入到结果链表之前,让其前驱r的next指针指向s的下一个结点,防止断链
}
//以下是尾插法的步骤
if(L == NULL){//插入第一个结点时需要特殊处理
L = s;
t = s;
}else{
t -> next = s;
t = s;//t指向新的表尾结点
}
}
t -> next = NULL;//尾结点指针置空
}
#include
using namespace std;
#include
typedef int ElemType;
typedef struct LNode{//定义单链表结点类型
ElemType data;//数据域
struct LNode *next;//指针域
}LNode,*LinkList;
//单链表打印输出
void LinkListPrint(LinkList L){
LNode *p = L;
while(p != NULL){
printf("%d ",p -> data);//遍历输出单链表中元素值
p = p -> next;
}
printf("\n");
}
//头插法建立单链表(不带头结点)
LinkList List_HeadInsert(LinkList &L){
L = NULL;//不带头结点的单链表初始化指向NULL
LNode *s;//待插入的新结点
int x;//待插入的新结点的元素值
scanf("%d",&x);//输入新结点的值
while(x != 9999) {//当x等于9999时插入停止
s = (LNode *) malloc(sizeof(LNode));//创建新结点
s->data = x;//新结点赋值
s->next = L;
L = s;//将新结点插入表中,L始终指向新插入的结点
scanf("%d", &x);
}
}
//尾插法建立单链表(不带头结点)
LinkList List_TailInsert(LinkList &L){
L = NULL;//初始化单链表,头指针L指向NULL
LNode *s;//待插入新结点
LNode *r = L;//r为表尾指针
int x;//待插入新结点元素值
scanf("%d",&x);//输入新结点
while(x != 9999){//输入9999表示插入结束
s = (LNode *)malloc(sizeof(LNode));//创建新结点
s -> data = x;//新结点赋值
if(L == NULL){//插入第一个结点时需要特殊处理
L = s;
r = s;
}else{
r -> next = s;
r = s;//r指向新的表尾结点
}
scanf("%d",&x);
}
r -> next = NULL;//尾结点指针置空
}
//单链表实现简单选择排序(递增)
void SelectSort(LinkList &L){//此方法采用不带头结点的头插法
LNode *h = L,*p,*q,*r,*s;//h指针指向原链表
L = NULL;//L为结果链表
while(h != NULL) {//原链表不能为空
p = s = h;//p为工作指针,s指向最大结点,每一趟都指向原链表的表头的第一个结点
q = r = NULL;//q为p的前驱,r为s的前驱
while (p != NULL) {//扫描原链表,寻找最大结点s
if (p->data > s->data) {//若找到最大结点,则用s记录,r记录其前驱结点
s = p;
r = q;
}
q = p;//未找到,继续寻找
p = p->next;
}
if (s == h) {//若最大结点在链表的第一个结点位置
h = h->next;//也即让s加入结果链表,h指针后移,下一趟不再考虑这一趟的s
} else {//若最大结点在链表的表内
r->next = s->next;//也即在s加入到结果链表之前,让其前驱r的next指针指向s的下一个结点,防止断链
}
//以下是头插法的步骤
s->next = L;
L = s;
}
}
//单链表实现简单选择排序(递减)
void SelectSort2(LinkList &L){//此方法采用不带头结点的头插法
LNode *h = L,*p,*q,*r,*s;//h指针指向原链表
L = NULL;//L为结果链表
while(h != NULL) {//原链表不能为空
p = s = h;//p为工作指针,s指向最小结点,每一趟都指向原链表的表头的第一个结点
q = r = NULL;//q为p的前驱,r为s的前驱
while (p != NULL) {//扫描原链表,寻找最小结点s
if (p->data < s->data) {//若找到最小结点,则用s记录,r记录其前驱结点
s = p;
r = q;
}
q = p;//未找到,继续寻找
p = p->next;
}
if (s == h) {//若最小结点在链表的第一个结点位置
h = h->next;//也即让s加入结果链表,h指针后移,下一趟不再考虑这一趟的s
} else {//若最小结点在链表的表内
r->next = s->next;//也即在s加入到结果链表之前,让其前驱r的next指针指向s的下一个结点,防止断链
}
//以下是头插法的步骤
s->next = L;
L = s;
}
}
//单链表实现简单选择排序(递增)
void SelectSort3(LinkList &L){//此方法采用不带头结点的尾插法
LNode *h = L,*p,*q,*r,*s,*t = L;//h指针指向原链表,t为结果链表尾指针
L = NULL;//L为结果链表
while(h != NULL) {//原链表不能为空
p = s = h;//p为工作指针,s指向最小结点,每一趟都指向原链表的表头的第一个结点
q = r = NULL;//q为p的前驱,r为s的前驱
while (p != NULL) {//扫描原链表,寻找最小结点s
if (p->data < s->data) {//若找到最小结点,则用s记录,r记录其前驱结点
s = p;
r = q;
}
q = p;//未找到,继续寻找
p = p->next;
}
if (s == h) {//若最小结点在链表的第一个结点位置
h = h->next;//也即让s加入结果链表,h指针后移,下一趟不再考虑这一趟的s
} else {//若最小结点在链表的表内
r->next = s->next;//也即在s加入到结果链表之前,让其前驱r的next指针指向s的下一个结点,防止断链
}
//以下是尾插法的步骤
if(L == NULL){//插入第一个结点时需要特殊处理
L = s;
t = s;
}else{
t -> next = s;
t = s;//t指向新的表尾结点
}
}
t -> next = NULL;//尾结点指针置空
}
//单链表实现简单选择排序(递减)
void SelectSort4(LinkList &L){//此方法采用不带头结点的尾插法
LNode *h = L,*p,*q,*r,*s,*t = L;//h指针指向原链表,t为结果链表尾指针
L = NULL;//L为结果链表
while(h != NULL) {//原链表不能为空
p = s = h;//p为工作指针,s指向最大结点,每一趟都指向原链表的表头的第一个结点
q = r = NULL;//q为p的前驱,r为s的前驱
while (p != NULL) {//扫描原链表,寻找最大结点s
if (p->data > s->data) {//若找到最大结点,则用s记录,r记录其前驱结点
s = p;
r = q;
}
q = p;//未找到,继续寻找
p = p->next;
}
if (s == h) {//若最大结点在链表的第一个结点位置
h = h->next;//也即让s加入结果链表,h指针后移,下一趟不再考虑这一趟的s
} else {//若最大结点在链表的表内
r->next = s->next;//也即在s加入到结果链表之前,让其前驱r的next指针指向s的下一个结点,防止断链
}
//以下是尾插法的步骤
if(L == NULL){//插入第一个结点时需要特殊处理
L = s;
t = s;
}else{
t -> next = s;
t = s;//t指向新的表尾结点
}
}
t -> next = NULL;//尾结点指针置空
}
int main(){
LinkList L;
// List_HeadInsert(L);
List_TailInsert(L);
printf("排序前:");
LinkListPrint(L);
// SelectSort(L);
// SelectSort2(L);
// SelectSort3(L);
SelectSort4(L);
printf("排序后:");
LinkListPrint(L);
return 0;
}