C语言实现链表(二)

来源:互联网 发布:西西里的美丽传说知乎 编辑:程序博客网 时间:2024/06/16 08:33

如下是单向链表的具体实现,主要包括:创建链表、增加结点(头插法,尾插法)、遍历结点、删除结点、排序(插入排序、选择排序、冒泡排序)、清空链表、最后是主函数的验证。

在此先说下我的插入排序(交换指针)的思路:如图


首先新建一个新头结点newHead,将原链表中从第二个有效结点开始之后所有的结点都链接到newHead,因此原链表就只有了一个有效结点,现在将newHead此链表中的结点(头结点除外)一个一个的插入到pHead中,就是比较newHead->next的元素的值与pHead中所有结点的值,找到合适的位置(本例以从小到大顺序排列),然后将newHead->next这个结点插入到pHead该位置,并且,newHead->next相应的也后移一个结点,具体实现见代码。


#include <stdio.h>#include <stdlib.h>#include <string.h>//创建、插入、删除、遍历、排序(插入、选择)//带头结点的单链表的操作//本结构体只是为了实现原理的方便,采用了最简单的元素结构,只有一个int型和next指针typedef struct NODE{int elem;struct NODE *next;}Node, *pNode;//创建带头结点的单项链表,本函数只是创建头结点pNode Create(){pNode pHead = (pNode)malloc(sizeof(Node));if(NULL == pHead){printf("内存申请失败");return NULL;}pHead->next = NULL;return pHead;}//插入结点函数,头插法pNode InsertHead(pNode pHead){pNode temp = (pNode)malloc(sizeof(Node));if(NULL == temp){printf("内存申请失败");return pHead;}printf("插入结点的值:");scanf("%d",&temp->elem);temp->next = pHead->next;  //在pHead和pHead->next中插入一个节点pHead->next = temp;return pHead;}//插入结点函数,尾插法pNode InsertTail(pNode pHead){pNode temp = (pNode)malloc(sizeof(Node));pNode currentNode = pHead;if(NULL == pHead){printf("内存申请失败");return pHead;}printf("插入结点的值:");scanf("%d",&temp->elem);while(currentNode->next != NULL)  //循环找到最后一个节点{currentNode = currentNode->next;}currentNode->next = temp;      //新结点插入到尾部temp->next = NULL;return pHead;}//遍历函数void Traversal(pNode pHead){if(pHead == NULL){printf("链表未创建\n");return ;}else if(pHead->next == NULL)   {printf("链表只有头结点\n");return ;}while(pHead->next != NULL)      //遍历到尾部,然后打印出elem的值{printf("%d\n",pHead->next->elem);pHead = pHead->next;}}//删除函数pNode Delete(pNode pHead){if(NULL == pHead || NULL == pHead->next){return pHead;}int elem;printf("要删除的值为:");scanf("%d",&elem);pNode currentNode = pHead->next;pNode currentNodeBefore = pHead;while(currentNode != NULL)        //遍历到尾部{if(currentNode->elem == elem)  //找到要删除的元素{currentNodeBefore->next = currentNode->next;  //更改结点指向,然后freefree(currentNode);return pHead;}currentNodeBefore = currentNode;currentNode = currentNode->next;}printf("未找到值为%d的结点\n",elem);return pHead;}//插入排序,交换指针pNode SortInsert(pNode pHead){if(NULL == pHead || NULL == pHead->next || NULL == pHead->next->next){return pHead;   //无头结点、只有头结点、只有一个头结点和一个基本结点,没有意义}pNode newHead = (pNode)malloc(sizeof(Node));  //创建一个新的结点if(NULL == newHead){printf("内存申请失败");return pHead;}newHead->next = pHead->next->next;pHead->next->next = NULL;while(newHead->next != NULL)       //外层循环,判断newHead中是否还有结点需要插入{pNode currentNode = pHead->next;pNode currentNodeBefore = pHead;while(currentNode != NULL)//内层循环,判断新结点插入位置{if(currentNode->elem > newHead->next->elem)  //找到插入位置{currentNodeBefore->next = newHead->next;newHead->next = newHead->next->next;currentNodeBefore->next->next = currentNode;break;}currentNodeBefore = currentNode;currentNode = currentNode->next;}if(NULL == currentNode)         //上述循环中未找到插入位置,说明应该插入尾部{currentNodeBefore->next = newHead->next;newHead->next = newHead->next->next;currentNodeBefore->next->next = currentNode;}}free(newHead);return pHead;}//插入排序,交换值域,因为涉及到链表的前一指针,所以在单链表中通过交换值域来插入排序不是很适用//双向链表中将会介绍//选择排序,交换指针pNode SortChoose(pNode pHead){if(NULL == pHead || NULL == pHead->next || NULL == pHead->next->next){return pHead;   //无头结点、只有头结点、只有一个头结点和一个基本结点,没有意义}pNode currentNode = pHead->next;pNode currentNodeBefore = pHead;pNode compareNode = currentNode->next;pNode compareNodeBefore = currentNode;pNode currentNodeTemp;while(NULL != compareNode)   //外层循环,判断是否还有待选结点作为最小值        {while(NULL != compareNode)  //内存循环,从待选最小值所在结点的后一个结点开始往后遍历,一个个比较{if(currentNode->elem > compareNode->elem)  //找到比假象最小值结点更小的结点{if(currentNode->next != compareNode)     //如果比较的两个结点是紧邻结点,需要单独讨论 {currentNodeBefore->next = compareNode;currentNodeTemp = compareNode->next;compareNode->next = currentNode->next;currentNode->next = currentNodeTemp;compareNodeBefore->next = currentNode;}else                               //比较两个结点不是紧邻结点{currentNodeBefore->next = compareNode;currentNode->next = compareNode->next;compareNode->next = currentNode;}                                 compareNode = currentNode->next;      //为下一次内层循环做准备compareNodeBefore = currentNode;currentNode = currentNodeBefore->next;}else{compareNodeBefore = compareNode;compareNode = compareNode->next;}}currentNodeBefore = currentNode;   //为下一次外层循环做准备currentNode = currentNode->next;compareNodeBefore = currentNode;compareNode = currentNode->next;}return pHead;}//选择排序,交换值域,可以看出,交换值域比交换指针至少代码量简单很多很多!!!pNode SortChooseNum(pNode pHead){if(NULL == pHead || NULL == pHead->next || NULL == pHead->next->next){return pHead;   //无头结点、只有头结点、只有一个头结点和一个基本结点,没有意义}pNode currentNode = pHead->next;pNode compareNode;int temp;while(currentNode != NULL){compareNode = currentNode->next;while(compareNode != NULL){if(currentNode->elem > compareNode->elem)  //找到更小的值,然后交换{temp = currentNode->elem;currentNode->elem = compareNode->elem;compareNode->elem = temp;}compareNode = compareNode->next;}currentNode = currentNode->next;}return pHead;}//冒泡排序,交换指针pNode SortBubble(pNode pHead){if(NULL == pHead || NULL == pHead->next || NULL == pHead->next->next){return pHead;   //无头结点、只有头结点、只有一个头结点和一个基本结点,没有意义}pNode currentNode;pNode currentNodeBefore;pNode compareNode;pNode end = NULL;while(end != pHead->next->next)     //外层循环,用一个end指针来判断{currentNode = pHead->next;currentNodeBefore = pHead;compareNode = currentNode->next;while(compareNode != end)        //内层循环,也是用一个end指针来判断{if(currentNode->elem > compareNode->elem)  //找到较小的数,交换{currentNodeBefore->next = compareNode;currentNode->next = compareNode->next;compareNode->next = currentNode;currentNodeBefore = compareNode;compareNode = currentNode->next;}else{currentNodeBefore = currentNode;currentNode = currentNode->next;compareNode = currentNode->next;}}end = currentNode;}return pHead;}//冒泡排序,交换值域,原理和指针交换差不多,但是比交换指针简单很多pNode SortBubbleNum(pNode pHead){if(NULL == pHead || NULL == pHead->next || NULL == pHead->next->next){return pHead;   //无头结点、只有头结点、只有一个头结点和一个基本结点,没有意义}pNode currentNode = pHead->next;pNode compareNode = currentNode->next;pNode pEnd = NULL;int temp;while(compareNode != pEnd)     {while(compareNode != pEnd){if(currentNode->elem > compareNode->elem){temp = currentNode->elem;currentNode->elem = compareNode->elem;compareNode->elem = temp;}currentNode = currentNode->next;compareNode = currentNode->next;}pEnd = currentNode;currentNode = pHead->next;compareNode = currentNode->next;}return pHead;}//快速排序,因为在排序过程中需要访问前一结点,所以单向链表不适合用快速排序//清除链表,释放空间,函数最后调用void ClearList(pNode pHead){pNode temp;while(pHead != NULL){temp = pHead->next;free(pHead);pHead = temp;}}int main(int argc, char const *argv[]){pNode pHead;pHead = Create();pHead = InsertTail(pHead);pHead = InsertTail(pHead);pHead = InsertTail(pHead);pHead = InsertHead(pHead);pHead = InsertHead(pHead);pHead = InsertHead(pHead);pHead = InsertHead(pHead);pHead = InsertHead(pHead);Traversal(pHead);printf("\n");pHead = SortInsert(pHead);pHead = SortChoose(pHead);pHead = SortBubble(pHead);pHead = SortChooseNum(pHead);pHead = SortBubbleNum(pHead);pHead = Delete(pHead);Traversal(pHead);ClearList(pHead);return 0;}


 
原创粉丝点击