0
点赞
收藏
分享

微信扫一扫

【数据结构】(初阶):线性表

书写经典 2022-05-01 阅读 115

 

✨前言✨


线性表

线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表,链表,栈,队列,字符串...

线性表在逻辑上是线性结构,也就是说是来连续的一条直线,但是在物理结构上不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式进行存储。


顺序表

顺序表的概念以及结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储,在数组上完成增删改查。

顺序表一般分为两种:

  • 静态顺序表
  • 动态顺序表

静态顺序表即使用定长数组存储元素。

动态顺序表即使用动态开辟的数组存储。


顺序表接口实现

typedef int SLDataType;

typedef struct SeqList
{
	SLDataType *p;//指向动态开辟的数组
	int size;//有效数据个数
	int capacity;//容量空间大小
}SL;

初始化

void SL_Init(SL* ps)
{
	assert(ps);
	ps->size = 0;
	ps->capacity = 0;
	ps->p = NULL;
}

检查容量

void SL_CheckCapacity(SL* ps)
{
	if (ps->capacity == ps->size)
	{
		int newCapacity = (ps->capacity == 0 ? 4 : 2 * ps->capacity);
		SLDataType* temp = (SLDataType*)realloc(ps->p, sizeof(SLDataType) * newCapacity);
		if (NULL == temp)
		{
			printf("realloc failed\n");
			return;
		}
		ps->p = temp;
		ps->capacity = newCapacity;
	}
}

数据插入

void SL_Insert(SL* ps, int loc, SLDataType x)
{
	assert(ps);
	assert(loc >= 0 && loc <= ps->size);

	SL_CheckCapacity(ps);
	int end = ps->size - 1;
	while (end >= loc)
	{
		ps->p[end + 1] = ps->p[end];
		end--;
	}
	ps->p[loc] = x;
	ps->size++;
}

 数据删除

void SL_Erase(SL* ps,int loc)
{
	assert(ps);
	assert(loc >= 0 && loc < ps->size);

	int begin = loc;
	while (begin < ps->size - 1)
	{
		ps->p[begin] = ps->p[begin + 1];
		begin++;
	}
	ps->size--;
}

 数据查找

int SL_Find(const SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (x == ps->p[i])
		{
			return i;
		}
	}
	return -1;
}

数据修改

void SL_Modify(SL* ps, int loc, SLDataType x)
{
	assert(ps);
	assert(loc >= 0 && loc < ps->size);

	ps->p[loc] = x;
}

数据打印

void SL_Print(const SL* ps)
{
	assert(ps);
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->p[i]);
	}
	printf("\n");
}

销毁顺序表

void SL_Destroy(SL* ps)
{
	assert(ps);
	if (ps->p != NULL)
	{
		free(ps->p);
		ps->p = NULL;
	}
}

链表

链表是一种物理存储上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

链表分类:

  • 单向或者双向
  • 带头或者不带头
  • 循环或者非循环

虽然有很多分类,但是最常用的就有两种结构:

  • 带头单向非循环链表
  • 带头双向循环链表

单链表接口实现

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

typedef int SListDataType;
typedef struct SListNode
{
	SListDataType data;
	struct SListNode* next;
}SListNode;

创建新节点

SListNode* BuySListNode(SListDataType x)
{
	SListNode* newNode = (SListNode*)malloc(sizeof(SListNode));
	assert(newNode);
	newNode->data = x;
	newNode->next = NULL;
	return newNode;
}

头插节点

void SL_PushFront(SListNode** phead,const SListDataType x)
{
	SListNode* newNode = BuySListNode(x);
	if (*phead == NULL)
	{
		*phead = newNode;
		return;
	}
	newNode->next = *phead;
	*phead = newNode;
}

尾插节点

void SL_PushBack(SListNode** phead,const SListDataType x)
{
	SListNode* newNode = BuySListNode(x);
	if (*phead == NULL)
	{
		*phead = newNode;
		return;
	}
	SListNode* cur = *phead;
	while (cur->next != NULL)
	{
		cur = cur->next;
	}
	cur->next = newNode;
}

链表打印

void SL_Show(const SListNode** phead)
{
	assert(phead);
	SListNode* cur = *phead;
	while (cur != NULL)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
}

插入数据

void SL_Insert(SListNode** pphead, SListNode* loc, SListDataType x)
{
	assert(pphead && loc);
	SListNode* newNode = BuySListNode(x);
	SListNode* cur = *pphead;
	while (cur != loc)
	{
		assert(cur);
		cur = cur->next;
	}
	newNode->next = cur->next;
	cur->next = newNode;
}

查找数据 

SListNode* SL_Find(const SListNode** phead, SListDataType x)
{
	SListNode* cur = *phead;
	while (cur->data != x)
	{
		cur = cur->next;
	}
	return cur;
}

 头删节点 

void SL_PopFront(SListNode** phead)
{
	assert(phead);
	SListNode* temp = *phead;
	*phead = (*phead)->next;
	free(temp);
}

尾删节点

void SL_PopBack(SListNode** phead)
{
	SListNode* cur = *phead;
	while ((cur->next)->next != NULL)
	{
		cur = cur->next;
	}
	free(cur->next);
	cur->next = NULL;
}

销毁链表 

void SL_Destroy(SListNode** pphead)
{
	SListNode* cur = *pphead;
	assert(pphead);
	while ((*pphead)->next != NULL)
	{
		cur = *pphead;
		*pphead = (*pphead)->next;
		free(cur);
	}
	free(*pphead);
}

举报

相关推荐

0 条评论