数据结构之单链表基本功能的实现

         尽管顺序表有存储密度高,可以随机存取结点等优点,但是假如要对顺序表进行插入或删除等一些操作时,经常需要移动诸多结点,如果要频繁的进行插入删除等一些操作,效率十分低下,而且顺序表大小不好确定。这时,用单链表实现其功能就比较方便,而且效率也比较高了。

         单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素 +指针,元素就是存储数据的存储单元,指针就是连接每个结点的地址数据,即就是每一个对象里边都存有下一个对象的地址。

         由于单链表的这种特性,我们只需要定义一个头指针,用其进行维护,使其指向第一个元素的位置,我们便可 访问表中其他元素进行操作。示意图如下:


1.单链表的创建:

由于链表中的每一个对象至少包含一个数据域和一个指向下一个结点的指针。因此,我们可以用结构体来定义这个结点:

typedef struct Node
{
	DataType data;
	struct Node* next;
}Node,*pNode,*pList;

定义好之后,可创建一个具有指向下一结点的指针,即单链表创建完成。
 pNode plist ;


2.单链表的初始化:

由于单链表由一个头指针进行维护,所以进行初始化时,只需将头指针里存放的地址改为空即可:


3.给单链表里放入元素:

要在定义的单链表里插入元素(结点),必须先先在内存中申请一块空间来存放要插入的元素:


       (1.)尾插法:即从链表的末尾插入元素:


      (2.)头插法:即从链表的首部插入:


4.删除单链表的元素:

(1.)尾删(从链表末尾开始删,一次删除一个元素)



   (2.)头删(从链表首部开始删,一次删除一个元素)



5.遍历单链表:

6.单链表的逆置:

思路:依次断开单链表结点,将头指针逐次向后移动,每移动一次,将上次断开对象的的地址放入它的next中,直到为空。


源程序:

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

typedef int DataType;

typedef struct ListNode 
{
	DataType  _data;
	struct ListNode* _next;
}ListNode;

ListNode* BuyNode(DataType x)
{
	ListNode* node = (ListNode*)malloc(sizeof(ListNode));
	node->_data = x;
	node->_next = NULL;
	return node;
}
void PushBack(ListNode** ppList, DataType x)
{
	assert(ppList);
	ListNode* cur = *ppList;
	ListNode* node = BuyNode(x);
	if (*ppList == NULL)   //空链表
	{
		*ppList = node;
	}
	else
	{
		while (cur->_next)
		{
			cur = cur->_next;
		}
		cur->_next = node;
	}
}


void PopBack(ListNode** ppList) 
{
	assert(ppList);
	ListNode* cur = *ppList;
	ListNode* del = NULL;
	if ((*ppList) == NULL)
	{
		return;
	}
	else if (cur->_next == NULL)   //一个元素
	{
		free(cur);
		cur = NULL;
		return;
	}
	else //
	{
		while (cur->_next)
		{
			del = cur;
			cur = cur->_next;
		}
		free(del->_next);
		del->_next = NULL;
		return;
	}
}
void PushFront(ListNode** ppList, DataType x)
{
	ListNode* node = BuyNode(x);
	ListNode* cur = *ppList;
	ListNode* tmp = NULL;
	if (*ppList == NULL)
	{
		*ppList = node;
		return;
	}
	else    //一个或多个元素
	{
		tmp = *ppList;
		*ppList = node;
		node->_next = tmp;
	}
}

void PopFront(ListNode** ppList)
{
	assert(ppList);
	if (*ppList == NULL)
	{
		return;
	}
	else
	{
		ListNode* tmp = (*ppList)->_next;
		free(*ppList);
		*ppList = tmp;
	}
}


ListNode* Find(ListNode* pList, DataType x)
{
	ListNode* cur = pList;
	while (cur)
	{
		if (cur->_data == x)
		{
			return cur;
		}
		cur = cur->_next;
	}
	return NULL;
}

// 在pos的前面插入一个节点x 
void Insert(ListNode** ppList, ListNode* pos, DataType x)
{
	assert(ppList);
	ListNode* pre = NULL;
	ListNode* cur = *ppList;
	ListNode* tmp= NULL;

	if ((pos == NULL) || (*ppList == NULL))
	{
		PushBack(ppList, x);
	}

	if (*ppList == pos) //给第一个位置
	{
		PushFront(ppList, x);
	}
	else
	{
		while (cur)
		{
			if (cur->_next == pos)
			{
				pre = cur;
				break;
			}
			cur = cur->_next;
		}
		tmp = BuyNode(x);
		pre->_next = tmp;
		tmp->_next = pos;
	}

}
void Erase(ListNode** ppList, ListNode* pos)
{
	assert(ppList);
	ListNode* cur = *ppList;
	ListNode* pre = NULL;
	ListNode* next = NULL;
	if (pos == NULL)
	{
		return;
	}
	if (pos == cur)   //删除第一个位置
	{
		PopFront(ppList);
	}
	else
	{
		while (cur)
		{
			if (cur->_next == pos)
			{
				pre = cur;
				break;
			}
			cur = cur->_next;
		}
		next = pre->_next->_next;
		free(pre->_next);
		pre->_next = next;
	}
}
void PrintList(ListNode* pList)   //不需要改变链表内容,用一级指针
{
	if (pList == NULL)
	{
		printf("链表为空\n");
	}
	else
	{
		while (pList)
		{
			printf("%d ", pList->_data);
			pList = pList->_next;
		}
		printf("\n");
	}
}

void TestList()
{
	ListNode* a = NULL;
/*
	PrintList(a);

	PushBack(&a, 1);
	PushBack(&a, 2);
	PushBack(&a, 3);
	PushBack(&a, 4);
	PushBack(&a, 5);
	PushBack(&a, 6);
	PrintList(a);


	PopBack(&a);
	PrintList(a);

	PopBack(&a);
	PrintList(a);

	PopBack(&a);

	PrintList(a);*/

	PushFront(&a, 1);
	PushFront(&a, 2);
	PushFront(&a, 3);
	PushFront(&a, 4);
	PushFront(&a, 5);
	PushFront(&a, 6);
	Erase(&a, Find(a, 6));
	PrintList(a);

	Insert(&a, Find(a, 6), 10);

	Insert(&a, Find(a, 4), 10);
	Find(a, 3);
	PrintList(a);
	PopFront(&a);
	PopFront(&a);
	PopFront(&a);
	PopFront(&a);
	PopFront(&a);
	PopFront(&a);
	PopFront(&a);
	PopFront(&a);
	PrintList(a);


}









  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值