由单链表向后续链表的延伸

在正式讲解链表的拓展问题时,我再谈谈我对链表框架的看法。
链表的组成成员是结点,但是只有结点是不行的,还需要有链表的框架。这就需要一个函数来初始化链表,想要敲出一个函数并不是太难,但是想要你的函数在整个程序中正常运行往往还缺很多,主要原因还是缺乏对于框架性知识的理解,所以在写链表的时候,首先是定义结点,然后要购买结点,然后初始化链表,最后将结点插入完成链表。

  1. 单项循环链表
    单项循环链表和单链表相差不大,只不过是将尾指针的后继指向了头,区别在于链表初始化的时候修改last指针的指向,last的后继指针不再指向NULL,而是指向头结点的位置,注意就是在创建时用的头插法和尾插法最后需要修改last指针的指向。在显示函数的时候不再是遇到空访问停止,而是遇到头结点访问停止。
    来看一下主要创建链表的核心代码
void ListInit(SLIST* psl)
{
	Listnode* S = _Buynode(0);
	psl->first = psl->last = S;
	psl->last->next = psl->first;
	psl->size = 0;
}
bool ListPushback(SLIST* psl,int y)
{
	Listnode* s = _Buynode(y);
	if (s == NULL)
		return false;
	psl->last->next = s;
	psl->last = s; 
	psl->size++;
	psl->last->next = psl->first;
	return true;
}
bool ListPushFront(SLIST* psl, int y)
{
	Listnode* s = _Buynode(y);
	if (s == NULL)
	return false;
	if (psl->size == 0)
	{
		psl->last->next = s;
		psl->last = s;
	}
	else
	{
		s->next = psl->first->next;
		psl->first->next = s;

	}
	psl->size++;
	psl->last->next = psl->first;
	return true;
}

显示函数

void ListShow(SLIST* psl)
{

	Listnode* p;
	p = psl->first->next;
	while (p != psl->first)
	{
		printf("%d  ", p->data);
		p = p->next;
	}
}
  1. 双向链表:
    双向链表和单链表差别也不大,双链表相比较单链表而言在指针域多了指向前驱结点的指针,这就造成了双链表进行增删查改等的基础操作上有了很大的该变,同时又方便了很多。因为双向链表的时候有了前驱指针这条链,就不容易造成链表的断链。来看下面代码。
    首先是创建节点,这个节点会多一个prew指针来记录结点的前驱。
typedef struct DListnode
{
	int data;
	struct DListnode* next;
	struct DListnode* prew;
}DListnode;//创建一个节点

接下来就是这个链表的怎么来创建
还是和单链表一样有一个记录头的指针和一个记录尾的指针,还有一个记录链表长度的无符号整型变量。
在初始化化链表的时候首先指向链表的2个指针指向头,而且头的地址为空。
基本上创建完成后就是完成这个双链表的各项功能,基本上掌握了单链表其他链表基本上就能掌握了,因为这里面的区别不大。
当然我们需要一种更高级的形式展现链表,不能像之前那样用啥将函数写出来调用,我们需要做个菜单。来看代码

while (1)
	{
		printf("*****************************************************\n");
		printf("*****[1]PushBank          [2]PushFront***************\n");
		printf("*****[3]PopBank	          [4]PopFront****************\n");
		printf("*****[5]ListShow          [6]FindBuyVal**************\n");
		printf("*****[7]DeleteBuyVal      [8]ReplaceByVal************\n");
		printf("*****[9]DListReverse	  [10]DListBreak*************\n");
		printf("*****************************************************\n");
		printf("*****************************************************\n");
		printf("请选择->");
		scanf("%d", &select);
		if (select == 0)
			break;
			switch (select)

在菜单中完成想要的操作

  1. 双向循环链表
    接下来我们来看双向循环链表。在生活中我们遇到最多的就是单链表和双向循环链表。我们来看一下双向循环链表的基本操作应该怎么完成。仿照单链表变成单循环链表,我们不难发现,双向链表变成双向循环链表实质上就是更改了尾指针。尾指针不在指向空,尾指针指向了头。在操作中的差异和双链表的区别不大。

a. 首先是链表初始化

bool DListNodeInit(SLIST* psl)
{
	DListnode* s = _BuyDNode(0);
	if (s == NULL)
		return false;
	psl->last = psl->first =  s;
	psl->last->next = psl->first;
	psl->first->prew = psl->last;
	psl->size = 0;
	return true;
}

b. 链表的头尾插

bool DListPushback(SLIST *psl, int x)
{
	DListnode* S = _BuyDNode(x);
	if (S == NULL)
	{
		return false;
	}
	psl->last->next = S;
	S->prew = psl->last;
	psl->last = S;
	psl->last->next = psl->first;
	psl->first->prew = psl->last;
	psl->size++;
	return true;
}
bool DListPushFront(SLIST* psl, int x)
{
	DListnode* P = _BuyDNode(x);
	if (P == NULL)
		return false;
	if (psl->size == 0)
	{
		psl->last->next = P;
		P->prew = psl->first;
		psl->last = P;
		psl->last->next = psl->first;
		psl->first->prew = psl->last;
		psl->size++;
	}
	else
	{
		P->next = psl->first->next;
		psl->first->next = P;
		psl->size++;
	}
	return true;
}

c. 链表的显示

void ShowDlist(SLIST* psl)
{
	if (psl->size > 0)
	{
		DListnode* P = psl->first->next;
		while (P != psl->first)
		{
			printf("%d", P->data);
			printf("->");
			P = P->next;
		}
	}
}

剩下操作和单链表差异不大,总之想掌握好链表还是需要下和很多功夫,链表的实际操作来说并不算难,但是却很容易出错,希望大家和我一起在不断练习当中慢慢掌握好它,整整做到学以致用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值