数据结构 顺序表,链表。

数据结构 列表和链表



前言

队列初学之后,我在回顾下之前的顺序表,链表之类的各种概念及其实现


提示:以下是本篇文章正文内容,下面案例可供参考

一,表的概念

1.1 线性表

线性表:零个或者多个数据元素的有限序列。
定义:第一个元素无前驱,最后一个元素无后继。除此外的每个元素有且仅有一个前驱和一个后继。

1.2线性表的顺序存储结构

线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。
可以用C语言的一堆数组来实现顺序存储结构
在这里插入图片描述
顺序表的功能设计
在这里插入图片描述

1.3线性表的链式存储结构

为了解决存储结构能够支持动态的添加及删除数据元素这个问题,我们引入了线性表的链式存储结构—链表。
其特点为:用一组任意的存储单元存储线性表的数据元素。
在这里插入图片描述
为了表示其中逻辑关系,我们把存储数据元素信息的域称为数据域,把存储直接后继的域称为指针域。这两部分信息组成的数据元素的存储映像称为结点(NODE)。
链表中只包含一个指针域,所以叫单链表。其中尾节点的指针域指向头节点则称为循环链表。
在这里插入图片描述

1.4 单链表结构和顺序存储结构的优缺点

存储分配
在这里插入图片描述
时间性能
在这里插入图片描述
空间性能

在这里插入图片描述

1.5 双向链表

为了克服链表的单向性,设计了双向链表(double linked list)。其是在单链表的每个结点中,在设置一个指向其前驱结点的指针域
在这里插入图片描述

二、顺序表和链表的实现

2.1顺序存储的结构代码

代码如下(示例):

#define MAXSIZE 20 
typedef int ElemType;
typedef struct  sqlist{
ElemType data [MAXSIZE];
 int length;

}Sqlist

第二个结构体为不定长顺序表

#define INIT_SIZE 10
typedef struct DSQList
{
	int  *data;
	int  length;
	int  listsize;
}DSQList, *PDSQList;

2.2不定长顺序表基本功能及实现

void Init_list(PDSQList ps);
//初始化

void Init_list(PDSQList ps)
{
	assert(ps != NULL);
	if (ps == NULL){return;}
	ps->data = (int*)malloc(sizeof(int) * INIT_SIZE);
	assert(ps->data != NULL);
	ps->length = 0;
	ps->listsize = INIT_SIZE;
}

bool Insert(PDSQList ps, int pos, int val);
//插值

bool Insert(PDSQList ps, int pos, int val) {
	assert(ps != NULL);//判断pos合法性
	if (pos < 0 || pos > ps->length) {
		return false;
	}
	if (IsFull(ps)) {

		Inc(ps);//扩容
	}
	//挪动数据,插入位置空出来, 值放进去  length ++
	for (int i = ps->length - 1; i >= pos; i--) {
		ps->data[i + 1] = ps->data[i];
	}
	ps->data[pos] = val;
	ps->length++;
	return true;
}

bool Del_pos(PDSQList ps, int pos);
//按位置删

bool Del_pos(PDSQList ps, int pos) {
	if (pos < 0 || pos >= ps->length) {
		return false;
	}
	//如果空就不允许删除操作。
	//挪数据
	for (int i = pos; i + 1 < ps->length; i++) {
		ps->data[i] = ps->data[i + 1];
	}
	//有效长度--
	ps->length--;
	return true;
}

bool Del_val(PDSQList ps, int val);
//按值删

bool Del_val(PDSQList ps, int val) {

	int i = Search(ps, val);
	if (i == -1) {
		return false;

	}
	Del_pos(ps, i);
	return true;
}

int Search(PDSQList ps, int val);
//值查找

int Search(PDSQList ps, int val) {

	for (int i = 0; i < ps->length; i++)
	{
		if (val == ps->data[i])
		{
			return i;
		}
	}
}

bool IsEmpty(PDSQList ps);
//判空

bool IsEmpty(PDSQList ps) {

return	ps->length == 0;
}

bool IsFull(PDSQList ps);
//判满

bool IsFull(PDSQList ps) {

	return ps->listsize == ps->length;
}

void Inc(PDSQList ps);
//扩容

static void Inc(PDSQList ps)//扩容
{  //malloc   realloc    calloc
	ps->data = (int*)realloc(ps->data, sizeof(int) * ps->listsize * 2);
	assert(ps->data != NULL);
	ps->listsize *= 2;

 }

void Clear(PDSQList);
//清空

void Clear(PDSQList ps) {
	ps->length = 0;
}

void Destory(PDSQList ps);
//销毁

void  Destory(PDSQList ps) {

	free(ps->data);
	ps->data = NULL;
	ps->length = 0;
	ps->listsize = 0;
}

void Show(PDSQList ps);
//用于打印值

void Show(PDSQList ps) {

	for (int i = 0; i < ps->length; i++)
	{
		printf("%d ", ps->data[i]);

	}
	printf("\n");
}

int Get_length(PDSQList ps);
//获取有效长度

int Get_length(PDSQList ps)
{
	return ps->length;
}

2.3单链表的结构体定义

typedef int data_t;
//单链表结点的存储结构
struct Node
{
	data_t data;//数据域
	struct Node* next;//指向下一个结点的指针域

};
typedef struct Node LINK;

2.4 单链表基本操作及实现

//创建单链表
LINK* createLink();

LINK* createLink()
{
	LINK* p = (LINK*)malloc(sizeof(LINK));
	if (p != NULL)
	{
		printf("单链表创建成功\n");
	}
	memset(p, 0, sizeof(LINK));
	p->next = NULL;
	return p;
}

