ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

数据结构(C)之线性表(未完成)

2021-09-25 20:33:19  阅读:166  来源: 互联网

标签:NULL 线性表 int SeqList list ret 完成 tlist 数据结构


文章目录


1、线性表基本定义

1.1 线性表定义

  线性表(List)是零个或多个数据元素的集合
  线性表中的数据元素之间是有顺序的
  线性表中的数据元素是有限的
  线性表中的数据类型必须相同

在这里插入图片描述



1.2 数学定义

  线性表宿舍具有相同类型n(≧ 0)个数据元素的有限序列,(a1,a2,……,an),ai是表项,n是表长度

1.3 性质

  a0为线性表的第一个元素,只有一个后继
  an为线性表的最后一个元素,只有一个前驱
  除a和an外的其他元素,既有前驱,又有后后继
  线性表能逐项访问和顺序读取


1.4 练习

下面关系能用线性表描述的是:
  A、班级中同学的友谊关(N:N)
  B、公司中上下级关系(1:N)
  C、冬天图书馆排队占座关系(1:?)
  D、花名册名字之间的关系(1:1)


1.5 线性表的操作

  创建线性表
  销毁线性表
  清空线性表   将元素插入线性表
  将元素从线性表中删除
  获取线性表在某个位置的元素
  获取线性表的长度

  线性表在程序中表现为一种特殊的数据类型
  线性表的操作在程序在的表现为一组函数
/*C语言描述=====》线性表的设计与实现
ADT抽象层  《[数据结构(C语言版)].严蔚敏_吴伟民.扫描版.pdf》 p44页 
人生财富库积累*/
#ifndef _WBM_LIST_H_
#define _WBM_LIST_H_

typedef void List;
typedef void ListNode;

//创建并且返回一个空的线性表
List* List_Create();

//销毁一个线性表list
void List_Destroy(List* list);

//将一个线性表list中的所有元素清空, 线性表回到创建时的初始状态
void List_Clear(List* list);

//返回一个线性表list中的所有元素个数
int List_Length(List* list);

//向一个线性表list的pos位置处插入新元素node
int List_Insert(List* list, ListNode* node, int pos);  

//获取一个线性表list的pos位置处的元素
ListNode* List_Get(List* list, int pos);

//删除一个线性表list的pos位置处的元素  返回值为被删除的元素,NULL表示删除失败
ListNode* List_Delete(List* list, int pos);

#endif
*/注意:
int List_Insert(List* list, ListNode* node, int pos);  (重点:分离思想) */



2、 线性表的顺序存储结构

2.1 基本概念

在这里插入图片描述

2.2 设计与实习

插入元素算法
  判读线性表是否合法
  判断插入位置是否合法
  把最后一个元素插入到位置元素后移一个位置
  将新元素插入
  线性表长度加+1

获取元素操作
  判断线性表是否合法
  判断位置是否合法
  直接通过数组下标方式获取元素

删除元素算法
  判读线性表是否合法
  判断删除位置是否合法
  将元素取出
  将删除位置后的元素分别向前移动一个位置
  线性表长度加-1



链表顺序存储插入算法和删除算法

在这里插入图片描述

2.3 优点与缺点

优点
  无需为线性表中的逻辑关系增加额外的空间
  可以快速的获取表中合法位置的·元素

缺点
  插入和删除操作需要移动大量元素
  当线性表长度大时难以确定存储空间的容量

2.4 实习代码

实现代码:

//头文件seqlish.h
#ifndef __MY_SEQLIST_H__
#define __MY_SEQLIST_H__

typedef void SeqList;
typedef void SeqListNode;

SeqList* SeqList_Create(int capacity);

void SeqList_Destroy(SeqList* list);

void SeqList_Clear(SeqList* list);

int SeqList_Length(SeqList* list);

int SeqList_Capacity(SeqList* list);

int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);

SeqListNode* SeqList_Get(SeqList* list, int pos);

SeqListNode* SeqList_Delete(SeqList* list, int pos);


