【C语言】单链表

    程序实现了单链表的基本操作,包括创建,初始化,销毁,头插,头删,尾插,尾删,打印单链表,查找指定数据的位置,指定位置插入指定数据,删除指定数据,删除链表里出现的所有指定数据,指定位置删除,单链表的冒泡排序。博主现阶段还是技术小白,此初步调试完成,读者如果发现新的bug,还请不吝赐教!

    先介绍一下单链表的概念:

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。

    链表中的数据是以结点来表示的,每个结点的构成:元素( 数据) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元指针就是连接每个结点的地址数据。

以“结点的序列”表示线性表称作 线性链表(单链表)

单链表是链式存取的结构,为找第 i 个 数据元素,必须先找到第 i-1 个数据元素。而且单链表只能从前往后遍历。

接下来分享一下我的实现:

头文件部分:

#define _CRT_SECURE_NO_WARNINGS 1
#ifndef _LINKLIST_H__
#define _LINKLIST_H__

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

typedef int DataType;
typedef struct LinkNode
{
	DataType data;
	struct LinkNode *next;
}LinkNode,*pLinkNode;

typedef struct LinkList
{
	LinkNode *pHead;
}LinkList,*pLinkList;

void InitLinkList(pLinkList pList);  //初始化单链表
void DestroyList(pLinkList pList);   //销毁单链表
void PushBack(pLinkList pList, DataType x);  //尾插
void PopBack(pLinkList pList);        //尾删
void PushFront(pLinkList pList, DataType x);   //头插
void PopFront(pLinkList pList);          //头删
void PrintList(pLinkList pList);         //打印单链表
pLinkNode Find(pLinkList pList, DataType x);   //查找指定元素的地址
void Insert(pLinkList pList, pLinkNode pos, DataType x);// 指定位置插入指定数据
void Remove(pLinkList pList, DataType x);//删除指定数据
void RemoveAll(pLinkList pList, DataType x);//删除链表里出现的所有指定数据
void Erase(pLinkList pList, pLinkNode pos);  //指定位置删除
void BubbleSort(pLinkList pList);   //单链表的冒泡排序

#endif //_LINKLIST_H__
函数实现:

#include"linklist.h"

void InitLinkList(pLinkList pList)
{
	assert(pList);
	pList->pHead = NULL;
}
void DestroyList(pLinkList pList)
{
	assert(pList);
	pLinkNode cur;
	cur = pList->pHead;
	while (cur)
	{
		pLinkNode del = cur;
		cur = cur->next;
		free(del);
		del = NULL;
	}
	pList->pHead = NULL;
}

pLinkNode BuyNewNode(DataType x)   //创建一个新结点并返回
{
	pLinkNode NewNode = NULL;
	NewNode = (pLinkNode)malloc(sizeof(LinkNode));
	if (NewNode == NULL)
	{
		printf("out of memory\n");
		exit(EXIT_FAILURE);
	}
	NewNode->data = x;
	NewNode->next = NULL;
	return NewNode;
}

void PushBack(pLinkList pList, DataType x)
{
	assert(pList);
	pLinkNode cur=NULL;
	pLinkNode NewNode=BuyNewNode(x);
	cur = pList->pHead;
	if (cur == NULL)   //若为空链表直接将新结点设置为头结点
	{
		pList->pHead = NewNode;
	}
	else
	{
		while ((cur->next) != NULL)    //找到链表的最后一个位置
		{
			cur = cur->next;
		}
		cur->next = NewNode;
	}
}

void PopBack(pLinkList pList)
{
	assert(pList);
	pLinkNode cur = pList->pHead;
	pLinkNode fcur = NULL;
	if (cur == NULL)
	{
		printf("空表\n");
		return;
	}
	else if (cur->next == NULL)   //只有一个结点的情况
	{
		free(pList->pHead);
		pList->pHead = NULL;
	}
	else                 //拥有两个以上的结点
	{
		while (cur->next != NULL)
		{
			fcur = cur;
			cur = cur->next;
		}
		fcur->next = NULL;
	}
}
void PushFront(pLinkList pList, DataType x)
{
	assert(pList);
	pLinkNode NewNode = BuyNewNode(x);
	if (pList->pHead == NULL)     //空表的情况
	{
		pList->pHead = NewNode;
	}
	else
	{
		NewNode->next = pList->pHead;
		pList->pHead = NewNode;
	}
}

void PopFront(pLinkList pList)
{
	assert(pList);
	if (pList->pHead == NULL)   //空表
	{
		return;
	}
	else         //非空
	{
		pList->pHead = pList->pHead->next;
	}
}
void PrintList(pLinkList pList)
{
	assert(pList);
	pLinkNode cur;
	cur = pList->pHead;
	while (cur)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL");
	printf("\n");
}

pLinkNode Find(pLinkList pList, DataType x)
{
	assert(pList);
	pLinkNode cur = pList->pHead;
	while (cur && (cur->data != x))// 当前结点不为指定数据则指针向后移动
	{
		cur = cur->next;
	}

	return cur;
}

void Insert(pLinkList pList, pLinkNode pos, DataType x)
{
	assert(pList);
	pLinkNode cur = pList->pHead;
	pLinkNode fcur = NULL;
	pLinkNode NewNode = BuyNewNode(x);
	if (pos == pList->pHead)  //若指定位置为头结点
	{
		NewNode->next = pList->pHead;
		pList->pHead = NewNode;
	}
	else
	{
		while (cur && (cur != pos))
		{
			fcur = cur;
			cur = cur->next;
		}
		NewNode->next = cur;
		fcur->next = NewNode;
	}
}

