【上机代码】链表选择排序

思路

选择排序算法通过选择和交换来实现排序,其排序流程如下:
(1)首先从原始数组中选择最小的1个数据,将其和位于第1个位置的数据交换。
(2)接着从剩下的n-1个数据中选择次小的1个元素,将其和第2个位置的数据交换
(3)然后,这样不断重复,直到最后两个数据完成交换。最后,便完成了对原始数组的从小到大的排序

关于链表的实现有两点疑问:
1,带头结点的单链表如何交换两个元素
A,B两个元素要设4个指针分别指向A、B的前后节点。交换时,分AB相邻和不相邻两种情况:
A,相邻只需要更改3个节点指向
AB
A的前置指向B,B指向A,A指向B的后置

B,不相邻要更改4个节点指向
A前置 A A后置 。。。。B前置 B B后置
A的前置指向B,B指向A的后置
B的前置指向A,A指向B的后置

2,简单选择排序中,链表如何区分两个元素
在数组的排序中,值是用下标来标识不同的元素,即使值相同也可区分。
在链表的排序中,在之前的遍历中已经找到的是<min的元素,找到的元素一定和min的值不相同,故可以用p->data != min->data作为条件。或者结构体中加一个id来区分不同的元素。

代码

#include<stdio.h>
#include "malloc.h"
#include<stdlib.h>

//定义链表结构体
typedef struct Listnode
{
	int data;
	struct Listnode* next;
}Listnode;

//交换链表中两个数据
void swap(Listnode* p, Listnode* min, Listnode* pre, Listnode* lmin, Listnode* bmin)
{
	if (p->next == min)//min就在p后一位,交换相邻的两个节点
	{
		pre->next = min;
		p->next = lmin;
		min->next = p;
	}
	else//交换不相邻的两个节点
	{
		pre->next = min;
		min->next = p->next;
		p->next = lmin;
		bmin->next = p;
	}
};

void select_sort(Listnode* head)//简单选择排序(升序)
{
	Listnode* pre = head;
	Listnode* p = pre->next;
	Listnode* bmin = pre, * min, * lmin;//bmin是min前一个节点,lmin是min后一个节点
	Listnode* bq, * q; //bq记录q的前一个节点

	while (p->next)//从第一个元素开始遍历到n-1个元素
	{
		min = p;//从第一个元素开始遍历
		lmin = min->next;//min的后一个节点
		bq = p;//p的前一个节点
		q = p->next;//p从第二个元素开始遍历
		while (q)//循环在min后面到第n个元素,找到最小值节点
		{
			if (q->data < min->data)
			{	//记录min及其前后两个节点
				bmin = bq;
				min = q;
				lmin = min->next;
			}
			bq = q;
			q = q->next;//遍历
		}
		if (p->data != min->data)//在min后找到更小的值就交换
		{
			swap(p, min, pre, lmin, bmin);
		}
		pre = pre->next;
		p = pre->next;
	}
}

//输出链表节点
void print(Listnode* L)
{
	Listnode* p = L;
	for (int i = 0;  i< L->data; ++i)//L为头结点不能动 否则每次遍历就会改变条件
	{
		printf("%d ", p->next->data);
		p = p->next;
	}
}

void test()
{
	//建立链表
	Listnode* L = (Listnode *) malloc(sizeof(Listnode));
	if (L == NULL) {
		printf("内存分配不成功!\n");
	}
	else
	{
		L->data = 10;
		Listnode* p = L;
		for (int i = 0; i < L->data; ++i)
		{
			p->next = (Listnode*)malloc(sizeof(Listnode));
			if (p->next) {
				p = p->next;
				p->data = rand() % 100;//取0-99的随机数  0-99,都为原值,100-199为0-99,以此类推
			}
		}
		p->next = NULL;
		printf("原始序列为:\n");
		print(L);
		select_sort(L);
		printf("\n排序后为:\n");
		print(L);
	}
}

int main()
{
	test();
	return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

燕南路GISer

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

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

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

打赏作者

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

抵扣说明:

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

余额充值