#endif // __MY_SEQLIST_H__



//seqlish.c
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include"seqlist.h"

//在结构体套一级指针
//
typedef struct _tag_SeqList
{
	int length;
	int capacity;
	unsigned int* node;

}TSeqList;

SeqList* SeqList_Create(int capacity)
{
	TSeqList* tmp = NULL;
	int ret = 0;

	tmp = (TSeqList*)malloc(sizeof(TSeqList));
	if (tmp == NULL)
	{
		ret = -1;
		printf("func SeqList_Create() err:%d \n", ret);
		return NULL;
	}

	memset(tmp, 0, sizeof(TSeqList));

	//根据capacity分配内存大小
	tmp->node = (SeqListNode*)malloc(sizeof(unsigned int*) * capacity);
	if (tmp->node == NULL)
	{
		ret = -2;
		printf("func SeqList_Create() err:%d \n", ret);
		return NULL;
	}
	tmp->capacity = capacity;
	tmp->length = 0;

	return tmp;
}

void SeqList_Destroy(SeqList* list)
{
	TSeqList* tlist = NULL;
	if (list == NULL)
	{
		return;
	}
	tlist = (TSeqList*)list;
	if (tlist->node != NULL)
	{
		free(tlist->node);
	}
	free(tlist);
	return;
}


//清空链表 //回到初始化状态
void SeqList_Clear(SeqList* list)
{
	TSeqList* tlist = NULL;
	int ret = 0;
	if (list == NULL)
	{
		ret = -1;
		printf("func SeqList_Clear() err:%d \n", ret);
		return;
	}
	tlist = (TSeqList *)list;
	if (tlist->node != NULL)
	{
		free(tlist->node);
	}

	tlist->capacity = 0;
	tlist->length = 0;
	return;
}

int SeqList_Length(SeqList* list)
{
	TSeqList* tlist = NULL;
	
	if (list == NULL)
	{
		return -1;
	}

	tlist = (TSeqList *)list;
	return tlist->length;

}

int SeqList_Capacity(SeqList* list)
{
	TSeqList* tlist = NULL;
	if (list == NULL)
	{
		return -1;
	}
	tlist = (TSeqList*)list;
	return tlist->capacity;
}

int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)
{
	TSeqList* tlist = NULL;
	int ret = 0,i=0;

	if (list == NULL || pos < 0 || node == NULL) 
	{
		ret = -1;
		printf("func SeqList_Insert() err:%d \n", ret);
		return ret;
	}

	tlist = (TSeqList*)list;

	//判断是否满了
	if (tlist->length >= tlist->capacity)
	{
		ret = -2;
		printf("func SeqList_Insert() err(tlist->length >= tlist->length):%d \n", ret);
		return ret;
	}

	//容错修正
	if (tlist->length <  pos)
	{
		pos = tlist->length;
	}

	//pos后元素后移
	for (i = tlist->length; i > pos; i--)
	{
		tlist->node[i] = tlist->node[i - 1];
	}

	//插入元素
	tlist->node[i] = (unsigned int)node;

	tlist->length++;

	return ret;
}

SeqListNode*  SeqList_Get(SeqList* list, int pos)
{
	TSeqList* tlist = NULL;

	SeqListNode* ret = 0;

	if (list == NULL || pos<0)
	{
		printf("func SeqList_Get() err:%d \n", ret);
		return NULL;
	}

	tlist = (TSeqList *)list;

	ret = (SeqListNode *)tlist->node[pos];

	return ret;
}

SeqListNode* SeqList_Delete(SeqList* list, int pos)
{
	TSeqList* tlist = NULL;

	SeqListNode* ret = 0;

	int i = 0;


	if (list == NULL || pos < 0)//检查
	{
		printf("func SeqList_Delete() err:%d \n", ret);
		return NULL;
	}

	tlist = (TSeqList *)list;

	if (pos >= tlist->length)
	{
		printf("func SeqList_Delete() err:%d \n", ret);
		return ret;
	}

	ret = (SeqListNode *)tlist->node[pos];//缓存pos的位置

	for (i = pos+1; i < tlist->length; i++)//pos后面的位置前移
	{
		tlist->node[i-1] = tlist->node[i];
	}

	tlist->length--;

	return ret;
}


