链表有单项链表和双向链表,在这里只讲单项链表的一些功能实现,包括链表的初始化,尾插、尾删,头插、头删,指定结点位置插入元素,删除一个x元素和所有x元素,以及删除指定位置的结点,冒泡排序等

首先定义出链表的结构,包括结点的定义和函数的声明

LinkList.h

#ifndef _LINKLIST_H__
#define _LINKLIST_H__


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

typedef int DataType;
typedef struct LinkNode		//定义一个结点
{
	struct LinkNode *next;
	DataType data;
}LinkNode,*pLinkNode;
typedef struct LinkList		//定义链表
{
	LinkNode *pHead;
}LinkList,*pLinkList; 

void Init(pLinkList pList);	//初始化
void Destory(pLinkList pList);	//销毁
void Print(pLinkList pList);	//输出
void PushBack(pLinkList pList,DataType x);	//尾插
void PopBack(pLinkList pList);	//尾删
void PushFront(pLinkList pList,DataType x);	//头插
void PopFront(pLinkList pList);	//头删
pLinkNode Find(pLinkList pList,DataType x);	//公共查找函数
void Insert(pLinkList pList,pLinkNode pos,DataType x);	//指定结点位置插入
void Remove(pLinkList pList,DataType x);	//删除一个X元素
void RemoveAll(pLinkList pList,DataType x);	//删除所有X元素
void Erase(pLinkList pList,pLinkNode pos);	//删除指定位置的结点
void BubbleSort(pLinkList pList);	//冒泡排序

#endif //_LINKLIST_H__
接下来就是各函数的实现部分:

@初始化:

只需将函数的头指针置为空

void Init(pLinkList pList)	//初始化
{
	assert(pList);
	pList->pHead = NULL;
}

@尾插:

首先得创建一个新结点,然后找到最后一个结点,将最后一个节点的next指针指向新结点


void PushBack(pLinkList pList,DataType x)	//尾插
{
	pLinkNode cur = NULL;
	pLinkNode newnode = NULL;
	assert(pList);
	cur = pList->pHead;
	newnode = BuyNode(x);
	//没有结点
	if(NULL == pList->pHead)
	{
		pList->pHead = newnode;
		newnode->next = NULL;
		return ;
	}
	//有一个或以上的结点
	while(cur->next)
	{
		cur = cur->next;
	}
	cur->next = newnode;
	newnode->next = NULL;
}

@尾删:

1.链表为空时不操作;2.链表不为空的情况下找到最后一个结点,将其free并将前一个结点的next指针置为空

void PopBack(pLinkList pList)	//尾删
{
	pLinkNode cur = NULL;
	pLinkNode prev = NULL;
	assert(pList);
	//没有结点
	if(NULL == pList->pHead)
	{
		printf("LinList is empty!\n");
		return ;
	}
	//有结点
	cur = pList->pHead;
	while(cur->next)
	{
		 prev = cur;
		 cur = cur->next;
	}
	free(cur);
	cur = NULL;
	prev->next = NULL;
}

@头插:

1.链表如果为空,将pHead指向新创建的结点;2.如果不为空,将pHead指向新创建的结点并将新结点的next指针指向原链表的第一个结点。如图:


@头删:

1.链表为空时不操作;2.链表不为空时,将pHead指向第二个结点并将第一个结点free掉


void PopFront(pLinkList pList)	//头删
{
	pLinkNode cur = NULL;
	pLinkNode del = NULL;
	assert(pList);
	//无节点
	if(NULL == pList->pHead)
	{
		printf("LinkList is empty!\n");
		return ;
	}
		return ;
	//有一个或以上结点
	cur = pList->pHead;
	del = cur;
	cur = cur->next;
	free(del);
	del = NULL;
	pList->pHead = cur;
}
@指定结点位置插入新元素:

1.链表为空的情况下不操作;2.链表只有一个结点并且在该结点位置前插入;3.链表有多个结点并找到指定位置插入


