单链表排序(移动节点)
单链表排序利用了选择排序的方式;
创建一个单链表结构体
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
菜鸟一枚,还请各位大神多多指教。