//dm02_线性表顺序储存与设计测试框架.c
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include"seqlist.h"

//在结构体套二级指针
//
typedef struct _tag_SeqList
{
	int length;
	int capacity;
	unsigned int** node;

}TSeqList;

SeqList* SeqList_Create(int capacity)
{
	TSeqList* tmp = NULL;
	int ret = 0;

	tmp = (TSeqList*)malloc(sizeof(TSeqList));
	if (tmp == NULL)
	{
		ret = -1;
		printf("func SeqList_Create() err:%d \n", ret);
		return NULL;
	}

	memset(tmp, 0, sizeof(TSeqList));

	//根据capacity分配内存大小
	tmp->node = (SeqListNode*)malloc(sizeof(unsigned int**) * capacity);
	if (tmp->node == NULL)
	{
		ret = -2;
		printf("func SeqList_Create() err:%d \n", ret);
		return NULL;
	}
	tmp->capacity = capacity;
	tmp->length = 0;

	return tmp;
}

void SeqList_Destroy(SeqList* list)
{
	TSeqList* tlist = NULL;
	if (list == NULL)
	{
		return;
	}
	tlist = (TSeqList*)list;
	if (tlist->node != NULL)
	{
		free(tlist->node);
	}
	free(tlist);
	return;
}


//清空链表 //回到初始化状态
void SeqList_Clear(SeqList* list)
{
	TSeqList* tlist = NULL;
	int ret = 0;
	if (list == NULL)
	{
		ret = -1;
		printf("func SeqList_Clear() err:%d \n", ret);
		return;
	}
	tlist = (TSeqList *)list;
	if (tlist->node != NULL)
	{
		free(tlist->node);
	}

	tlist->capacity = 0;
	tlist->length = 0;
	return;
}

int SeqList_Length(SeqList* list)
{
	TSeqList* tlist = NULL;
	
	if (list == NULL)
	{
		return -1;
	}

	tlist = (TSeqList *)list;
	return tlist->length;

}

int SeqList_Capacity(SeqList* list)
{
	TSeqList* tlist = NULL;
	if (list == NULL)
	{
		return -1;
	}
	tlist = (TSeqList*)list;
	return tlist->capacity;
}

int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)
{
	TSeqList* tlist = NULL;
	int ret = 0,i=0;

	if (list == NULL || pos < 0 || node == NULL) 
	{
		ret = -1;
		printf("func SeqList_Insert() err:%d \n", ret);
		return ret;
	}

	tlist = (TSeqList*)list;

	//判断是否满了
	if (tlist->length >= tlist->capacity)
	{
		ret = -2;
		printf("func SeqList_Insert() err(tlist->length >= tlist->length):%d \n", ret);
		return ret;
	}

	//容错修正
	if (tlist->length <  pos)
	{
		pos = tlist->length;
	}

	//pos后元素后移
	for (i = tlist->length; i > pos; i--)
	{
		tlist->node[i] = tlist->node[i - 1];
	}

	//插入元素
	tlist->node[i] = node;

	tlist->length++;

	return ret;
}

SeqListNode*  SeqList_Get(SeqList* list, int pos)
{
	TSeqList* tlist = NULL;

	SeqListNode* ret = 0;

	if (list == NULL || pos<0)
	{
		printf("func SeqList_Get() err:%d \n", ret);
		return NULL;
	}

	tlist = (TSeqList *)list;

	ret = (SeqListNode *)tlist->node[pos];

	return ret;
}