void Insert(pLinkList pList,pLinkNode pos,DataType x)	//指定结点位置插入
{
	pLinkNode cur = NULL;
	pLinkNode prev = NULL;
	pLinkNode newnode =	NULL;
	assert(pList);
	newnode = BuyNode(x);
	//无结点时
	if(NULL == pList->pHead)
	{
		pList->pHead = newnode;
		newnode->next = NULL;
		return ;
	}
	//有一个结点并且在该结点前插入
	if(pList->pHead == pos)
	{
		PushFront(pList,x);
		return ;
	}
	//有一个以上结点
	cur = pList->pHead;
	while(cur != pos)
	{
		prev = cur;
		cur = cur->next;
	}
	prev->next = newnode;
	newnode->next = cur;
}
@删除一个指定元素x:

1.空链表的情况下不操作;2.有一个结点时:判断该节点是不是要删除的元素;3.有多个结点时:查找要删除的元素,然后删除



void Remove(pLinkList pList,DataType x)	//删除一个X元素
{
	pLinkNode cur = NULL;
	pLinkNode prev = NULL;
	pLinkNode del = NULL;
	assert(pList);
	cur = pList->pHead;
	prev = pList->pHead;
	del = Find(pList,x);
	//无结点时
	if(NULL == pList->pHead)
	{
		printf("LinkList is empty!\n");
		return ;
	}
	//只有一个结点时
	if(NULL == cur->next)
	{
		if(cur->data == x)//该结点元素就是要删除的元素
		{
			free(cur);
			cur = NULL;
			pList->pHead = NULL;
			return ;
		}
	}
	//有多个结点时
	else
	{
		while(cur)
		{
			if(cur->data == x)		//第一个结点就是要删除的元素
			{
				del = cur;
				pList->pHead = cur->next;
				free(del);
				del = NULL;
				return ;
			}
			prev = cur;
			cur = cur->next;		//第二个结点开始,里边有需要删除的元素
			while(cur)
			{
				
				if(cur->data == x)
				{
					prev->next = cur->next;
					free(cur);
					cur = NULL;
					return ;
				}
				prev = cur;
				cur = cur->next;
			}
		}
	}
}

@删除所有指定元素x:

1.链表为空时不操作;2.有一个结点时:判断该结点是不是要删除的元素x;3.有多个结点时:首先判断第一个结点是不是要删除的元素x,如果是,删除并继续向后寻找,直到遍历完整个链表;如果不是,就从第二个结点开始遍历


void RemoveAll(pLinkList pList,DataType x)	//删除所有X元素
{
	pLinkNode prev = NULL;
	pLinkNode cur = NULL;
	assert(pList);
	//空链表
	if(NULL == pList->pHead)
	{
		printf("LinkList is empty!\n");
		return ;
	}
	cur = pList->pHead;
	//链表有一个结点
	if(NULL == cur->next)
	{
		if(cur->data == x)//并且该结点元素就是要删除的元素
		{
			free(cur);
			cur = NULL;
			pList->pHead = NULL;
			return ;
		}
	}
	//链表有多个结点
	cur = cur->next;
	prev = pList->pHead;
	while(cur)
	{
		if(prev->data == x)//第一个结点是要删除的元素x
		{
			pList->pHead = prev->next;
			free(prev);
			prev = NULL;
		}
		if(cur->data == x)//要删除的元素存在于第一个结点之后
		{
			prev->next = cur->next;
			free(cur);
			cur = NULL;
			cur = prev;
		}
		prev = cur;
		cur = cur->next;
	}
}
@删除指定位置的结点:

1.空链表时不操作;2.有一个结点时:判断该节点是不是要删除的结点pos;3.有多个结点时:判断第一个结点是不是要删除的结点,如果是,就将第一个结点删除并直接返回;如果不是,应继续遍历此链表知道找到要删除的结点


