数据结构——单链表

为什么我们要引入无头单链表?

还记得我们顺序表吗?

顺序表的插入和删出的时间复杂度都是O(n)

我们要把他的时间复杂度缩短,就引入单链表 

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。它的数据是以结点(类型一般为结构体)来表示的,每个结点的构成:数据(类型为要存储的数据的类型) + 指针(结构体指针),数据就是链表里具体要存储的东西,指针就是用来把每个节点都连接起来,使它们形成一个链状。

单链表也分为2种:

1.无头单链表

2.有头单链表

有头结点的链表相对于无头结点的链表来说,主要体现在链表结点的增减上,如果没有头结点,链表的第一个结点的增减操作要和其他结点分开独立出来,而有了头结点后,链表的第一个结点的增删操作可以和后续的节点合并的一起,同理对于尾结点。在部分的访问判断操作链表第一个结点位置的特殊性也造成了增加头结点后程序的简明性(不用将第一个结点单独提出来操作处理)!

这里我们只看无头单链表的结构,会了这个由头也自然会了

在这里给大家展示增删改查

typedef struct Node
{
	struct Node* next;
	DataType data;
}*NODE,Node;

此结构体的next指向下一个存储单元的地址

data存储元素

首先我们来看看尾插(时间复杂度O(n))


void SListPushBack(NODE *pHead, DataType data)
{
	NODE PNEW = NULL;
	PNEW = BuySListNode(data);//申请新节点
	assert(pHead);
	//空
	if (NULL == (*pHead))
	{
		*pHead=PNEW;
	}//非空
	else
	{
		NODE p = *pHead;
		while (p->next)
			p = p->next;
		p->next = PNEW;
	}

}

头插(时间复杂度O(1))

void SListPushFront(NODE *pHead, DataType data)
{
	assert(pHead);
	NODE PNEW = NULL;
	PNEW= BuySListNode(data);
	if (PNEW == NULL)
	{
		return;
	}
	PNEW->next = *pHead;
	*pHead= PNEW;
	
}

尾删(时间复杂度O(n))

void  SListPopBack(NODE *pHead)
{
	assert(pHead);
	NODE L = *pHead;
	if (L == NULL)
	{
		return ;
	}
	while (L->next->next != NULL)
	{
		L = L->next;
	}
	L->next = NULL;
	free(L->next);
}

头删(时间复杂度O(1))

void SListPopFront(NODE *pHead)
{
	NODE pDel = NULL;
	assert(pHead);
	//空
	if (NULL==(*pHead))
		return;
	pDel = *pHead;
	*pHead = pDel->next;
	//free(pDel);
}

查找(时间复杂度O(n))

// 查找值为data的结点,返回该结点在链表中的位置 
NODE SListFind(NODE *pHead, DataType data)
{
	assert(pHead);
	NODE L = *pHead;
	while (L != NULL)
	{
		
		if (L->data == data)
		{
			return L;
		}
		L = L->next;
	}
	return NULL;
}

