数据结构 列表和链表
文章目录
前言
队列初学之后,我在回顾下之前的顺序表,链表之类的各种概念及其实现
提示:以下是本篇文章正文内容,下面案例可供参考
一,表的概念
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!!!!