void Erase(pLinkList pList,pLinkNode pos)	//删除指定位置的结点
{
	pLinkNode cur = NULL;
	pLinkNode prev = NULL;
	assert(pList);
	//空链表
	if(NULL == pList->pHead)
	{
		printf("LinkList is empty!\n");
		return ;
	}
	cur = pList->pHead;
	//一个节点
	if(NULL == cur->next)
	{
		if(cur == pos)//判断这个结点是不是要删除的结点
		{
			free(cur);
			cur = NULL;
			pList->pHead = NULL;
		}
		return ;
	}
	//第一个结点就是要删除的结点
	if(pos == cur)
	{
		free(cur);
		cur = NULL;
		pList->pHead = NULL;
	}
	//链表有多个结点
	cur = cur->next;
	prev = pList->pHead;
	while(cur)
	{
		if(cur == pos)
		{
			prev->next = cur->next;
			free(cur);
			return ;
		}
		prev = cur;
		cur = cur->next;
	}
}
@排序(此处用冒泡排序):

1.链表为空或者链表只有一个结点时:不需要排序;

2.排序时应定义一个尾指针来控制循环的次数


void BubbleSort(pLinkList pList)	//冒泡排序
{
	pLinkNode tail = NULL;
	pLinkNode cur = NULL;
	assert(pList);
	if((pList->pHead == NULL)||(pList->pHead->next == NULL))
	{
		printf("LinkList do not need to sort!\n");
		return ;
	}
	cur = pList->pHead;
	while(cur != tail)
	{
		while(cur->next != tail)
		{
			if(cur->data < cur->next->data)
			{
				DataType tmp = cur->data;
				cur->data = cur->next->data;
				cur->next->data = tmp;
			}
			cur = cur->next;
		}
		tail = cur;
		cur = pList->pHead;
	}
}
由于在实现某些函数时要创建一个新结点或者寻找一个结点位置,因此这里可以写两个函数来实现。 以下是所有函数的实现:

LinkList.c

#include"LinkList.h"

