单向链表的实现

编程入门 行业动态 更新时间:2024-10-25 05:18:44

单向<a href=https://www.elefans.com/category/jswz/34/1769662.html style=链表的实现"/>

单向链表的实现

本想先用快速排序算法对一个数组的元素从小到大进行排序,然后把快速排序算法用于链表元素从小到大进行排序的,但是发现一个问题改变了我的想法,先把问题呈上。

volatile uint16_t count = 0;//统计递归执行的次数
volatile uint16_t num   = 0;//统计快速算法进行排序时执行的次数//快速排序算法--从小到大依次排序
void quickSort(uint8_t *dataBuf,uint8_t leftSub,uint8_t rightSub)
{uint8_t left,right,temp;uint8_t keyNum;left          = leftSub;right        = rightSub;keyNum  = dataBuf[(leftSub+rightSub)/2];++count;while(left <= right){++num;//从左到右找比keyNum大的元素while((dataBuf[left] < keyNum) && (left < rightSub)){left++;}//从右到左找比keyNum小的元素while((dataBuf[right] > keyNum) && (right > leftSub)){right--;}//若找到且满足条件的,则交换if(left <= right){temp = dataBuf[left];dataBuf[left] = dataBuf[right];dataBuf[right] = temp;left++;right--;}}if(left < rightSub){quickSort(dataBuf,left,rightSub);}if(right >leftSub){quickSort(dataBuf,leftSub,right);}
}int main()
{uint8_t data[]={8,2,5,3,4,6,9,1,7};//组1:8,2,5,3,4,6,9,1,7    组2:9,7,8,6,5,4,2,3,1quickSort(data,0,sizeof(data)-1);//把数组,最左下标和最有下标作为参数传入快速排序函数中printf("count=%d,num=%d \r\n",count,num);for(uint8_t index = 0;index < sizeof(data);index++){printf("%d ",data[index]);}return 0;
}

数组元素经过从小到大的排序后,输出打印显示如下所示,

 我们可以看到,对这样一组数据data[]={8,2,5,3,4,6,9,1,7}进行排序,调用快速排序算法函数调了6次,内部总共执行了9次完成了从小到大的排序,这种情况是比较理想的,如果我们把data数组的元素换成组2的元素,再打印结果,出乎了我们的预料,打印结果如下:

我们可以看到,用快速算法对数组data[]={9,7,8,6,5,4,2,3,1}从小到大进行排序,发现调用快速算法函数72次,内部总共执行510次,程序没有继续执行,发生异常了,如果在程序中使用快速算法,会导致程序内存溢出,程序崩溃等故障,所以在这里(单向链表元素数据项进行排序)就不用快速排序算法, 网上查了一下几种排序算法的稳定性,可以看到,插入、冒泡、堆、归并和基数排序是稳定的。

选择排序算法的特点: (1)可用于链式存储结构。 (2)移动记录次数较少,当每一记录占用的空间较多时,选择排序比直接插入排序快。

这里我们用选择排序对单向链表的元素数据项从小到大进行排序,首先还是先用选择排序对一个数组进行从小到大进行排序,然后在这个选择排序算法函数中把数组改为单向链表。

//选择排序算法--从小到大依次排序
void SelectSort(uint8_t *dataBuf,uint16_t length)
{uint8_t temp=0;printf("未排序的数组:\r\n");ArrayPrintShow(dataBuf,length);//排一次序printf("\r\n正在排序的数组:\r\n");for(uint8_t i = 0;i<length-1;i++){for(uint8_t j = i+1;j<length;j++){if(dataBuf[i] > dataBuf[j]){temp       = dataBuf[i];dataBuf[i] = dataBuf[j];dataBuf[j] = temp;}}ArrayPrintShow(dataBuf,length);//排一次序}
}//信息打印显示
void ArrayPrintShow(uint8_t *data,uint16_t len)
{for(uint8_t index = 0;index < len;index++){printf("%d ",data[index]);}printf("\r\n");
}int main()
{uint8_t data[]={9,7,8,6,5,4,2,3,1};SelectSort(data,sizeof(data));return 0;
}

数组经过从小到大进行排序后,打印结果如下所示:

 下面我们就在这个选择排序算法函数中对前面讲的单向链表中的图书价格进行从小到达进行排序,最后再输出打印显示。

根据算法画出流程图如下图所示:

 选择排序算法程序实现如下所示:

int SingLinkList_SelectSort(BOOKLT *bookHeadNode)
{BOOKLT *pFront = bookHeadNode;BOOKLT *p = pFront->next;BOOKLT *qFront = NULL;BOOKLT *q = NULL;BOOKLT * temp = NULL;if((NULL==pFront->next)||(NULL==p->next))//链表只有头结点或者链表只有一个结点不需要排序{return -1;}while(p)//pFront->next不等于空{qFront = p;q = qFront->next;while(q)//qFront->next不等于空{if((p->bookInfo.price) > (q->bookInfo.price)){/*//方式一:结点内存数据拷贝,不交换结点memcpy(temp->bookInfo.ISBN,q->bookInfo.ISBN,sizeof(q->bookInfo.ISBN));memcpy(temp->bookInfo.bookName,q->bookInfo.bookName,sizeof(q->bookInfo.bookName));temp->bookInfo.price = q->bookInfo.price;memcpy(q->bookInfo.ISBN,p->bookInfo.ISBN,sizeof(q->bookInfo.ISBN));memcpy(q->bookInfo.bookName,p->bookInfo.bookName,sizeof(q->bookInfo.bookName));q->bookInfo.price = p->bookInfo.price;memcpy(p->bookInfo.ISBN,temp->bookInfo.ISBN,sizeof(q->bookInfo.ISBN));memcpy(p->bookInfo.bookName,temp->bookInfo.bookName,sizeof(q->bookInfo.bookName));p->bookInfo.price = temp->bookInfo.price;*///方式二:只移动指针指向,不拷贝数据;断开结点,结点交换,再重新插入节点if(qFront == p)//情况1:p结点和q结点相邻,且p结点元素中的价格数据项大于q结点元素中的价格数据项{//主链表断开p结点和q结点qFront->next=q->next;q->next = NULL;qFront=pFront;//重置qFrontpFront->next=p->next;p->next = NULL;//两个结点相互切换指向temp = q;q = p;p = temp;//重新把新p结点插入到pFront之后p->next = pFront->next;pFront->next = p;qFront = p; //重置qFront//重新把新q结点插入到qFront之后q->next=qFront->next;qFront->next=q;}else//情况2{//主链表断开p结点和q结点qFront->next = q->next;q->next = NULL;pFront->next = p->next;p->next = NULL;//两个结点相互切换指向temp = q;q = p;p = temp;//重新把新p结点插入到pFront之后p->next = pFront->next;pFront->next = p;//重新把新q结点插入到qFront之后q->next = qFront->next;qFront->next=q;}}//内循环--往下一个结点移动qFront = q;q = qFront->next;}//外循环--往下一个结点移动pFront = p;p = pFront->next;}return true;
}

 main.c主文件实现如下所示:

int main()
{BOOKLT *myBookHeadNode;//定义一个BOOKLT类型的头结点指针myBookHeadNode  = SingLinkList_Create();//上面的链表内存已经被释,重新放创建一个头结点SingLinkList_TailInsert_method2(myBookHeadNode,sizeof(bookStock)/sizeof(BOOKINFO),bookStock);//后插法插入节点printf("=============所有图书信息打印如下=================\r\n");SingLinkList_Traverse(myBookHeadNode);//遍历单向链表printf("\r\n===========所有图书价格从低到高排序如下===========\r\n");//价格从低到高进行排序再输出SingLinkList_SelectSort(myBookHeadNode);//选择排序调用SingLinkList_Traverse(myBookHeadNode);//遍历单向链表SingLinkList_Destory(myBookHeadNode);//释放各个结点的内存和头结点的内存return 0;
}

图书价格排序前和排序后如下图所示:

 到此,图书价格按低到高顺序排序功能已完成。

2022.06.19结。

更多推荐

单向链表的实现

本文发布于:2024-02-12 19:47:33,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1689171.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:链表

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!