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

957

被折叠的 条评论
为什么被折叠?