我们来看看代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int DataType;
typedef struct Node
{
	struct Node* next;
	DataType data;
}*NODE,Node;
//创建链表
void SListInit(NODE *pHead)
{
	//DE *pHead = (NODE)malloc(sizeof(NODE));
	assert(pHead);
	*pHead= NULL;
}
NODE deletenode(NODE pHead)
{
	int i = 0;
	int n = 0;
	int data1;
	NODE p;
	p = pHead;
	scanf("%d", &n);
	NODE s;
	for (i = 0; i < n; i++)
	{
		s = (NODE)malloc(sizeof(int));
		scanf("%d", &data1);
		s->data = data1;
		p->next = s;
		p = s;
	}
	p->next = NULL;
	return pHead;
}
NODE BuySListNode(DataType data)
{
	NODE PNEW = (NODE)malloc(sizeof(NODE));
	if (NULL == PNEW)
	{
		return NULL;
	}
	PNEW->data = data;
	PNEW->next = NULL;
	return PNEW;
}
// 尾插
void SListPushBack(NODE *pHead, DataType data)
{
	NODE PNEW = NULL;
	PNEW = BuySListNode(data);
	assert(pHead);
	//空
	if (NULL == (*pHead))
	{
		*pHead=PNEW;
	}//非空
	else
	{
		NODE p = *pHead;
		while (p->next)
			p = p->next;
		p->next = PNEW;
	}

}
// 尾删 
void  SListPopBack(NODE *pHead)
{
	assert(pHead);
	NODE L = *pHead;
	if (L == NULL)
	{
		return ;
	}
	while (L->next->next != NULL)
	{
		L = L->next;
	}
	L->next = NULL;
	free(L->next);
}
// 头插 
void SListPushFront(NODE *pHead, DataType data)
{
	assert(pHead);
	NODE PNEW = NULL;
	PNEW= BuySListNode(data);
	if (PNEW == NULL)
	{
		return;
	}
	PNEW->next = *pHead;
	*pHead= PNEW;
	
}
//头删 
void SListPopFront(NODE *pHead)
{
	NODE pDel = NULL;
	assert(pHead);
	//空
	if (NULL==(*pHead))
		return;
	pDel = *pHead;
	*pHead = pDel->next;
	//free(pDel);
}
// 查找值为data的结点,返回该结点在链表中的位置 
NODE SListFind(NODE *pHead, DataType data)
{
	assert(pHead);
	NODE L = *pHead;
	while (L != NULL)
	{
		
		if (L->data == data)
		{
			return L;
		}
		L = L->next;
	}
	return NULL;
}
// 在链表pos位置后插入结点data 
NODE SListInsert(NODE pHead, NODE pos, DataType data)
{
	assert(pHead);
	NODE L = pHead;
	NODE s = (NODE)malloc(sizeof(NODE));
	if (s == NULL)
	{
		printf("申请内存失败!!!!!\n");
	}
	s->data = data;
	s->next= pos->next;
	pos->next = s;
	return pHead;
}
// 删除链表pos位置上的结点 ????
NODE SListErase(NODE pHead, NODE pos)
{
	assert(pos);
	NODE L = pHead;
	if (pHead == NULL)
	{
		return NULL;
	}
	while(L->next != pos)
	{
		L = L->next;
	}
	L->next = pos->next;
	free(pos);
	return pHead;
}
// 销毁单链表 
void  SListDestroy(NODE pHead)
{
	assert(pHead);
	NODE L = NULL;
	if (pHead == NULL)
	{
		return ;
	}
	while (pHead != NULL)
	{
		L = pHead->next;
		free(pHead);
		pHead = L;
	}
	return ;
}
 
// 求链表中结点的个数 
int SListSize(NODE pHead)
{
	assert(pHead);
	NODE L = pHead->next;
	int count = 0;
	if (pHead == NULL)
	{
		return 0;
	}
	while (L != NULL)
	{
		L = L->next;
		count++;
	}
	return count;
}

// 将链表中的结点清空 
void SListClear(NODE pHead)
{
	assert(pHead);
	NODE L = pHead;
	NODE tmp = NULL;
	if (pHead == NULL)
	{
		return ;
	}
	while (L->next != NULL)
	{
		tmp = L->next;
		free(L);
		L = tmp;
	}
	if (L->next == NULL)
	{
		free(L->next);
		L = NULL;
	}
}


// 获取链表中的最后一个结点,返回该结点的地址 
NODE SListBack(NODE pHead)
{
	assert(pHead);
	NODE L = pHead;
	if (L = NULL)
	{
		return NULL;
	}
	while(L->next)
	{
		L = L->next;
	}
	return L;
}
///打印链表
void PrintSList(NODE pHead)
{
	NODE L =pHead;
	while (L!= NULL)
	{
		printf("%d--->", L->data);
		L = L->next;
	}
	printf("NULL");
	printf("\n");
}
void test1()
{
	NODE pHead;
	SListInit(&pHead);
	SListPushFront(&pHead, 1);
	SListPushFront(&pHead, 2);
	SListPushFront(&pHead, 3);
	SListPushFront(&pHead, 4);
	SListPushFront(&pHead, 5);
	PrintSList(pHead);
	//SListFind(NODE *pHead, DataType data);
	//SListPopFront(&pHead);
	PrintSList(pHead);
	
}

int main()
{
	test1();
	system("pause");
	return 0;
}


猜你喜欢

转载自blog.csdn.net/champion_man/article/details/80706759