单链表的 C 语言实现

用 C 语言实现一个单链表,包含链表的创建、遍历、插入、删除、排序、反转等常用操作

# include<stdio.h>
# include<stdlib.h>
# include<malloc.h>

//定义链表节点结构体 
struct Node
{
	int data;
	struct Node * pNext;
};
//函数声明 
struct Node * createLinkedList(void);
void traverseLinkedList(struct Node * pHead);
bool isEmptyLinkedList(struct Node * pHead);
int getLinkedListSize(struct Node * pHead);
void sortLinkedList(struct Node * pHead);
bool insertLinkedList(struct Node * pHead, int pos, int val);
bool deleteLinkedList(struct Node * pHead, int pos, int * val);
struct Node * reverseLinkedList(struct Node * pHead);
void traverseLinkedList2(struct Node * pHead);//用于链表翻转后的遍历输出 

int main(void)
{
	struct Node * pHead = NULL;
	
	pHead = createLinkedList();
	
	traverseLinkedList(pHead);
	
	if (isEmptyLinkedList(pHead))
	{
		printf("链表为空\n");
	}
	else
	{
	   	int length = getLinkedListSize(pHead);
		printf("链表不为空,链表的长度为 len= %d \n",length);
		
		sortLinkedList(pHead);
		printf("排序后的链表\n");
		traverseLinkedList(pHead);
		
		insertLinkedList(pHead,1,666);
		printf("插入新节点后的链表\n");
		traverseLinkedList(pHead);
		
		length = getLinkedListSize(pHead);
		printf("插入新节点后的链表长度为 len= %d \n",length);
		
//		int val;
//		deleteLinkedList(pHead,2,&val);
//		printf("删除节点%d后的链表\n",val);
//		traverseLinkedList(pHead);
		
		struct Node * reverseHead = reverseLinkedList(pHead);
		printf("反转后的链表\n");
		traverseLinkedList(reverseHead);
		
		printf("\n=================\n");
		insertLinkedList(reverseHead,0,777);
		printf("插入新节点后的链表\n");
		traverseLinkedList(reverseHead);
	}

	
	
	return 0;
} 
struct Node * createLinkedList(void)
{
	int len;//链表长度
	int i;
	int val;
	//创建头指针,指向头结点 
	struct Node * pHead = (struct Node *)malloc(sizeof(struct Node));
	if (pHead == NULL)
	{
		printf("create failed!");
		exit(-1);
	}
	//定义一个尾指针,永远指向最后一个节点 
	struct Node * pTail = pHead;
	pTail->pNext = NULL;//初始时刻,头结点指针域和数据域都为空,避免垃圾值 
	pTail->data = NULL;
	
	printf("please input the length of list: len= ");
	scanf("%d",&len);
	
	//循环创建链表
	for (i=0; i<len; i++)
	{
		struct Node * pNew = (struct Node *)malloc(sizeof(struct Node));
		
		printf("please input the %d list value:",i+1);
		scanf("%d",&val);
		 
		pNew->data = val;
		pTail->pNext = pNew;
		pTail = pNew;
		pTail->pNext = NULL; 
		
	}
	
	return pHead; 
}
void traverseLinkedList(struct Node * pHead)
{ 
	struct Node * p = pHead;//定义 一个指针p指向头结点,用于循环遍历输出 
	//兼容反转后的链表也能输出 
	if (p->data == NULL)
		p = p->pNext; 
	while (p != NULL)
	{
		printf("%d ",p->data);
		p = p->pNext;
	}


	//用这种方式不太好,一个循环下来改变了pHead的值 
//	while (pHead->pNext != NULL)
//	{
//		printf("%d ",pHead->pNext->data);
//		pHead = pHead->pNext;
//	}
	printf("\n");
	
	return ;
} 
bool isEmptyLinkedList(struct Node * pHead)
{
	if (pHead->pNext != NULL)
	{
		return false;
	}
	else
	{ 
		return true;
	}
}
int getLinkedListSize(struct Node * pHead)
{
	int len=0;
	//先判断链表是否为空 
	if (isEmptyLinkedList(pHead))
	{
		len = 0;
		return len;
	}	
	while (pHead->pNext != NULL)
	{
		len++;
		pHead = pHead->pNext;
	}
	
	return len;
}
void sortLinkedList(struct Node * pHead)
{
	int i,j,tmp;
	struct Node * p;
	struct Node * q;
	int length = getLinkedListSize(pHead);
	
	for (i=0,p=pHead->pNext; i<length; i++,p=p->pNext)
	{
		for (j=i+1,q=p->pNext; j<length; j++,q=q->pNext)
		{
			if (p->data > q->data)
			{
				tmp = p->data;
				p->data = q->data;
				q->data = tmp;
			}
		}
	}
}

bool insertLinkedList(struct Node * pHead, int pos, int val)
{
	int i=0;
	struct Node * p = pHead;
	//执行完while语句,此时的p已经指向了pos前的一个节点 
	while (p != NULL && i<pos-1)// 1 2 3 4 5
	{
		p = p->pNext;
		i++;
	}
	if (i>pos-1 || p==NULL)
	{
		return false;
	}
	//pos=1直接从这里开始执行 
	struct Node * pNew = (struct Node *)malloc(sizeof(struct Node));
	if (NULL == pNew)
	{
		printf("create failed!\n"); 
		exit(-1);
	}
	pNew->data = val;
	pNew->pNext = p->pNext;
	p->pNext = pNew;
	
	return true;
}

bool deleteLinkedList(struct Node * pHead, int pos, int * val)
{
	int i = 0;
	struct Node * p = pHead;//此时p指向头结点,注意是头结点
	//比如要删除pos=2的节点,经过while循环后,p已经指向了首节点,首节点的指针域保存的下一个节点(也就是pos=2)的地址 
	while (p->pNext!=NULL && i<pos-1)
	{
		p = p->pNext;
		i++;
	}
	if (i>pos-1 || p==NULL)
	{
		return false;
	}
	*val = p->pNext->data;
	p->pNext = p->pNext->pNext;
	
	return true;
}
struct Node * reverseLinkedList(struct Node * pHead)
{
	/*
		带有头结点和尾节点的链表反转后对比:
		反转前:头结点数据域不存任何值,指针域保存下一节点的地址,尾节点指针域为空
		反转后:头结点数据域有值,指针域保存下一节点的地址,尾节点指针域为空
		反转后没有了头结点 
	*/
	if (pHead==NULL || pHead->pNext == NULL)
	{
		return pHead;
	}

	pHead = pHead->pNext;//首先跳过头结点,此时pHead指向了首节点 
	struct Node * curNode = pHead;//curNode指向了首节点 
	struct Node * preNode = NULL;
	while (curNode)
	{
		//第一次循环后,curNode指向了首节点的下一个节点,preNode指向了首节点 
		//第二次循环后,curNode指向的那个节点的指针域保存了preNode节点的地址(既首节点的地址),所以首节点的下一个节点指向了首节点,并且curNode和preNode分别后移一位 
		//依次循环,直到最后。。 
		struct Node * tmpNode = curNode->pNext;
		curNode->pNext = preNode;
		preNode = curNode;
		curNode = tmpNode;
	}
	
	return preNode;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值