单链表排序(交换节点)

单链表排序(移动节点)

单链表排序利用了选择排序的方式;
创建一个单链表结构体

typedef int data_t;//为了能适应存储其他类型数据,可以将int换成其他数据类型而不通用一个一个更改程序里的了

typedef struct node{
	data_t a;//链表里存的数据
	struct node *next;//指向下一个节点
}linknode,* linklist;//创建结构体变量和指针

单链表节点的结构形式出来啦,接下来我们就按图施工,创建链表吧

linklist link_creart(){
	linklist H;
	H = (linklist)malloc(sizeof(linknode));//为链表节点申请内存
	if(H == NULL){
		printf("malloc is fail\n");
		return H;
	}
	H->a = 0;//第一个作为头节点不存数据随便写个值
	H->next = NULL;//后续节点还没有只能是空
	return H;
}

空链表不能饿着肚子需要填一些东西进去,那么我们就写个函数喂一下这个链表吧。

int link_insert_last(linklist H,data_t value){//采取尾部插入的方式填充链表
	linklist p;
	linklist q;
	p = H;
	q = (linklist)malloc(sizeof(linknode));//为每个插入的节点申请内存
	if(q == NULL){
		printf("creart new node fail\n");
		return 0;
	}
	q->a = value;//输入我们需要存储的值
	q->next = NULL;//注意:最后一个节点的next需要为NULL,因为我们采用尾部插入,所以新建的节点next=NULL
	while(p->next != NULL){//找到最后一个节点
		p = p->next;
	}
	p->next = q;
	return 1;
}

利用link_insert_last(linklist H,data_t value)函数如果这样操作是不是太麻烦了呢

link_insert_last(linklist H,data_t 1)link_insert_last(linklist H,data_t 2)link_insert_last(linklist H,data_t 3)link_insert_last(linklist H,data_t 4)

那我们换个方法

data_t a;
while(1){
		scanf("%d",&a);
		if(a == -1){  //输入-1停止输入
			break;
		}
		link_insert_last(H,a);
	}

有了输入我们还需要看一下,是不是输入进去了,下面做一个函数让链表显示一下

int link_show(linklist H){
	if(H->next == NULL) //如果连表是个空链表就没必要执行了
		printf("the link is NULL\n");
	linklist p;
	p = H;
	while(p->next != NULL){
		printf("%3d",p->next->a);
		p = p->next;
	}
	puts("");
	return 1;
}

接下来我们测试一下

int main(){
linklist H;
data_t a;
H = link_creart();
while(1){
		scanf("%d",&a);
		if(a == -1){  //输入-1停止输入
			break;
		}
		link_insert_last(H,a);
	}
	link_show(H);
}

输入1,2,3,4,5;

1
2
3
4
5
  1  2  3  4  5
  

接下来进入正题,怎样才能用交换节点的方式对单链表进行排序呢
首先需要根据位置找到节点

linklist link_inquire_pos(linklist H,int pos){
	int i = 0;
	linklist p;
	p = H;
	if(pos == -1){
		return NULL;
	}
	while(i<pos){
		i++;
		p = p->next;
		if(p == NULL){
			return NULL;
		}
	}
	return p;
}

利用上边的函数我们可以找到在链表某个位置上的节点了
接下来我们对某两个位置上的节点进行交换,函数如下所示(这个函数写的不太好请各位大神指正)

int link_exch(linklist H,int pos1,int pos2){
	if(H == NULL){
		return 0;
	}
	if(H->next == NULL || H->next->next == NULL){
		printf("node none or just one\n");
		return 0;
	}
	linklist p,q,top1,top2,r;
	p = link_inquire_pos(H,pos1);
	q = link_inquire_pos(H,pos2);
	if(pos1+1 != pos2){    //两个相邻节点交换位置
		top1 = link_inquire_pos(H,pos1-1);
		top2 = link_inquire_pos(H,pos2-1);
		top1->next = q;
		r = q->next;
		q->next = p->next;
		top2->next = p;
		p->next = r;
	}
	else{
		top1 = link_inquire_pos(H,pos1-1);
		top1->next = q;
		p->next = q->next;
		q->next = p;
	}
	return 0;
}```
求链表长度的函数

```c
int link_long(linklist H){
	linklist p;
	p = H->next;
	if(H == NULL){
		return -1;
	}
	if(H->next == NULL){
		return 0;
	}
	int i = 0;
	while(p){
		i++;
		p = p->next;
	}
	return i;
}```

下面我们就可以编辑排序函数啦
前边是做了一些准备编了一些函数,排序函数具体做法是:找到需要交换的节点位置,将两个节点交换(具体说明在注释中)
```c
int link_rank(linklist H){
	if(H == NULL){
		return 0;
	}
	if(H->next == NULL){  //空链表就没必要了 
		printf("the node is no data\n");
		return 0;
	}
	if(H->next->next == NULL){  //链表就一个节点(不包括头节点)也不用排序
		printf("the node just one data\n");
		return 0;
	}
#if 1
	linklist p,q;
	p = H->next;
	q = p->next;
	int i,j,k;
	k = link_long(H);
	i = 1;  //用i,j表示p,q指向的节点位置
	j = 2;
	while(i <= k-1){
		while(j <= k){
			if(q->a < p->a){
				link_exch(H,i,j);//将两个节点位置交换
				/*根据位置找出节点,恢复节点原来指向的位置
				(因为交换后p,q还指向原来的节点而这个函数
				是利用位置进行操作的,所以需要将p,q指向原来的位置)*/
				q = link_inquire_pos(H,j);
				p = link_inquire_pos(H,i);
			}
			j++;
			q = q->next;
		}
		i++;
		j = i+1;
		p = p->next;
		q = p->next;//将q节点指向p后的一个节点
	}
#else  //这个是只交换节点所存储的数据,以达到排序的目的
	linklist p,q;
	data_t i;
	p = H->next;
	q = p->next;
	while(p->next){
		while(q){
			if(q->a < p->a){
				i = q->a;
				q->a = p->a;
				p->a = i;
			}
			q = q->next;
		}
		p = p->next;
		q = p->next;
	}
#endif
	return 0;
}

我们来执行一下单链表排序

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"linktable.h"//这个是我自己写得头文件,见附件

int main(){
linklist H;
data_t a;
H = link_creart();
while(1){
		scanf("%d",&a);
		if(a == -1){  //输入-1停止输入
			break;
		}
		link_insert_last(H,a);
	}
	link_show(H);
	link_rank(H);
	link_show(H);
	H =	link_free(H);//释放节点所占内存
	return 0;
}

执行结果
在这里插入图片描述
我自己变得库文件
链接:https://pan.baidu.com/s/1hoIIRPrCm7w-9vMM294jyg
提取码:aiyy

菜鸟一枚,还请各位大神多多指教。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值