C语言实现链表(二)

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

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


首先新建一个新头结点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;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值