顺序表和链表

 线性表

线性表 linear list n 个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使
用的数据结构,常见的线性表:顺序表链表、栈、队列、字符串 ...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,
线性表在物理上存储时,通常以数组和链式结构的形式存储。

 顺序表

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存

储。在数组上完成数据的增删查改。
顺序表和链表_第1张图片

 顺序表一般的功能

顺序表一般需要能够尾插、头插、尾删、头删、任意插入(后面)、任意位置删除等主要功能;

void SLInit(SL*ps1);//初始化
void SLDestroy(SL*ps1);//销毁
void SLPrint(SL* ps1);//打印
void SLCheckcapacity(SL* ps1);//检查容量是否已经满了
void SLPushBack(SL* ps1, SLDataType x);//尾插
void SLPushFront(SL* ps1, SLDataType x);//头插
void SLPopBack(SL* ps1);//尾删
void SLPopFront(SL* ps1);//头删
void SLInSert(SL* ps1, int pos, SLDataType x);//任意位置插入;
void SLErase(SL* ps1, int pos);//任意位置删除
int SLFind(SL* ps1, SLDataType x);//查找

接口实现

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致 N 定大了,空
间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间
大小,所以下面我们实现动态顺序表。
初始化
void SLInit(SL* ps1)//初始化
{
	assert(ps1);
	ps1->a = NULL;
	ps1->size = 0;
	ps1->capacity = 0;
}
销毁顺序表
void SLDestroy(SL* ps1)//销毁
{
	assert(ps1);
	if (ps1->a != NULL)
	{
		free(ps1->a);
		ps1->a = NULL;
		ps1->size = 0;
		ps1->capacity = 0;
	}
}
打印
void SLPrint(SL* ps1)//打印
{
	assert(ps1);
	int i = 0;
	for (i = 0; i < ps1->size; i++)
	{
		printf("%d ", ps1->a[i]);
	}
	printf("\n");
}
检查空间是否满的情况
void SLCheckcapacity(SL* ps1)//检查空间是否满了
{
	assert(ps1);
	if (ps1->size == ps1->capacity)//空间满的情况下
	{
		SLDataType newcapacity = ps1->capacity == 0 ? 4 : 2 * ps1->capacity;//开始capacity为空的话给它一些空间
		SLDataType* tmp = (SLDataType*)realloc(ps1->a, sizeof(SLDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc");
			return;
		}
		ps1->a = tmp;
		ps1->capacity = newcapacity;
	}
}
尾插
void SLPushBack(SL * ps1, SLDataType x)//尾插
{
	assert(ps1);
	SLCheckcapacity(ps1);
	ps1->a[ps1->size] = x;//空间够的情况下,直接在size的位置尾插,
	ps1->size++;//size用完++;
}
头插
void SLPushFront(SL* ps1, SLDataType x)//头插
{
	assert(ps1);
	SLCheckcapacity(ps1);
	int end = ps1->size - 1;
	while (end >= 0)
	{
		ps1->a[end + 1] = ps1->a[end];
		end--;
	}
	ps1->a[0] = x;
	ps1->size++;
}
尾删
void SLPopBack(SL* ps1)//尾删
{
	assert(ps1->size>0);//为真就过,为假报错,防止size减到0还去减;
	ps1->size--;//减去一个size即删除最后一个数据;
}
头删
void SLPopFront(SL* ps1)//头删
{
	assert(ps1->size > 0);
	int begin = 1;
	while (begin < ps1->size)
	{
		ps1->a[begin-1] = ps1->a[begin];
		begin++;
	}
	ps1->size--;
}
任意位置插入(在指定位置的后面)
void SLInSert(SL* ps1, int pos, SLDataType x)//任意位置插入;
{
	assert(ps1);
	assert(pos >= 0 && pos <= ps1->size);
	SLCheckcapacity(ps1);
	int end = ps1->size - 1;
	while (end >= pos)
	{
		ps1->a[end + 1] = ps1->a[end];
		end--;
	}
	ps1->a[pos] = x;
	ps1->size++;
}
任意位置删除
void SLErase(SL* ps1, int pos)//任意位置删除
{
	assert(ps1);
	assert(pos >= 0 && pos < ps1->size);
	int begin = pos + 1;
	while (begin < ps1->size)
	{
		ps1->a[begin - 1] = ps1->a[begin];
		begin++;
	}
	ps1->size--;
}
查找某个数据
int SLFind(SL* ps1, SLDataType x)//查找
{
	assert(ps1);
	int i = 0;
	for (i = 0; i < ps1->size; i++)
	{
		if (ps1->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

链表

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

 链表主要分为八种形态:单向不带头非循环、单向不带头循环、单向带头非循环、单向带头循环、双向不带头非循环、双向不带头循环、双向带头不循环、双向带头循环链表;

他们之间结构能功能非常类似,掌握其中一个,就可以稍加变通,掌握其他几种,我们经常使用到的是单向不带头非循环链表和双向带头循环链表,这两可以说是链表结构中的两个极端——一个穷困潦倒什么都没有,一个富家少爷什么都有。话说回来,无头单向不循环链表结构最简单,但却是最难实现的一个链表,带头双向循环链表结构最复杂,但却是实现起来最容易上手的一个。前者是关于链表内容OJ题的常客,后者则是我们日常最经常使用的。

链表接口实现

无头单向不循环链表
打印
void SLPrint(SLNode* phead)//打印
{
	SLNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->val);
		cur = cur->next;
	}
	printf("NULL\n");
}
创建新的结点
SLNode* CreateNode(SLNDataType x)//创建新的结点
{
	SLNode* NewNode = (SLNode*)malloc(sizeof(SLNode));
	if (NewNode == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	NewNode->val = x;
	NewNode->next = NULL;
	return NewNode;
}
尾插 
void SLPushBack(SLNode** pphead, SLNDataType x)//尾插;
{
	SLNode* NewNode = CreateNode(x);//创建新节点
	if (*pphead == NULL)  //链表为空
	{
		*pphead=NewNode;
	}
	else//链表不为空
	{
		SLNode* tail = *pphead;//找尾在哪里
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = NewNode;
	}
	
}
头插
void SLPushFront(SLNode** pphead, SLNDataType x)//头插;
{
	SLNode* NewNode = CreateNode(x);
	NewNode->next = *pphead;
	*pphead = NewNode;
}
尾删
void SLPopBack(SLNode** pphead)//尾删;
{
	assert(*pphead);
	if ((*pphead)->next==NULL)//一个节点,直接把这个结点free
	{
		free(*pphead);
		*pphead = NULL;
	}
	else//不止一个节点
	{
		SLNode* pre = NULL;//定义一个结点,让它始终在tail前面一个,当tail->next=NULL时,说明是最后一个结点,把pre->置空
		SLNode* tail = *pphead;//找尾
		while (tail->next != NULL)
		{
			pre = tail;
			tail = tail->next;
		}
		free(tail);
		tail = NULL;
		pre->next = NULL;
	}
}
头删
void SLPopFront(SLNode** pphead)//头删;
{
	assert(*pphead);
	SLNode* tmp = (*pphead)->next;//定义一个结点,让它指向头节点的下一个结点;
	free(*pphead);//释放头节点
	*pphead = tmp;//把新的头节点指向定义的tmp;
	
}
查找
SLNode* SLFind(SLNode* phead, SLNDataType x)//查找
{
	SLNode* cur = phead;
	while (cur!=NULL)
	{
		if (cur->val == x)
			return cur;

		cur= cur->next;
	}

	return NULL;
}
 任意位置后面插入
void SLInsert(SLNode** pphead, SLNode* pos, SLNDataType x)//任意后插入
{
	SLNode* NewNode = CreateNode(x);
	NewNode->next = pos->next;
	pos->next = NewNode;
}
任意位置删除
void SLErase(SLNode** pphead, SLNode* pos)//任意删除
{
	if (pos = *pphead)//如果pos就是头节点,就是头删
	{
		SLPopFront(pphead);
	}
	else
	{
		SLNode* pre = *pphead;
		while (pre->next != pos)
		{
			pre = pre->next;
		}
		pre->next = pos->next;
		free(pos);
	}
}
销毁
void SLTDestroy(SLNode** pphead)//销毁
{
	assert(pphead);

	SLNode* cur = *pphead;
	while (cur)
	{
		SLNode* next = cur->next;
		free(cur);
		cur = next;
	}

	*pphead = NULL;
}
带头双向循环链表
创建新的结点
LT* CreateLTnode(Datatype x)//创建新的节点
{
	LT* newnode = (LT*)malloc(sizeof(LT));
	if (newnode == NULL)
	{
		perror("malloc");
		exit (-1);
	}
	newnode->data = x;
	newnode->pre = NULL;
	newnode->next=NULL;
	return newnode;
}
初始化
LT*  LTInit()
{
	LT*phead = CreateLTnode(-1);
	phead->pre = phead;
	phead->next = phead;
	return phead;
}
打印
void LTPrint(LT*phead)
{
	assert(phead);
	LT* cur = phead->next;
	while (cur != phead)
	{
		printf("%d<-->", cur->data);
		cur = cur->next;
	}
	printf("\n");
}
尾插
void LTPushback(LT* phead, Datatype x)//尾插
{
	assert(phead);
	LT* ptail = phead->pre;//找尾
	LT* newnode = CreateLTnode(x);
	ptail->next = newnode;
	newnode->pre = ptail;
	newnode->next = phead;
	phead->pre = newnode;

}
尾删
void LTPopback(LT* phead)//尾删
{
	assert(phead);
	assert(phead->next != NULL);
	LT* tail = phead->pre;
	LT* tailpre = phead->pre->pre;
	phead->pre = tailpre;
	tailpre->next = phead;
	free(tail);
	tail = NULL;
}
头插
void LTPushfront(LT* phead, Datatype x)//头插
{
	LT* newnode = CreateLTnode(x);
	LT* Next = phead->next;
	phead->next = newnode;
	newnode->next = Next;
	newnode->pre = phead;
	Next->pre = newnode;
}
头删
void LTPopfront(LT* phead)//头删
{
	assert(phead);
	assert(phead->next != NULL);
	LT* cur = phead->next;
	LT* Next = phead->next->next;
	phead->next = Next;
	Next->pre = phead;
	free(cur);
	cur = NULL;
}
查找
LT* LTFind(LT* phead, Datatype x)//查找
{
	assert(phead);
	LT* cur = phead->next;
	while (cur != NULL)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
任意位置插入
void LTInsert(LT* pos, Datatype x)//任意位置插入;//在pos的前面插入,传pos=phead时是尾插
{
	assert(pos);
	LT* pospre = pos->pre;
	LT* newnode = CreateLTnode(x);
	pospre->next = newnode;
	newnode->next = pos;
	newnode->pre = pospre;
	pos->pre = newnode;
}
任意位置删除
void LTErase(LT* pos)//任意位置删除;
{
	assert(pos);
	LT* pospre = pos->pre;
	LT* posnext = pos->next;
	pospre->next = posnext;
	posnext->pre = pospre;
	free(pos);
	pos = NULL;
}
销毁
void LTDestroy(LT* phead)//销毁
{
	assert(phead);
	LT* cur = phead->next;
	while (cur != phead)
	{
		LT* Next = cur->next;
		free(cur);
		cur = Next;

	}
	free(phead);
}

顺序表和单链表的区别

顺序表和链表_第3张图片

 源码

顺序表

#include
#include
#include
typedef int SLDataType;//重定义数据类型,方便以后可能改类型
typedef struct SeqList
{
	int* a;
	int size;//有效数据的个数
	int capacity;//容量大小
}SL;
void SLInit(SL*ps1);//初始化
void SLDestroy(SL*ps1);//销毁
void SLPrint(SL* ps1);//打印
void SLCheckcapacity(SL* ps1);//检查容量是否已经满了
void SLPushBack(SL* ps1, SLDataType x);//尾插
void SLPushFront(SL* ps1, SLDataType x);//头插
void SLPopBack(SL* ps1);//尾删
void SLPopFront(SL* ps1);//头删
void SLInSert(SL* ps1, int pos, SLDataType x);//任意位置插入;
void SLErase(SL* ps1, int pos);//任意位置删除
int SLFind(SL* ps1, SLDataType x);//查找
void SLInit(SL* ps1)//初始化
{
	assert(ps1);
	ps1->a = NULL;
	ps1->size = 0;
	ps1->capacity = 0;
}
void SLDestroy(SL* ps1)//销毁
{
	assert(ps1);
	if (ps1->a != NULL)
	{
		free(ps1->a);
		ps1->a = NULL;
		ps1->size = 0;
		ps1->capacity = 0;
	}
}
void SLPrint(SL* ps1)//打印
{
	assert(ps1);
	int i = 0;
	for (i = 0; i < ps1->size; i++)
	{
		printf("%d ", ps1->a[i]);
	}
	printf("\n");
}
void SLCheckcapacity(SL* ps1)//检查空间是否满了
{
	assert(ps1);
	if (ps1->size == ps1->capacity)//空间满的情况下
	{
		SLDataType newcapacity = ps1->capacity == 0 ? 4 : 2 * ps1->capacity;//开始capacity为空的话给它一些空间
		SLDataType* tmp = (SLDataType*)realloc(ps1->a, sizeof(SLDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc");
			return;
		}
		ps1->a = tmp;
		ps1->capacity = newcapacity;
	}
}
void SLPushBack(SL * ps1, SLDataType x)//尾插
{
	assert(ps1);
	SLCheckcapacity(ps1);
	ps1->a[ps1->size] = x;//空间够的情况下,直接在size的位置尾插,
	ps1->size++;//size用完++;
}
void SLPushFront(SL* ps1, SLDataType x)//头插
{
	assert(ps1);
	SLCheckcapacity(ps1);
	int end = ps1->size - 1;
	while (end >= 0)
	{
		ps1->a[end + 1] = ps1->a[end];
		end--;
	}
	ps1->a[0] = x;
	ps1->size++;
}
void SLPopBack(SL* ps1)//尾删
{
	assert(ps1->size>0);//为真就过,为假报错,防止size减到0还去减;
	ps1->size--;//减去一个size即删除最后一个数据;
}
void SLPopFront(SL* ps1)//头删
{
	assert(ps1->size > 0);
	int begin = 1;
	while (begin < ps1->size)
	{
		ps1->a[begin-1] = ps1->a[begin];
		begin++;
	}
	ps1->size--;
}
void SLInSert(SL* ps1, int pos, SLDataType x)//任意位置插入;
{
	assert(ps1);
	assert(pos >= 0 && pos <= ps1->size);
	SLCheckcapacity(ps1);
	int end = ps1->size - 1;
	while (end >= pos)
	{
		ps1->a[end + 1] = ps1->a[end];
		end--;
	}
	ps1->a[pos] = x;
	ps1->size++;
}
void SLErase(SL* ps1, int pos)//任意位置删除
{
	assert(ps1);
	assert(pos >= 0 && pos < ps1->size);
	int begin = pos + 1;
	while (begin < ps1->size)
	{
		ps1->a[begin - 1] = ps1->a[begin];
		begin++;
	}
	ps1->size--;
}
int SLFind(SL* ps1, SLDataType x)//查找
{
	assert(ps1);
	int i = 0;
	for (i = 0; i < ps1->size; i++)
	{
		if (ps1->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

 无头单向不循环链表

#include
#include
#include
typedef int SLNDataType;
typedef struct SListNode
{
	SLNDataType val;
	struct SListNode* next;//下一个节点
}SLNode;
void SLPrint(SLNode* phead);//打印
SLNode* CreateNode(SLNDataType x);//创建新的结点
void SLPushBack(SLNode** pphead, SLNDataType x);//尾插;
void SLPushFront(SLNode** pphead, SLNDataType x);//头插;
void SLPopBack(SLNode** pphead);//尾删;
void SLPopFront(SLNode** pphead);//头删;
SLNode* SLFind(SLNode* phead, SLNDataType x);//查找
void SLInsert(SLNode** pphead, SLNode* pos, SLNDataType x);//任意插入
void SLErase(SLNode** pphead, SLNode* pos);//任意删除
void SLTDestroy(SLNode** pphead);//销毁
void SLPrint(SLNode* phead)//打印
{
	SLNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->val);
		cur = cur->next;
	}
	printf("NULL\n");
}
SLNode* CreateNode(SLNDataType x)//创建新的结点
{
	SLNode* NewNode = (SLNode*)malloc(sizeof(SLNode));
	if (NewNode == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	NewNode->val = x;
	NewNode->next = NULL;
	return NewNode;
}
void SLPushBack(SLNode** pphead, SLNDataType x)//尾插;
{
	SLNode* NewNode = CreateNode(x);//创建新节点
	if (*pphead == NULL)  //链表为空
	{
		*pphead=NewNode;
	}
	else//链表不为空
	{
		SLNode* tail = *pphead;//找尾在哪里
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = NewNode;
	}
	
}
void SLPushFront(SLNode** pphead, SLNDataType x)//头插;
{
	SLNode* NewNode = CreateNode(x);
	NewNode->next = *pphead;
	*pphead = NewNode;
}
void SLPopBack(SLNode** pphead)//尾删;
{
	assert(*pphead);
	if ((*pphead)->next==NULL)//一个节点,直接把这个结点free
	{
		free(*pphead);
		*pphead = NULL;
	}
	else//不止一个节点
	{
		SLNode* pre = NULL;//定义一个结点,让它始终在tail前面一个,当tail->next=NULL时,说明是最后一个结点,把pre->置空
		SLNode* tail = *pphead;//找尾
		while (tail->next != NULL)
		{
			pre = tail;
			tail = tail->next;
		}
		free(tail);
		tail = NULL;
		pre->next = NULL;
	}
}
void SLPopFront(SLNode** pphead)//头删;
{
	assert(*pphead);
	SLNode* tmp = (*pphead)->next;//定义一个结点,让它指向头节点的下一个结点;
	free(*pphead);//释放头节点
	*pphead = tmp;//把新的头节点指向定义的tmp;
	
}
SLNode* SLFind(SLNode* phead, SLNDataType x)//查找
{
	SLNode* cur = phead;
	while (cur!=NULL)
	{
		if (cur->val == x)
			return cur;

		cur= cur->next;
	}

	return NULL;
}
void SLInsert(SLNode** pphead, SLNode* pos, SLNDataType x)//任意后插入
{
	SLNode* NewNode = CreateNode(x);
	NewNode->next = pos->next;
	pos->next = NewNode;
}
void SLErase(SLNode** pphead, SLNode* pos)//任意删除
{
	if (pos = *pphead)//如果pos就是头节点,就是头删
	{
		SLPopFront(pphead);
	}
	else
	{
		SLNode* pre = *pphead;
		while (pre->next != pos)
		{
			pre = pre->next;
		}
		pre->next = pos->next;
		free(pos);
	}
}
void SLTDestroy(SLNode** pphead)//销毁
{
	assert(pphead);

	SLNode* cur = *pphead;
	while (cur)
	{
		SLNode* next = cur->next;
		free(cur);
		cur = next;
	}

	*pphead = NULL;
}

带头双向循环链表

#include
#include
#include
typedef int Datatype;
typedef struct Listnode
{
	Datatype data;
	struct Listnode* next;
	struct Listnode* pre;
}LT;
LT*  LTInit();//初始化
void LTPrint(LT* phead);//打印
void LTPushback(LT* phead, Datatype x);//尾插
void LTPopback(LT* phead);//尾删
void LTPushfront(LT* phead, Datatype x);//头插
void LTPopfront(LT* phead);//头删
LT* LTFind(LT* phead, Datatype x);//查找
void LTInsert(LT* pos, Datatype x);//任意位置插入;
void LTErase(LT* pos);//任意位置删除;
void LTDestroy(LT* phead);//销毁
LT* CreateLTnode(Datatype x)//创建新的节点
{
	LT* newnode = (LT*)malloc(sizeof(LT));
	if (newnode == NULL)
	{
		perror("malloc");
		exit (-1);
	}
	newnode->data = x;
	newnode->pre = NULL;
	newnode->next=NULL;
	return newnode;
}
LT*  LTInit()
{
	LT*phead = CreateLTnode(-1);
	phead->pre = phead;
	phead->next = phead;
	return phead;
}
void LTPrint(LT*phead)
{
	assert(phead);
	LT* cur = phead->next;
	while (cur != phead)
	{
		printf("%d<-->", cur->data);
		cur = cur->next;
	}
	printf("\n");
}
void LTPushback(LT* phead, Datatype x)//尾插
{
	assert(phead);
	LT* ptail = phead->pre;//找尾
	LT* newnode = CreateLTnode(x);
	ptail->next = newnode;
	newnode->pre = ptail;
	newnode->next = phead;
	phead->pre = newnode;

}
void LTPopback(LT* phead)//尾删
{
	assert(phead);
	assert(phead->next != NULL);
	LT* tail = phead->pre;
	LT* tailpre = phead->pre->pre;
	phead->pre = tailpre;
	tailpre->next = phead;
	free(tail);
	tail = NULL;
}
void LTPushfront(LT* phead, Datatype x)//头插
{
	LT* newnode = CreateLTnode(x);
	LT* Next = phead->next;
	phead->next = newnode;
	newnode->next = Next;
	newnode->pre = phead;
	Next->pre = newnode;
}
void LTPopfront(LT* phead)//头删
{
	assert(phead);
	assert(phead->next != NULL);
	LT* cur = phead->next;
	LT* Next = phead->next->next;
	phead->next = Next;
	Next->pre = phead;
	free(cur);
	cur = NULL;
}
LT* LTFind(LT* phead, Datatype x)//查找
{
	assert(phead);
	LT* cur = phead->next;
	while (cur != NULL)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

void LTInsert(LT* pos, Datatype x)//任意位置插入;//在pos的前面插入,传pos=phead时是尾插
{
	assert(pos);
	LT* pospre = pos->pre;
	LT* newnode = CreateLTnode(x);
	pospre->next = newnode;
	newnode->next = pos;
	newnode->pre = pospre;
	pos->pre = newnode;
}
void LTErase(LT* pos)//任意位置删除;
{
	assert(pos);
	LT* pospre = pos->pre;
	LT* posnext = pos->next;
	pospre->next = posnext;
	posnext->pre = pospre;
	free(pos);
	pos = NULL;
}
void LTDestroy(LT* phead)//销毁
{
	assert(phead);
	LT* cur = phead->next;
	while (cur != phead)
	{
		LT* Next = cur->next;
		free(cur);
		cur = Next;

	}
	free(phead);
}

你可能感兴趣的:(链表,数据结构)