//判断单链表是否为空
int isEmpty(LINK* pHead);

//判断单链表是否为空
int isEmpty(LINK* pHead)
{
	if (pHead->next == NULL) {
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

//头插法
void insertLinkHead(LINK* pHead, data_t num);

//头插法
void insertLinkHead(LINK* pHead, data_t num) {
	//创建新结点
	LINK* node = (LINK*)malloc(sizeof(LINK));
	if (node == NULL) {
		printf("新节点创建失败\n");
		return;
	}
	memset(node, 0, sizeof(LINK));
	node->data = num;
	//插入结点
	node->next = pHead->next;
	pHead->next = node;
}

//尾插法
void insertLinkTail(LINK* pHead, data_t num);

//尾插法
void insertLinkTail(LINK* pHead, data_t num)
{
	//创建新结点
	LINK* node = (LINK*)malloc(sizeof(LINK));
	if (node == NULL) {
		printf("新节点创建失败\n");
		return;
	}
	memset(node, 0, sizeof(LINK));
	node->data = num;
	//遍历到链表尾部
	LINK* tmp = pHead;
	while (tmp->next != NULL) {
		tmp = tmp->next;
	}
	tmp->next = node;//最后一个元素的指针域指向新结点
}

//指定位置插入新元素
void insertNew(LINK* pHead, data_t num, int offset);

//指定位置插入新元素
void insertNew(LINK* pHead, data_t num, int offset)
{
	//创建新结点
	LINK* node = (LINK*)malloc(sizeof(LINK));
	memset(node, 0, sizeof(LINK));
	node->data = num;
	//循环遍历链表,找到对应位置
	int  i = 1;
	LINK* pTmp = pHead;
	while (pTmp->next != NULL) {
		if (offset == i) {
			node->next = pTmp->next;
			pTmp->next = node;
			return;
		}
		//printf("%d\n", i);
		i++;
		pTmp = pTmp->next;
	}
}

//打印单链表所有结点
void printLink(LINK* pHead);

void printLink(LINK* pHead)
{
	LINK* pTmp = NULL;
	pTmp = pHead->next;//pTmp指向了第一个数据节点
	while (pTmp != NULL)
	{
		printf("%d\t", pTmp->data);
		pTmp = pTmp->next;
	}
	putchar('\n');
}

//头删
void delHead(LINK* pHead);

//头删
void delHead(LINK* pHead) {
	LINK* pDel = NULL;
	if (pHead->next != NULL) {
		pDel = pHead->next;
		pHead->next = pDel->next;
		free(pDel);
		pDel = NULL;
	}
}

//尾删
void delTail(LINK* pHead);

void delTail(LINK* pHead)
{
	LINK* tmp1 = pHead;
	LINK* tmp2 = pHead->next;
	if (isEmpty(pHead) == FALSE) {
		while (tmp2->next != NULL)
		{
			tmp1 = tmp1->next;
			tmp2 = tmp2->next;
		}
		tmp1->next = tmp2->next;
		free(tmp2);
		tmp2 = NULL;
	}
}

//指定数据删除
void delLocation(LINK* pHead, data_t num);

void delLocation(LINK* pHead, data_t num)
{
	LINK* tmp1 = pHead;
	LINK* tmp2 = pHead->next;
	while (tmp1->next != NULL)
	{
		if (tmp2->data == num) {
			tmp1->next = tmp2->next;
			free(tmp2);
			tmp2 = NULL;
			return;
		}
		tmp1 = tmp1->next;
		tmp2 = tmp2->next;
	}
}

//清除
void Clearall(LINK* pHead);

void Clearall(LINK* pHead) {
	LINK* tmp = NULL;
	while (pHead != NULL) {
		tmp = pHead->next;
		free(pHead);
		pHead = tmp;
	}
}

//销毁
void Destory(LINK* pHead);

// 消除单链表(头销,尾销)
void Destory1(LINK* pHead) {
	LINK* tmp = NULL;
	while (pHead != NULL) {
		tmp = pHead->next;
		free(pHead);
		pHead = tmp;
	}
}

//按值检索
LINK* search_val(LINK* pHead);

// 查询指定元素在单链表中的位置
int search_val(LINK* pHead, data_t val) {
	int pos = 0;
	for (LINK* tmp = pHead->next; tmp != NULL; tmp = tmp->next, pos++) {
		if (tmp->data == val) {
			return pos; // 返回位置
		}
	}
	return -1; // 未找到返回-1
}

//改位置的值
void Change_pos(LINK* pHead, int pos,int val);

void Change_pos(LINK* pHead, int pos, data_t val) {
	int i = 0;
	LINK* tmp = NULL;
	for (LINK* tmp = pHead->next; tmp != NULL && i < pos; tmp = tmp->next, i++);
	if ( tmp!= NULL) { // 检查是否找到了指定位置
		tmp->data = val;
	}
}

//值替换
void Change_val(LINK* pHead,int val,int val2);

oid Change_val(LINK* pHead, data_t val, data_t new_val) {
	for (LINK* tmp = pHead->next; tmp != NULL; tmp = tmp->next) {
		if (tmp->data == val) {
			tmp->data = new_val;
		}
	}
}

总结

大致讲述了各种表的基础概念,并且列举了链表和不定长顺序表的基础操作。
这次先到此为止,下次总给双向循环链表的代码,小生浅薄,有不足之处,望诸位看官多多包涵不吝赐教。 salute!!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值