SeqListNode* SeqList_Delete(SeqList* list, int pos)
{
	TSeqList* tlist = NULL;

	SeqListNode* ret = 0;

	int i = 0;


	if (list == NULL || pos < 0)//检查
	{
		printf("func SeqList_Delete() err:%d \n", ret);
		return NULL;
	}

	tlist = (TSeqList *)list;

	if (pos >= tlist->length)
	{
		printf("func SeqList_Delete() err:%d \n", ret);
		return ret;
	}

	ret = (SeqListNode *)tlist->node[pos];//缓存pos的位置

	for (i = pos+1; i < tlist->length; i++)//pos后面的位置前移
	{
		tlist->node[i-1] = tlist->node[i];
	}

	tlist->length--;

	return ret;
}


3、 线性表的链式储存结构

3.1 基本概念

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

在这里插入图片描述

在这里插入图片描述



表头节点
  链表中的第一个节点,指向第一个元素的指针以及链表自身的一些信息
数据节点
  链表中代表数据元素的节点,包含指向下一个数据元素的指针和数据元素的信息
尾节点
  链表中最后一个数据节点,其下一个元素指针为空,表示无后继

3.2 链表技术领域推演

在这里插入图片描述

3.3 设计与实习

链表链式存储_api实现分析

在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 的元素的值,需要怎么做
  ret = current->next;
此问题是:指向节点的指针移动n次 和 第n个元素之间的关系?


删除元素
在这里插入图片描述




重要技术场景图
链表链式存储_插入
在这里插入图片描述


链表链式存储_删除
在这里插入图片描述

3.4 优点与缺点

优点
  无需一次性定制链表的容量
  插入和删除操作无需移动数据

缺点
  数据元素必须保存后继元素的位置信息
  获取指定数据的元素操作需要访问之前的元素

3.5 实现代码

实现代码:

//头文件linklish.h
#ifndef _LINKLIST_H
#define _LINKLIST_H

typedef void LinkList;
/*
typedef struct _tag_LinkListNode;
struct _tag_LinkListNode
{
	LinkListNode* next;
}
*/

typedef struct _tag_LinkListNode
{
	struct _tag_LinkListNode* nxet;
}LinkListNode;


LinkList* LinkList_Create();

void LinkeList_Destroy(LinkList* list);

void LinkList_Clear(LinkList* list);

int LinkList_Length(LinkList* list);

int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);

LinkListNode* LinkList_Get(LinkList* list, int pos);

LinkListNode* LinkList_Delete(LinkList* list, int pos);

#endif



//linklish.c
#include<stdio.h>
#include<Stdlib.h>
#include<string.h>
#include "linklist.h"

typedef struct _tag_LinkList
{
	LinkListNode header;
	int length;
}TLinkList;

LinkList* LinkList_Create()
{
	TLinkList* ret = NULL;

	ret = (TLinkList *)malloc(sizeof(TLinkList));

	if (ret == NULL)
	{
		printf("func LinkList_Create() err:%d\n", ret);
	}

	memset(ret, 0 ,sizeof(TLinkList));

	//可以删去
	ret->length = 0;
	ret->header.nxet = NULL;

	return ret;
}


void LinkeList_Destroy(LinkList* list)
{
	if (list != NULL)
	{
		free(list);

		//可以删去
		list = NULL;
	}

	return;
}

//让链表恢复到初始状态
void LinkList_Clear(LinkList* list)
{

	TLinkList* tlist = NULL;

	if (list == NULL)
	{
		return;
	}

	tlist = (TLinkList*)list;

	tlist->header.nxet = NULL;
	tlist->length = 0;

	return;
}

int LinkList_Length(LinkList* list)
{
	int ret = 0;
	TLinkList* tlist = NULL;

	if(list == NULL)
	{
		ret = -1;
		printf("func LinkList_Length() err:%d \n", ret);
		return ret;
	}

	tlist = (TLinkList*)list;

	ret = tlist->length;

	return ret;
}

