单链表实现简单选择排序

目录

  • 算法思想
  • 代码实现
    • 头插法递增
    • 头插法递减
    • 尾插法递增
    • 尾插法递减
  • 完整程序测试
  • 测试结果

算法思想

我们用不带头结点的单链表实现简单选择排序。
递增:每次从原链表中找出一个最大(最小)元素,然后头插(尾插)到结果链表中。
递减:每次从原链表中找出一个最小(最大)元素,然后头插(尾插)到结果链表中。

代码实现

头插法递增

//单链表实现简单选择排序(递增)
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;
}

测试结果

在这里插入图片描述

你可能感兴趣的:(C语言,数据结构,链表,数据结构,算法)