顺序表和链表
线性表
线性表是n个具有相同特性的数据元素有限序列。线性表是一种在实际中广泛使用的数据结构。
常见的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构,也就是说连续的一条直线。但是正在物理结构上并不一样是连续的,线性表在物理上存储时,通常以数组和链式结构形式存储。
1. 顺序表
概念及结构
顺序表是用一段 物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表一般可以分为:
静态顺序表:使用定长数组存储
动态顺序表:使用动态开辟的数组存储
//顺序表的静态存储 typedef struct SeqList { int array[100];//定长数组 unsigned int size; } seqlist; //顺序表的动态存储 typedef struct SeqList { int *array; //动态开辟的数组 unsigned int size; //有效数据个数 unsigned int capicity; //容量空间大小 }
这里的顺序表我用的是静态存储法
接口实现
#include "SeqList.h"
#include <assert.h>
#include <stdlib.h>
void SeqListInit(SeqList *seqlist)
{
seqlist->array = (SDataType *)malloc(sizeof(SeqList) * CAP);
if (!seqlist)
{
printf("malloc error!\n");
exit(EXIT_FAILURE);
}
seqlist->cap = CAP;
seqlist->size = 0;
}
void SeqListDestory(SDataType *array)
{
assert(array);
free(array);
array = NULL;
}
void IncreaseCapacity(SeqList *seqlist)
{
assert(seqlist);
//调用此函数的时候应确定要扩容
seqlist = realloc(seqlist, sizeof(SeqList) * (2 * seqlist->cap));
if (!seqlist)
{
printf("realloc error\n");
exit(EXIT_FAILURE);
}
seqlist->cap *= 2;
}
void SeqListPushFornt(SeqList *seqlist, SDataType x)
{
assert(seqlist);
if (!seqlist->size)
{
seqlist->array[0] = x;
seqlist->size++;
return;
}
if (seqlist->size == seqlist->cap)
{
IncreaseCapacity(seqlist);
}
//i表示空间下标
//将所有数据向后移一位
for (int i = seqlist->size; i > 0; i--)
{
seqlist->array[i] = seqlist->array[i - 1];
}
seqlist->array[0] = x;
seqlist->size++;
}
void SeqListPushBack(SeqList *seqlist, SDataType x)
{
assert(seqlist);
if (seqlist->size == seqlist->cap)
{
IncreaseCapacity(seqlist);
}
seqlist->array[seqlist->size] = x;
seqlist->size++;
}
void SeqListInsert(SeqList *seqlist, SDataType x, size_t pos)
{
assert(seqlist);
if (seqlist->size == seqlist->cap)
{
IncreaseCapacity(seqlist);
}
//i表示空间下标
//将pos以及之后的所有数据将后移一位
for (size_t i = seqlist->size; i > pos; i--)
{
seqlist->array[i] = seqlist->array[i - 1];
}
seqlist->array[pos] = x;
seqlist->size++;
}
void SeqListPopFront(SeqList *seqlist)
{
assert(seqlist);
assert(seqlist->array);
//i表示空间下标
for (int i = 0; i < seqlist->size - 1; i++)
{
seqlist->array[i] = seqlist->array[i + 1];
}
seqlist->size--;
}
void SeqListPopBack(SeqList *seqlist)
{
assert(seqlist);
assert(seqlist->array);
seqlist->size--;
}
void SeqListErase(SeqList *seqlist, size_t pos)
{
assert(seqlist);
assert(seqlist->array);
//i表示空间下标
for (int i = pos; i < seqlist->size - 1; i++)
{
seqlist->array[i] = seqlist->array[i + 1];
}
seqlist->size--;
}
void SeqListRemove(SeqList *seqlist, SDataType x)
{
assert(seqlist);
assert(seqlist->array);
for (int i = 0; i < seqlist->size; i++)
{
if (x == seqlist->array[i])
{
SeqListErase(seqlist, i);
return;
}
}
}
void SeqListRemoveAll(SeqList *seqlist, SDataType x)
{
assert(seqlist);
assert(seqlist->array);
//创建一个新的内存块用来存放不是x元素的数据
SeqList *new_seqlist = NULL;
new_seqlist = (SeqList *)malloc(sizeof(SeqList));
if (!new_seqlist)
{
printf("malloc new_seqlist error\n");
exit(EXIT_FAILURE);
}
new_seqlist->array = (SDataType *)malloc(sizeof(SeqList) * seqlist->cap);
if (!new_seqlist->array)
{
printf("malloc array error\n");
exit(EXIT_FAILURE);
}
int index = 0;
int size = seqlist->size;
//将所有不是x数据的元素搬到另一个新的内存块中
for (int i = 0; i < size; i++)
{
if (x != seqlist->array[i])
{
new_seqlist->array[index] = seqlist->array[i];
index++;
}
else
seqlist->size--;
}
SeqListDestory(seqlist->array);
seqlist->array = new_seqlist->array;
}
int SeqListFind(SeqList *seqlist, SDataType x)
{
assert(seqlist);
assert(seqlist->array);
for (int i = 0; i < seqlist->size; i++)
{
if (x == seqlist->array[i])
return i;
}
//走到这里说明没找到
return -1;
}
//二分法查找
//要求:时间复杂度:O(N);空间复杂度O(1)
int SeqListBinaryFind(SeqList *seqlist, SDataType x)
{
assert(seqlist);
assert(seqlist->array);
//left和right都代表数据下标
int left = 0;
int right = seqlist->size - 1;
while (left <= right)
{
int mid = (left + right) / 2;
if (seqlist->array[mid] == x)
return mid;
else if (seqlist->array[mid] > x)
right = mid - 1;
else
left = mid + 1;
}
//如果走到这里说明没有找到
return -1;
}
void SeqListModify(SeqList *seqlist, SDataType x, size_t pos)
{
assert(seqlist);
assert(seqlist->array);
assert(pos >= 0 && pos < (size_t)seqlist->size);
seqlist->array[pos] = x;
}
void SeqListPrint(SeqList *seqlist)
{
assert(seqlist);
assert(seqlist->array);
for (int i = 0; i < seqlist->size; i++)
printf("%d ", seqlist->array[i]);
printf("\n");
}
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
void SeqListBubbleSort(SeqList *seqlist)
{
assert(seqlist);
assert(seqlist->array);
for (int end = seqlist->size - 1; end > 0; end--)
{
int index = 1;
for (int i = 0; i < end; i++)
{
if (seqlist->array[i] > seqlist->array[i + 1])
{
swap(seqlist->array + i, seqlist->array + i + 1);
index = 0;
}
}
if (1 == index)
break;
}
}
2.链表
链表的概念及结构
链表是一种 物理存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针连接次序实现的。
实际中链表的结构非常多样
- 单向。双向
- 带头、不带头
- 循环、非循环
在这里分别用了单向不带头和双向带头的链表完成了对链表的各个接口的实现
单向不带头结构
#include "SList.h"
#include <assert.h>
#include <stdlib.h>
void SListInit(SList **first)
{
assert(first);
*first = NULL;
}
void SListDestory(SList **first)
{
assert(first);
SList *next = NULL;
while (first)
{
next = (*first)->next;
free((*first));
(*first) = next;
}
first = NULL;
}
SList *BuySlistNode(SLTDataType value)
{
SList *node = (SList *)malloc(sizeof(SList));
if (!node)
{
printf("Malloc Node Error!\n");
exit(EXIT_FAILURE);
}
node->value = value;
node->next = NULL;
return node;
}
void SListPushFront(SList **first, SLTDataType value)
{
SList *node = BuySlistNode(value);
if (!(*first))
{
(*first) = node;
return;
}
node->next = (*first);
(*first) = node;
}
void SListPushBack(SList **first, SLTDataType value)
{
assert((*first) != NULL);
SList *end = *first;
//找到最后一个结点
while (end->next)
{
end = end->next;
}
SList *node = BuySlistNode(value);
end->next = node;
}
void SListPopFront(SList **first)
{
assert((*first));
SList *old_first = (*first);//创建一个结点来存储将要删除的结点
(*first) = (*first)->next;
free(old_first);
old_first = NULL;
}
void SListPopBack(SList **first)
{
assert(first);
SList *LBO = *first;
//找到倒数第二个结点
while (LBO->next->next)
{
LBO = LBO->next;
}
SList *old_node = LBO->next;
LBO->next = NULL;
free(old_node);
old_node = NULL;
}
void SListRemove(SList **first, SLTDataType value)
{
assert(first);
//如果第一个值就是要找的值,调用头删直接删
if (value == (*first)->value)
{
SListPopFront(first);
return;
}
SList *target = *first;
while (target->next)
{
if (value == target->next->value)
{
SListPopFront(&target->next);
return;
}
target = target->next;
}
}
void SListPrint(SList **first)
{
assert(first);
SList *node = *first;
while (node)
{
printf("%d ", node->value);
node = node->next;
}
printf("\n");
}
SList *SListFind(SList **first, SLTDataType value)
{
assert(first);
assert(*first);
SList *finder = *first;
while (finder)
{
if (finder->value == value)
return finder;
finder = finder->next;
}
return NULL;
}
void SListInsertAfter(SList **pos, SLTDataType value)
{
assert(pos);
assert(*pos);
SList *loc = *pos;
SList *node = BuySlistNode(value);
node->next = loc->next;
loc->next = node;
}
双向带头结构
#include "DList.h"
static DListNode *DListBuyNode(DLDataType value)
{
DListNode *node = (DListNode *)malloc(sizeof(DListNode));
if (!node)
{
exit(EXIT_FAILURE);
}
node->value = value;
node->prev = NULL;
node->next = NULL;
return node;
}
void DListInit(DList *dlist)
{
dlist->head = DListBuyNode(0);//这里的0没有任何意义
dlist->head->prev = dlist->head;
dlist->head->next = dlist->head;
}
//这里将除头结点外其他结点全部free
void DListClear(DList *dlist)
{
DListNode *cur = dlist->head->next;
DListNode *next = NULL;
//将head后的所有结点全部free
while (cur != dlist->head)
{
next = cur->next;
free(cur);
cur = next;
}
//改为初始状态头结点的next和prev都等于自身
dlist->head->next = dlist->head;
dlist->head->prev = dlist->head;
}
//这里是将所有结点都销毁包括头结点
void DListDestory(DList *dlist)
{
DListClear(dlist);
free(dlist->head);
dlist->head = NULL;
}
void DListPushFront(DList *dlist, DLDataType value)
{
DListNode *node = DListBuyNode(value);
node->next = dlist->head->next;
node->prev = dlist->head;
dlist->head->next->prev = node;
dlist->head->next = node;
}
void DListPushBack(DList *dlist, DLDataType value)
{
DListNode *node = DListBuyNode(value);
DListNode *cur = dlist->head->prev;//定义一个cur结点指针来指向最后一个结点
node->next = cur->next;
node->prev = cur;
cur->next = node;
dlist->head->prev = node;
}
void DListInsertFront(DListNode *pos, DLDataType value)
{
DListNode *node = DListBuyNode(value);
node->next = pos;
node->prev = pos->prev;
pos->prev->next = node;
pos->prev = node;
}
void DListInsertBack(DListNode *pos, DLDataType value)
{
DListNode *node = DListBuyNode(value);
node->next = pos->next;
node->prev = pos;
pos->next->prev = node;
pos->next = node;
}
void DListPrint(DList *dlist)
{
if (dlist->head->prev == dlist->head)
{
printf("NULL\n");
return;
}
DListNode *cur = dlist->head->next;
while (cur != dlist->head)
{
printf("%d-->", cur->value);
cur = cur->next;
}
printf("head\n");
}
DListNode *DListSearch(DList *dlist, DLDataType value)
{
DListNode *cur = dlist->head->next;
while (cur->next != dlist->head)
{
if (cur->value == value)
return cur;
cur = cur->next;
}
//走到这说明没找到
return NULL;
}
void DListPopFront(DList *dlist)
{
DListNode *cur = dlist->head->next;
dlist->head->next->next->prev = dlist->head;
dlist->head->next = dlist->head->next->next;
free(cur);
cur = NULL;
}
void DListPopBack(DList *dlist)
{
DListNode *cur = dlist->head->prev;
dlist->head->prev->prev->next = dlist->head;
dlist->head->prev = dlist->head->prev->prev;
free(cur);
cur = NULL;
}
void DListEreasePos(DListNode *pos)
{
DListNode *cur = pos->next;
pos->next->next->prev = pos;
pos->next = pos->next->next;
free(cur);
cur = NULL;
}
void DListRemoveAll(DList *dlist, DLDataType value)
{
DListNode *cur = dlist->head;
while (cur->next != dlist->head)
{
cur = cur->next;
if (cur->next->value == value)
DListEreasePos(cur);
}
}