void Init(pLinkList pList)	//初始化
{
	assert(pList);
	pList->pHead = NULL;
}
void Destory(pLinkList pList)	//销毁
{
	pLinkNode cur = NULL;
	pLinkNode del = NULL;
	assert(pList);
	cur = pList->pHead;
	if(NULL == pList->pHead)//空链表
		return ;
	while(cur)		//有一个或以上结点
	{
		del = cur;
		cur = cur->next;
		free(del);
		del = NULL;
	}
	pList->pHead = NULL;
}
void Print(pLinkList pList)	//输出
{
	pLinkNode cur = NULL;
	assert(pList);
	cur = pList->pHead;
	while(cur)
	{
		printf("%d->",cur->data);
		cur = cur->next;
	}
	printf("over!\n");
}
pLinkNode BuyNode(DataType x)//创建一个新结点
{
	pLinkNode NewNode = NULL;
	NewNode = (pLinkNode)malloc(sizeof(LinkNode));
	if(NULL == NewNode)
	{
		printf("out of memory!\n");
		exit(EXIT_FAILURE);
	}
	NewNode->data = x;
	return NewNode;
}
void PushBack(pLinkList pList,DataType x)	//尾插
{
	pLinkNode cur = NULL;
	pLinkNode newnode = NULL;
	assert(pList);
	cur = pList->pHead;
	newnode = BuyNode(x);
	//没有结点
	if(NULL == pList->pHead)
	{
		pList->pHead = newnode;
		newnode->next = NULL;
		return ;
	}
	//有一个或以上的结点
	while(cur->next)
	{
		cur = cur->next;
	}
	cur->next = newnode;
	newnode->next = NULL;
}
void PopBack(pLinkList pList)	//尾删
{
	pLinkNode cur = NULL;
	pLinkNode prev = NULL;
	assert(pList);
	//没有结点
	if(NULL == pList->pHead)
	{
		printf("LinList is empty!\n");
		return ;
	}
	//有结点
	cur = pList->pHead;
	while(cur->next)
	{
		 prev = cur;
		 cur = cur->next;
	}
	free(cur);
	cur = NULL;
	prev->next = NULL;
}
void PushFront(pLinkList pList,DataType x)	//头插
{
	pLinkNode newnode = NULL;
	pLinkNode cur = NULL;
	assert(pList);
	newnode = BuyNode(x);
	//没有结点
	if(NULL == pList->pHead)
	{
		pList->pHead = newnode;
		newnode->next = NULL;
		return ;
	}
	//有一个或以上结点
	cur = pList->pHead;
	pList->pHead = newnode;
	newnode->next = cur;
}
void PopFront(pLinkList pList)	//头删
{
	pLinkNode cur = NULL;
	pLinkNode del = NULL;
	assert(pList);
	//无节点
	if(NULL == pList->pHead)
	{
		printf("LinkList is empty!\n");
		return ;
	}
		return ;
	//有一个或以上结点
	cur = pList->pHead;
	del = cur;
	cur = cur->next;
	free(del);
	del = NULL;
	pList->pHead = cur;
}
pLinkNode Find(pLinkList pList,DataType x)	//公共查找函数
{
	pLinkNode cur = NULL;
	assert(pList);
	if(NULL == pList->pHead)
	{
		printf("LinkList is empty!\n");
		return pList->pHead;
	}
	cur = pList->pHead;
	while(cur)
	{
		if(cur->data == x)
			return cur;
		cur = cur->next;
	}
}
void Insert(pLinkList pList,pLinkNode pos,DataType x)	//指定结点位置插入
{
	pLinkNode cur = NULL;
	pLinkNode prev = NULL;
	pLinkNode newnode =	NULL;
	assert(pList);
	newnode = BuyNode(x);
	//无结点时
	if(NULL == pList->pHead)
	{
		pList->pHead = newnode;
		newnode->next = NULL;
		return ;
	}
	//有一个结点并且在该结点前插入
	if(pList->pHead == pos)
	{
		PushFront(pList,x);
		return ;
	}
	//有一个以上结点
	cur = pList->pHead;
	while(cur != pos)
	{
		prev = cur;
		cur = cur->next;
	}
	prev->next = newnode;
	newnode->next = cur;
}
void Remove(pLinkList pList,DataType x)	//删除一个X元素
{
	pLinkNode cur = NULL;
	pLinkNode prev = NULL;
	pLinkNode del = NULL;
	assert(pList);
	cur = pList->pHead;
	prev = pList->pHead;
	del = Find(pList,x);
	//无结点时
	if(NULL == pList->pHead)
	{
		printf("LinkList is empty!\n");
		return ;
	}
	//只有一个结点时
	if(NULL == cur->next)
	{
		if(cur->data == x)//该结点元素就是要删除的元素
		{
			free(cur);
			cur = NULL;
			pList->pHead = NULL;
			return ;
		}
	}
	//有多个结点时
	else
	{
		while(cur)
		{
			if(cur->data == x)		//第一个结点就是要删除的元素
			{
				del = cur;
				pList->pHead = cur->next;
				free(del);
				del = NULL;
				return ;
			}
			prev = cur;
			cur = cur->next;		//第二个结点开始,里边有需要删除的元素
			while(cur)
			{
				
				if(cur->data == x)
				{
					prev->next = cur->next;
					free(cur);
					cur = NULL;
					return ;
				}
				prev = cur;
				cur = cur->next;
			}
		}
	}
}
void RemoveAll(pLinkList pList,DataType x)	//删除所有X元素
{
	pLinkNode prev = NULL;
	pLinkNode cur = NULL;
	assert(pList);
	//空链表
	if(NULL == pList->pHead)
	{
		printf("LinkList is empty!\n");
		return ;
	}
	cur = pList->pHead;
	//链表有一个结点
	if(NULL == cur->next)
	{
		if(cur->data == x)//并且该结点元素就是要删除的元素
		{
			free(cur);
			cur = NULL;
			pList->pHead = NULL;
			return ;
		}
	}
	//链表有多个结点
	cur = cur->next;
	prev = pList->pHead;
	while(cur)
	{
		if(prev->data == x)//第一个结点是要删除的元素x
		{
			pList->pHead = prev->next;
			free(prev);
			prev = NULL;
		}
		if(cur->data == x)//要删除的元素存在于第一个结点之后
		{
			prev->next = cur->next;
			free(cur);
			cur = NULL;
			cur = prev;
		}
		prev = cur;
		cur = cur->next;
	}
}
void Erase(pLinkList pList,pLinkNode pos)	//删除指定位置的结点
{
	pLinkNode cur = NULL;
	pLinkNode prev = NULL;
	assert(pList);
	//空链表
	if(NULL == pList->pHead)
	{
		printf("LinkList is empty!\n");
		return ;
	}
	cur = pList->pHead;
	//一个节点
	if(NULL == cur->next)
	{
		if(cur == pos)//判断这个结点是不是要删除的结点
		{
			free(cur);
			cur = NULL;
			pList->pHead = NULL;
		}
		return ;
	}
	//第一个结点就是要删除的结点
	if(pos == cur)
	{
		free(cur);
		cur = NULL;
		pList->pHead = NULL;
	}
	//链表有多个结点
	cur = cur->next;
	prev = pList->pHead;
	while(cur)
	{
		if(cur == pos)
		{
			prev->next = cur->next;
			free(cur);
			return ;
		}
		prev = cur;
		cur = cur->next;
	}
}
void BubbleSort(pLinkList pList)	//冒泡排序
{
	pLinkNode tail = NULL;
	pLinkNode cur = NULL;
	assert(pList);
	if((pList->pHead == NULL)||(pList->pHead->next == NULL))
	{
		printf("LinkList do not need to sort!\n");
		return ;
	}
	cur = pList->pHead;
	while(cur != tail)
	{
		while(cur->next != tail)
		{
			if(cur->data < cur->next->data)
			{
				DataType tmp = cur->data;
				cur->data = cur->next->data;
				cur->next->data = tmp;
			}
			cur = cur->next;
		}
		tail = cur;
		cur = pList->pHead;
	}
}

