企业级数据结构之-顺序表的连式存储

线性表的链式存储

1、基本概念

链式存储定义

为了表示每个数据元素与其直接后继元素之间的逻辑关系,每个元素除了存储本身的信息外,还需要存储指示其直接后继的信息。

 


 

表头结点

链表中的第一个结点,包含指向第一个数据元素的指针以及链表自身的一些信息

数据结点

链表中代表数据元素的结点,包含指向下一个数据元素的指针和数据元素的信息

尾结点

链表中的最后一个数据结点,其下一元素指针为空,表示无后继。

 

2、设计与实现

C语言中可以用结构体来定义链表中的指针域,链表中的表头结点也可以用结构体实现



带头结点、位置从0的单链表
返回链表中第3个位置处,元素的值
LinkListNode* LinkList_Get(LinkList* list, int pos)
{ 
int  i = 0;
TLinkList *tList = (TLinkList *)list;
LinkListNode *current = NULL;
LinkListNode *ret = NULL;
 
if (list==NULL ||pos<0 || pos>=tList->length)
{
return NULL;
}
current = (LinkListNode *)tList;
for (i=0; i<pos; i++)
{
current = current->next;
}
ret = current->next;
return ret ;
}
 

返回第三个位置的

移动pos次以后,当前指针指向哪里?

答案:指向位置2,所以需要返回 ret = current->next;

 

备注:

循环遍历时, 遍历第1次,指向位置0

遍历第2次,指向位置1

遍历第3次,指向位置2

遍历第n次,指向位置n-1;

所以如果想返回位置n的元素的值,需要怎么做

  ret = current->next;

此问题是:指向头结点的指针移动n次 和 第n个元素之间的关系?

删除元素



 

3、优点和缺点

优点:

无需一次性定制链表的容量

插入和删除操作无需移动数据元素

缺点:

数据元素必须保存后继元素的位置信息

获取指定数据的元素操作需要顺序访问之前的元素





程序演示:(此程序实现算法与程序类型分离)

头文件 

#ifndef _zeng_
#define _zeng_
typedef void LinkList;
//注意该结构体地址等于&next地址
typedef struct xiaozeng
{
	struct xiaozeng*next;
}LinkListNode;//结点


//创建头结点
LinkList *LinkList_Create();
//销毁链表
void LinkList_Destroy(LinkList *list);
//链表清空
void LinkList_Clear(LinkList *list);
//获取链表长度
int LinkList_Length(LinkList *list);
//插入结点地址
void LinkList_Insert(LinkList *list, LinkListNode *node, int pos);
//得到结点地址
LinkListNode *LinkList_Get(LinkList *list, int pos);
//得到删除结点地址
LinkListNode *LinkList_Delete(LinkList *list, int pos);

#endif





实现.c

#include"1.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct _zzzz
{
	LinkListNode header;//指向下一个结点
	int length;//保存链表长度

}TLinkList;
//创建链表
LinkList *LinkList_Create()
{
	TLinkList *ret = (TLinkList*)malloc(sizeof(TLinkList));
	memset(ret, 0, sizeof(TLinkList));//初始化内存
	if (ret == NULL)
	{
		printf("创建头结点失败\n");
		return NULL;
	}
	ret->length = 0;//初始化为空
	ret->header.next = NULL;
	return ret;//返回头结点地址
}
//销毁结点
void LinkList_Destroy(LinkList *list)
{
	TLinkList *tmp = (TLinkList*)list;//类型转换
	if (tmp == NULL)
	{
		printf("链表为空\n");
		return;
	}
	free(tmp);//释放内存
}

//链表清空
void LinkList_Clear(LinkList *list)
{
	TLinkList *tmp = (TLinkList*)list;
	if (tmp == NULL)
	{
		printf("链表为空\n");
		return;
	}
	tmp->length = 0;//长度置0
	tmp->header.next = NULL;
	return;
}

//获取链表长度
int LinkList_Length(LinkList *list)
{
	TLinkList *tmp = (TLinkList*)list;
	if (tmp == NULL)
	{
		printf("链表为空\n");
		return -1;
	}
	return tmp->length;//返回长度
	  
}
//插入结点           //表头          //插入结点         //位置,从0号开始
void LinkList_Insert(LinkList *list, LinkListNode *node, int pos)
{
	TLinkList *tmp = (TLinkList*)list;
	//注意该结构体地址等于&next地址
	LinkListNode *current = &tmp->header.next;//指向头结点

	if (list == NULL || node == NULL || pos < 0)
	{
		printf("插入失败\n");
		return;
	}
	//容错性,使得不断为空
	if (pos>LinkList_Length(list))
	{
		pos = LinkList_Length(list);
	}
	
	for (int i = 0; i < pos && (current->next != NULL); i++)
	{
		current = current->next;
	}
	//现在current指向pos前一个结点
	node->next = current->next;   //先将前一个结点保存的地址赋值给node->next
	current->next = node;   //再将node地址赋给current->next;两步实现插入
	tmp->length++;  //插入后长度+1
	return;
}

//获得指定位置结点地址
LinkListNode *LinkList_Get(LinkList *list, int pos)
{
	TLinkList *tmp = (TLinkList*)list;
	LinkListNode *current = &tmp->header.next;//从头开始

	if (list == NULL ||  pos < 0||pos>=LinkList_Length(list))
	{
		printf("获取失败\n");
		return NULL;
	}
	for (int i = 0; i < pos && (current->next != NULL); i++)
	{
		current = current->next;
	}
	//现在current指向pos前一个结点
	return current->next;


}
//删除一个结点并返回该删除结点地址
LinkListNode *LinkList_Delete(LinkList *list, int pos)
{
	TLinkList *tmp = (TLinkList*)list;
	LinkListNode *current = &tmp->header.next;

	if (list == NULL || pos < 0 || pos >= LinkList_Length(list))
	{
		printf("删除失败\n");
		return NULL;
	}
	for (int i = 0; i < pos && (current->next != NULL); i++)
	{
		current = current->next;
	}
	LinkListNode *bao = current->next;//缓冲保存
	current->next = current->next->next;//删除该结点,就是把指向该结点变成指向该结点指向的结点
	tmp->length--;//长度-1
	return bao;//返回其结点
}



主函数

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include"1.h"
typedef struct Teacher    //即将被插入结点
{
	int data;//将被当做指针用,存储地址,只要是4个字节就OK,可以定义为LinkListnode Node//4个字节
	char name[4];
	int age;
}Teacher;
int main()
{
    Teacher t1, t2, t3;
	int length, i = 0;
	t1.age = 31;
	t2.age = 32;
	t3.age = 33;
	LinkList *list = LinkList_Create();
	                     //强制转换使得t1的4个字节当做指针用
	LinkList_Insert(list, (LinkListNode *)&t1, LinkList_Length(list));
	LinkList_Insert(list, (LinkListNode *)&t2, LinkList_Length(list));
	LinkList_Insert(list, (LinkListNode *)&t3, LinkList_Length(list));

	for (i = 0; i < LinkList_Length(list); i++)
	{
		Teacher *tmp=(Teacher*)LinkList_Get(list, i);
		if (tmp != NULL)
		{
			printf("age:%d   ", tmp->age);
		}

	}
	while (LinkList_Length(list)>0)
	{
		Teacher *tmp = (Teacher*)LinkList_Delete(list, 0);
		if (tmp!= NULL)
		{
			printf("age: %d ", tmp->age);
		}
	}
	LinkList_Destroy(list);
	system("pause");

	



}







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值