void Remove(pLinkList pList, DataType x)
{
	assert(pList);
	pLinkNode cur = pList->pHead;
	pLinkNode fcur = NULL;
	if (cur->data == x)      //若指定数据为头结点包含的数据
	{
		pList->pHead = pList->pHead->next;
	}
	else
	{
		while (cur&&(cur->data!=x))  //找到指定数据
		{
			fcur = cur;
			cur = cur->next;
		}
		if (cur == NULL)  //若遍历整个链表后没有找到
		{
			printf("链表中无该数据\n");
		}
		else   //找到了删除
		{
			fcur->next = cur->next;
			free(cur);
			cur = NULL;
		}
	}
}

void RemoveAll(pLinkList pList, DataType x)
{
	assert(pList);
	pLinkNode cur = pList->pHead;
	pLinkNode fcur = NULL;
	pLinkNode del = NULL;
	if (cur == NULL)      //空表
	{
		return;
	}
	if ((cur->data == x)&&(cur->next == NULL))  //表中只有一个结点。
	{
		free(cur);
		cur = NULL;
	}
	else if (cur->data == x)     //若要删除的数据是头结点
	{
		PopFront(pList);
	}
		while (cur &&(cur->next))  //循环找到所有指定的数据删除
		{
			if(cur->next->data == x)
			{
				del = cur->next;
				cur->next = del->next;
				free(del);
				del = NULL;
			}
			cur = cur->next;
		}
}

void Erase(pLinkList pList, pLinkNode pos)
{
	assert(pList);
	pLinkNode cur = pList->pHead;
	pLinkNode fcur = NULL;
	if (pos == pList->pHead)  //若指定位置是头结点的位置,调用头删函数
	{
		PopFront(pList);
	}
	else
	{
		while (cur)
		{
			while (cur != pos)  //循环找到指定位置
			{
				fcur = cur;
				cur = cur->next;
			}
			if (cur == NULL)
			{
				printf("无数据存放在该位置\n");
				return;
			}
			else
			{
				fcur->next = cur->next;
				free(cur);
				cur = NULL;
			}
		}
	}
}
void BubbleSort(pLinkList pList)
{
	assert(pList);
	pLinkNode cur = pList->pHead;
	pLinkNode inCur = pList->pHead;
	pLinkNode checkNode = NULL;
	DataType  tmp = 0;
	int   count = 0;  //用来优化冒泡排序
	while (cur->next)
	{
		while (inCur->next != checkNode)
		{
			if (inCur->data > inCur->next->data)
			{
				tmp = inCur->data;
				inCur->data = inCur->next->data;
				inCur->next->data = tmp;
				count++;
			}
			inCur = inCur->next;
		}

		if (count == 0)
		{
			return;
		}
		checkNode = inCur;//j<size-1-i;
		inCur = pList->pHead;
		cur = cur->next;
	}
}
主函数部分(主要用来测试):

#include"linklist.h"

test1()
{
	LinkList list;
	InitLinkList(&list);
	PushBack(&list, 1);
	PushBack(&list, 2);
	PushBack(&list, 3);
	PopBack(&list);
	PopBack(&list);
	PrintList(&list);//测试尾插和尾删,应该输出1->NULL;
	DestroyList(&list);
}
test2()
{
	LinkList list;
	pLinkNode ret = NULL;
	InitLinkList(&list);
	PushFront(&list, 1);
	PushFront(&list, 2);
	PushFront(&list, 3);
	PopFront(&list);
	PrintList(&list);  //测试头插和头删,应该输出2->1->NULL
	ret = Find(&list, 1);
	if (ret == NULL)
	{
		printf("链表中不存在该数据");
	}
	Remove(&list, 1);    
	PrintList(&list);//测试删除指定数据函数,应该输出2->NULL
	DestroyList(&list);
}

test3()
{
	LinkList list;
	InitLinkList(&list);
	PushBack(&list, 1);
	PushBack(&list, 2);
	PushBack(&list, 3);
	PushBack(&list, 1);
	PushBack(&list, 2);
	PrintList(&list);
	RemoveAll(&list, 1); //测试指定链表中存在的所有某个数据,调用后应输出2->3->2->NULL
	PrintList(&list);
	DestroyList(&list);
}
test4()
{
	LinkList list;
	pLinkNode ret = NULL;
	InitLinkList(&list);
	PushFront(&list, 1);
	PushFront(&list, 5);
	PushFront(&list, 3);
	PushFront(&list, 7);
	PushFront(&list, 9);
	PushFront(&list, 0);
	PrintList(&list);
	BubbleSort(&list);  //测试冒泡排序,输出一个无序,调用后输出有序
	PrintList(&list);
	DestroyList(&list);
}
test5()
{
	LinkList list;
	pLinkNode ret = NULL;
	InitLinkList(&list);
	PushFront(&list, 1);
	PushFront(&list, 2);
	PushFront(&list, 3);
	PrintList(&list);
	ret = Find(&list, 1);
	if (ret == NULL)
	{
		printf("链表中不存在该数据");
	}
	Insert(&list, ret, 3);   //测试指定位置插入指定数据,调用后输出3->2->3->1->NULL;
	PrintList(&list);
	DestroyList(&list);
}

test6()
{
	LinkList list;
	pLinkNode ret = NULL;
	InitLinkList(&list);
	PushBack(&list, 1);
	PushBack(&list, 2);
	PushBack(&list, 3);
	PrintList(&list);
	ret = Find(&list, 1);
	if (ret == NULL)
	{
		printf("链表中不存在该数据");
	}
	Erase(&list, ret); //测试指定位置删除,调用后应输出2->3->NULL
	PrintList(&list);
	DestroyList(&list);
}

int main()
{
	test1();
	test2();
	test3();
	test4();
	test5();
	test6();
	getchar();
	return 0;
}





  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值