C语言实现链表(三)

如下是实现双向链表的源代码,主要包括:创建链表、插入结点(头插法、尾插法)、遍历链表、删除结点、排序(插入、快速)、清空链表、主函数(验证函数功能),源代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
//不带头结点的双向链表的操作

//本结构体只是为了实现原理的方便,采用了最简单的元素结构,只有一个int型、前指针pre、后指针next
typedef struct NODE
{
	int elem; 
	struct NODE *pre;
	struct NODE *next;
}Node, *pNode;

//创建不带头结点的双向链表,创建同时,赋值第一个值
pNode Create()
{
	pNode pHead = (pNode)malloc(sizeof(Node));
	if(NULL == pHead)
	{
		printf("内存申请失败");
		return NULL;
	}
	printf("插入结点的值:");
	scanf("%d",&pHead->elem);
	pHead->pre = 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);
	if(NULL == pHead)
	{
		temp->next = NULL;
		temp->pre = NULL;
		return temp;		
	}
	temp->next = pHead;
	pHead->pre = temp;
	temp->pre = NULL;
	return temp;
}

//插入结点函数,尾插法
pNode InsertTail(pNode pHead)
{
	pNode temp = (pNode)malloc(sizeof(Node));
	pNode currentNode = pHead;
	if(NULL == pHead)
	{
		printf("内存申请失败");
		return pHead;
	}
	printf("插入结点的值:");
	scanf("%d",&temp->elem);
	if(NULL == pHead)
	{
		temp->next = NULL;
		temp->pre = NULL;
		return temp;
	}
	while(currentNode->next != NULL)    //找到尾结点
	{
		currentNode = currentNode->next;
	}
	currentNode->next = temp;
	temp->pre = currentNode;
	temp->next = NULL;
	return pHead;
}

//遍历函数
void Traversal(pNode pHead)
{
	if(pHead == NULL)
	{
		printf("链表未创建\n");
		return ;
	}
	while(pHead != NULL)
	{
		printf("%d\n",pHead->elem);
		pHead = pHead->next;
	}
}

//删除函数
pNode Delete(pNode pHead)
{
	bool flag = false;   //判断是否找到了要删除的结点
	if(NULL == pHead)
	{
		return pHead;
	}
	int elem;
	printf("要删除的值为:");
	scanf("%d",&elem);
	pNode currentNode = pHead;
	while(currentNode != NULL)  //寻找要删除的结点
	{
		if(currentNode->elem == elem)
		{
			flag = true;   //找到了要删除的结点,flag = true,并且跳出循环
			break;		   //currentNode即为要删除的结点
		}
		currentNode = currentNode->next;
	}
	if(flag)    //找到了要删除的结点
	{
		if(NULL == currentNode->pre && NULL == currentNode->next)  //删除只有一个结点的链表
		{
			free(currentNode);
			return NULL;
		}
		else if(NULL == currentNode->pre && NULL != currentNode->next)  //删除第一个结点,并且该链表不只有一个结点
		{
			currentNode = currentNode->next;
			currentNode->pre = NULL;
			free(currentNode->pre);
			return currentNode;
		}
		else if(NULL == currentNode->next)          //删除尾结点
		{
			currentNode->pre->next = NULL;
			free(currentNode);
			return pHead;
		}
		else
		{
			currentNode->pre->next = currentNode->next;        //删除中间结点
			currentNode->next->pre = currentNode->pre;
			free(currentNode);
			return pHead;
		}
	}
	else  //未找到要删除的结点
	{
		printf("未找到值为%d的结点\n",elem);
		return pHead;
	}
}

