1,顺序表的实质就是数组,但要求数据必须是连续存放的。
2,顺序表的物理结构与逻辑结构是统一的,简单地说,就是逻辑上连续的两个数据,
他们在物理空间上也是连续的,也就是内存空间是连续的。
内存开辟如下图所示:
下面我们主要介绍一下动态的顺序表,因为静态的顺序表不太灵活,一旦开辟好空间就不太好调整。
#pragma once
#include
#include
#includetypedef int SLDateType;typedef struct SeqList
{SLDateType* a;int size;int capcity;
}SeqList;
//初始化顺序表
void SLInit(SeqList* ps);
//销毁顺序表
void SLDestory(SeqList* ps);
//打印顺序表
void SLPrint(SeqList* ps);
//检查空间
void SLCheckCapcity(SeqList* ps);
//尾插 尾删
void SLPushBack(SeqList* ps, SLDateType x);
void SLPopBack(SeqList* ps);
//头插 头删
void SLPushFront(SeqList* ps, SLDateType x);
void SLPopFront(SeqList* ps);
//任意位置插入 删除
void SLInsert(SeqList* ps, int pos, SLDateType x);
void SLErase(SeqList* ps, int pos);
//查找
int SLFind(SeqList* ps, SLDateType x, int begin);
void SLInit(SeqList* ps)
{assert(ps);ps->a = NULL;ps->capcity = 0;ps->size = 0;
}
我在初始化的时候没有给顺序表开辟空间,当然你可以为其开辟一部分空间。
将其capcity赋值为0;
size(数据个数)赋值为0;
void SLDestory(SeqList* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->capcity = 0;ps->size = 0;
}
将开辟的空间释放掉。
void SLPrint(SeqList* ps)
{assert(ps);for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}
我们在插入数据之前都要先判断一下表是否还有空间,以防越界错误。
void SLCheckCapcity(SeqList* ps)
{assert(ps);if (ps->size == ps->capcity){int newcapcity = ps->a == NULL ? 4 : 2 * ps->capcity;SLDateType* tmp = realloc(ps->a, newcapcity * sizeof(SLDateType));if (tmp == NULL){perror("malloc fail");exit(-1);}ps->a = tmp;ps->capcity = newcapcity;}
}
void SLPushBack(SeqList* ps, SLDateType x)
{assert(ps);SLCheckCapcity(ps);ps->a[ps->size] = x;ps->size++;
}
插入之前先检查顺序表是否有多余空间。
void SLPopBack(SeqList* ps)
{assert(ps);assert(ps->size > 0);ps->size--;
}
void SLPushFront(SeqList* ps, SLDateType x)
{assert(ps);SLCheckCapcity(ps);int end = ps->size - 1;while (end >= 0){ps->a[end + 1] = ps->a[end];end--;}ps->a[0] = x;ps->size++;
}
void SLPopFront(SeqList* ps)
{assert(ps);assert(ps->size > 0);int begin = 1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;
}
void SLInsert(SeqList* ps, int pos, SLDateType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckCapcity(ps);int end = ps->size - 1;while (end >= pos){ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = x;ps->size++;
}
我们发现任意位置的插入包括了头插与尾插,所以可以改变一下之前的代码
头插
void SLPushFront(SeqList* ps, SLDateType x)
{/*assert(ps);SLCheckCapcity(ps);int end = ps->size - 1;while (end >= 0){ps->a[end + 1] = ps->a[end];end--;}ps->a[0] = x;ps->size++;*/SLInsert(ps, 0, x);
}
尾插
void SLPushBack(SeqList* ps, SLDateType x)
{/*assert(ps);SLCheckCapcity(ps);ps->a[ps->size] = x;ps->size++;*/SLInsert(ps, ps->size, x);
}
void SLErase(SeqList* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);assert(ps->size > 0);int begin = pos + 1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;
}
同样之前头删,尾删的代码就可以更改:
头删
void SLPopFront(SeqList* ps)
{/*assert(ps);assert(ps->size > 0);int begin = 1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;*/SLErase(ps, 0);
}
尾删
void SLPopBack(SeqList* ps)
{/*assert(ps);assert(ps->size > 0);ps->size--;*/SLErase(ps, ps->size - 1);
}
int SLFind(SeqList* ps, SLDateType x, int begin)
{assert(ps);assert(begin >= 0);for (int i = begin; i < ps->size; i++){if (ps->a[i] == x){return i;}}return -1;
}
链表与上述的顺序表有3个巨大的不同:
1,链表的逻辑结构与物理结构不统一(相邻数据的内存空间并不连续)
2,不存在空间满了的情况,插入新的数据就新开辟一个结点连接到链表上
3,插入删除数据不用数据,只是改变结点的连接方式即可
一般我们通常这样理解:
但实际的结构是这样的:
上一个结点的指针域存放着下一结点的地址,在内存中是上图那样存储的。
typedef int SLTDateType;typedef struct SListNode
{SLTDateType data;struct SListNode* next;
}SListNode;
//创建一个结点
SListNode* BuySListNode(SLTDateType x);
//打印链表
void SLTPrint(SListNode* phead);
//销毁链表
void SLTDestory(SListNode** pphead);
//尾插 尾删
void SLTPushBack(SListNode** pphead, SLTDateType x);
void SLTPopBack(SListNode** pphead);
//头插 头删
void SLTPushFront(SListNode** pphead, SLTDateType x);
void SLTPopFront(SListNode** pphead);
//查找
SListNode* SLTFind(SListNode* phead, SLTDateType x);void SLTInsertAfter(SListNode* pos, SLTDateType x);
void SLTEraseAfter(SListNode* pos);void SLTInsert(SListNode** pphead, SListNode* pos, SLTDateType x);
void SLTErase(SListNode** pphead, SListNode* pos);
SListNode* BuySListNode(SLTDateType x)
{SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));if (newnode == NULL){perror("malloc fail");exit(-1);}newnode->data = x;newnode->next = NULL;return newnode;
}
void SLTDestory(SListNode** pphead)
{assert(*pphead);SListNode* cur = *pphead;SListNode* next = NULL;while (cur){next = cur->next;free(cur);cur = next;}*pphead = NULL;
}
void SLTPrint(SListNode* phead)
{SListNode* cur = phead;while (phead){printf("%d->", cur->data);cur = cur->next;}printf("NULL");
}
void SLTPushBack(SListNode** pphead, SLTDateType x)
{SListNode* newnode = BuySListNode(x);if (*pphead == NULL){*pphead = newnode;}else{SListNode* ptail = *pphead;while (ptail->next){ptail = ptail->next;}ptail->next = newnode;}
}
void SLTPopBack(SListNode** pphead)
{assert(*pphead);if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{SListNode* cur = *pphead;while (cur->next->next){cur = cur->next;}cur->next = NULL;}
}
void SLTPushFront(SListNode** pphead, SLTDateType x)
{SListNode* newnode = BuySListNode(x);newnode->next = (*pphead)->next;*pphead = newnode;
}
void SLTPopFront(SListNode** pphead)
{assert(*pphead);SListNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}
void SLTInsertAfter(SListNode* pos, SLTDateType x)
{assert(pos);SListNode* newnode = BuySListNode(x);newnode->next = pos->next;pos->next = newnode;
}
void SLTEraseAfter(SListNode* pos)
{assert(pos);if (pos->next != NULL){SListNode* next = pos->next->next;free(pos->next);pos->next = next;}
}
SListNode* SLTFind(SListNode* phead, SLTDateType x)
{SListNode* cur = phead;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}
void SLTInsert(SListNode** pphead, SListNode* pos, SLTDateType x)
{SListNode* newnode = BuySListNode(x);if (pos == *pphead){newnode->next = (*pphead)->next;*pphead = newnode;}else{assert(pos);SListNode* cur = *pphead;while (cur->next != pos){cur = cur->next;}newnode->next = pos;cur->next = newnode;}
}
void SLTErase(SListNode** pphead, SListNode* pos)
{if (pos == *pphead){free(pos);*pphead = NULL;}else{SListNode* cur = *pphead;while (cur->next != pos){cur = cur->next;}SListNode* next = pos->next;free(pos);cur->next = next;}
}