test.c

#define _CRT_SECURE_NO_WARNINGS
#include"LinkList.h"

void menu()
{
	printf("***********************************\n");
	printf("******** 0.结束    1.输出 *********\n");
	printf("******** 2.尾插    3.尾删 *********\n");
	printf("******** 4.头插    5.头删 *********\n");
	printf("******** 6.删除x   7.删除所有x ****\n");
	printf("******** 8.插入指定元素 ***********\n");
	printf("******** 9.删除指定结点 ***********\n");
	printf("******** 10.排序         ***********\n");
}
int main()
{
	LinkList mylist;
	int input = 1;
	DataType data = 0;
	DataType p = NULL;
	pLinkNode pos = NULL;
	Init(&mylist);
	while(1)
	{
		menu();
		printf("请输入选项:");
		scanf("%d",&input);
		printf("\n");
		switch(input)
		{
		case 0:
			exit(0);
			break;
		case 1:
			Print(&mylist);
			break;
		case 2:
			printf("请输入插入的数:");
			scanf("%d",&data);
			PushBack(&mylist,data);
			break;
		case 3:
			PopBack(&mylist);
			break;
		case 4:
			printf("请输入插入的数:");
			scanf("%d",&data);
			PushFront(&mylist,data);
			break;
		case 5:
			PopFront(&mylist);
			break;
		case 6:
			printf("输入要删除的数:");
			scanf("%d",&data);
			Remove(&mylist,data);
			break;
		case 7:
			printf("输入要删除的数:");
			scanf("%d",&data);
			RemoveAll(&mylist,data);
			break;
		case 8:
			printf("请输入要在哪一个位置前插入:");
			scanf("%d",&p);
			printf("请输入要插入的数:");
			scanf("%d",&data);
			pos = Find(&mylist,p);
			Insert(&mylist,pos,data);
			break;
		case 9:
			printf("输入要删除某个位置的结点:");
			scanf("%d",&data);
			pos = Find(&mylist,data);
			Erase(&mylist,pos);
			break;
		case 10:
			BubbleSort(&mylist);
			break;
		default:
			printf("无效选择!\n");
			break;
		}
	}
	Destory(&mylist);
	system("pause");
	return 0;
}





本文转载:CSDN博客