//插入排序函数,指针交换
//也可以通过new一个新的头结点,仿照带头结点的单向链表的做法,此方法比较简单
//因为不用考虑插入到最前面的这种情况,有兴趣的可以尝试写一下
pNode SortInsert(pNode pHead)
{
	if(NULL == pHead || NULL == pHead->next)
	{
		return pHead;   //无头结点、只有头结点、只有一个头结点和一个基本结点,没有意义
	}
	pNode currentNode = pHead;
	pNode currentNodeBefore = pHead;
	pNode compareNode = pHead->next;
	currentNode->next = NULL;
	compareNode->pre = NULL;
	pNode compareNodeTemp = NULL;
//通过compareNode和currentNode的元素值比较,判断插入位置
	while(compareNode != NULL)
	{
		currentNode = pHead;
		compareNodeTemp = compareNode->next;
		while(currentNode != NULL)
		{
			if(currentNode->elem > compareNode->elem)
			{
				if(NULL == currentNode->pre)     //插入最前面
				{
					compareNode->next = currentNode;
					currentNode->pre = compareNode;
					compareNode->pre = NULL;
					pHead = compareNode;
				}
				else                              //插入两结点中间
				{
					currentNode->pre->next = compareNode;
					compareNode->pre = currentNode->pre;
					compareNode->next = currentNode;
					currentNode->pre = compareNode;
				}
				break;
			}
			currentNodeBefore = currentNode;
			currentNode = currentNode->next;
		}
		if(NULL == currentNode)              //插入尾部
		{
			currentNodeBefore->next = compareNode;
			compareNode->pre = currentNodeBefore;
			compareNode->next = NULL;
		}
		compareNode = compareNodeTemp;
	}
	return pHead;
}

//插入排序,交换值域,思路和交换指针一样,整体来说,比交换指针域简单
pNode SortInsertNum(pNode pHead)
{
	if(NULL == pHead || NULL == pHead->next)
	{
		return pHead;   //无结点、只有一个结点,没有意义
	}
	pNode currentNode = pHead;
	pNode compareNode = currentNode->next;
	pNode compareNodeTemp;
	int temp;
	while(compareNode != NULL)
	{
		currentNode = pHead;
		while(currentNode != compareNode)
		{
			compareNodeTemp = compareNode;
			if(currentNode->elem > compareNode->elem)  //找到了插入位置
			{
				temp = compareNode->elem;
				for(; compareNodeTemp != currentNode; )  //将compareNode之前一直到currentNode的元素值都向后移动一个结点
				{										 
					compareNodeTemp->elem = compareNodeTemp->pre->elem;
					compareNodeTemp = compareNodeTemp->pre;
				}
				currentNode->elem = temp;
			}
			currentNode = currentNode->next;
		}
		compareNode = compareNode->next;
	}
	return pHead;
}

//找到尾结点函数,为了快速排序的需要
pNode FindTail(pNode pHead)
{
	if(NULL == pHead || NULL == pHead->next)
	{
		return pHead;   //无结点、只有一个结点,没有意义
	}
	pNode pTail;
	pNode currentNode = pHead;
	while(currentNode->next != NULL)
	{
		currentNode = currentNode->next;
	}
	pTail = currentNode;
	return pTail;
}

//找到分割链表的结点函数,快速排序一部分
pNode Partition(pNode pLow, pNode pHigh)
{
	int key = pLow->elem;
	while(pLow != pHigh)
	{
		while(pLow != pHigh && pHigh->elem >= key)
			pHigh = pHigh->pre;
		if(pLow != pHigh)
		{
			pLow->elem = pHigh->elem;
			pLow = pLow->next;
		}
		while(pLow != pHigh && pLow->elem <= key)
		 	pLow = pLow->next;
		if(pLow != pHigh)
		{
			pHigh->elem = pLow->elem;
			pHigh = pHigh->pre;
		}
	}
	pLow->elem = key;
	return pLow;
}

//快速排序函数,值域交换
//指针域交换太复杂,弗敢想象,you can you up
//我在写这个排序过程中,主要是参照数组的快速排序方法,其实原理一样,只是判断条件会有所区别
void SortQuick(pNode pHead, pNode pTail)
{
	pNode pPos;
	if(pHead != pTail)
	{
		pPos = Partition(pHead,pTail);
		if(pPos != pHead)   //pPos如果为头结点,pPos->pre会出现问题
		{
			SortQuick(pHead,pPos->pre);
		}
		if(pPos != pTail)   //同理
		{
			SortQuick(pPos->next,pTail);
		}
	}
	return ;
}

//清除链表,释放空间,函数最后调用
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;
	pNode pTail;
	pHead = Create();
	pHead = InsertTail(pHead);
	pHead = InsertTail(pHead);
	pHead = InsertTail(pHead);
	pHead = InsertTail(pHead);
	Traversal(pHead);
	printf("\n");
	pHead = Delete(pHead);
	pHead = SortInsert(pHead);
	pHead = SortInsertNum(pHead);
	pTail = FindTail(pHead);
	SortQuick(pHead,pTail);
	Traversal(pHead);
	ClearList(pHead);

	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值