如下是单向链表的具体实现,主要包括:创建链表、增加结点(头插法,尾插法)、遍历结点、删除结点、排序(插入排序、选择排序、冒泡排序)、清空链表、最后是主函数的验证。
在此先说下我的插入排序(交换指针)的思路:如图
首先新建一个新头结点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; //更改结点指向,然后free free(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; }