int LinkList_Insert(LinkList* list, LinkListNode* node, int pos)
{
	int i = 0, ret = 0;
	LinkListNode* current = NULL;
	TLinkList* tlist = NULL;

	if (list == NULL || pos < 0 || node == NULL)
	{
		ret = -1;
		printf("func LinkList_Insert() err:%d \n", ret);
		return ret;
	}

	tlist = (TLinkList*)list;

	if (tlist->length < pos)
	{
		ret = -2;
		printf("func LinkList_Insert() err:%d \n", ret);
		return ret;
	}

	current = &(tlist->header);

	for (i = 0; i < pos && (current->nxet!=NULL); i++)
	{
		current = current->nxet;
	}
	
	//1 然后node接续链表
	node->nxet = current->nxet;
	//2 让前面的链表 连接新的node节点
	current->nxet = node;
	
	tlist->length++;

	return ret;
}

LinkListNode* LinkList_Get(LinkList* list, int pos)
{
	TLinkList* tlist = NULL;
	LinkListNode* current = NULL;
	int i = 0,ret=0;

	if (list == NULL||pos<0)
	{
		printf("func LinkList_Get() err:%d \n", ret);
		return NULL;
	}

	tlist = (TLinkList*)list;
	current = &(tlist->header);//让辅助指针指向表的头部
	
	for (i = 0; i < pos && (current->nxet !=NULL) ; i++)//跳pos次
	{
		current = current->nxet;
	}

	return current->nxet;
}

LinkListNode* LinkList_Delete(LinkList* list, int pos)
{
	int i = 0;
	LinkListNode* current = NULL;
	LinkListNode* ret = NULL;

	TLinkList* tlist = NULL;
	if (list == NULL || pos < 0)
	{
		printf("func LinkList_Delete() err:%d \n", ret);
		return NULL;
	}

	tlist = (TLinkList*)list;
	current = &(tlist->header);//让辅助指针变量指向链表的头部

	for (i = 0; i < pos && (current->nxet!=NULL); i++)//跳pos次
	{
		current = current->nxet;
	}

	//缓存被删除的节点
	ret = current->nxet; 

	//连线
	current->nxet = ret->nxet;

	tlist->length--;

	return ret;
}


//线性表链式存储集成测试.c
#include<stdio.h>
#include<Stdlib.h>
#include<string.h>
#include "linklist.h"


typedef	struct Teacher
{
	LinkListNode node;//第一个域(第一个元素)
	int age;
	char name[64];
}Teacher;

void main() 
{
	int ret = 0, len = 0;

	LinkList* list = NULL;

	Teacher t1, t2, t3, t4, t5;
	t1.age = 31;
	t2.age = 32;
	t3.age = 33;
	t4.age = 34;
	t5.age = 35;

	
	list = LinkList_Create();
	if (list== NULL)
	{
		return;
	}

	len = LinkList_Length(list);

	//链表的算法和具体业务节点的分离
	ret = LinkList_Insert(list, (LinkListNode*)(&t1) , 0);
	ret = LinkList_Insert(list, (LinkListNode*)(&t2), 0);
	ret = LinkList_Insert(list, (LinkListNode*)(&t3), 0);
	ret = LinkList_Insert(list, (LinkListNode*)(&t4), 0);
	ret = LinkList_Insert(list, (LinkListNode*)(&t5), 0);

	//遍历
	for (int i = 0; i < LinkList_Length(list); i++)
	{
		Teacher* tmp = LinkList_Get(list, i);
		if (tmp == NULL)
		{
			return;
		}
		printf("tmp->age:%d \n", tmp->age);
	}

	//删除链表
	while (LinkList_Length(list) > 0)
	{
		LinkList_Delete(list, 0);
	}

	LinkeList_Destroy(list);

	system("pause");
	return ;
}


4、 循环链表

4.1 基本概念

4.2 设计与实习

4.3 优点与缺点



5、 双向链表

5.1 基本概念

5.2 设计与实习

5.3 优点与缺点



标签:NULL,线性表,int,SeqList,list,ret,完成,tlist,数据结构
来源: https://blog.csdn.net/weixin_52804129/article/details/120388443

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有