動態順序表將順序表進行動態存儲
在這裏我們在堆上創建一段空間(堆上的空間便於擴充,因爲堆上的空間是我們自己進行動態管理的)
typedef int DataType;
typedef struct SeqListDynamic
{
DataType *arr;//指向堆上那段空間的指針
int capicity;//總容量大小
int size;//有效數據個數
}SeqListD;
動態順序表中,我們實現了以下基本操作
//動態順序表的初始化
void SeqListDInit(SeqListD *psld);
//動態順序表的銷燬
void SeqListDDestory(SeqListD *psld);
//動態順序表的打印
void SeqListDPrint(SeqListD *psld);
//動態順序表的插入:尾插、頭插、插入指定位置
void SeqListDPushBack(SeqListD *psld, DataType data);
void SeqListDPushFront(SeqListD *psld, DataType data);
void SeqListDInsert(SeqListD *psld, int pos, DataType data);
1)初始化
void SeqListDInit(SeqListD *psld)
{
assert(psld != NULL);
//開始我們默認在堆上將申請兩個數據那麼大的空間
psld->capicity = 2;
//將申請好的空間用arr去指向
psld->arr = (DataType *)malloc(psld->capicity * sizeof(DataType));
//malloc申請空間會有申請失敗的時候,因此一定要對申請的空間進行判空
assert(psld->arr);
//初始化時有效數據的個數應該爲0
psld->size = 0;
}
2)銷燬
void SeqListDDestory(SeqListD *psld)
{
assert(psld != NULL);
psld->size = 0;
psld->capicity = 0;
//堆上的空間使我們向操作系統借的
//一旦我們使用完畢一定要記得歸還給操作系統,否則會出現內存泄漏的問題
free(psld->arr);
//free掉這段空間之後arr變成了一個野指針,爲此我們最好將該指針指向空
psld->arr = NULL;
}
3)打印
void SeqListDPrint(SeqListD *psld)
{
assert(psld != NULL);
for (int i = 0; i < psld->size; i++)
{
printf("%d->", psld->arr[i]);
}
printf("NULL\n");
}
4)插入
//在此我們寫一個函數來應對空間不足時對空間的擴充
void ExpandIfRequired(SeqListD *psld)
{
assert(psld != NULL);
//當有效元素的個數小於當前容量的時候就不需要擴充直接返回
if (psld->size < psld->capicity)
{
return;
}
//我們使用夥伴算法來進行擴充容量
//當空間不足時我們就將空間擴充到原來的2倍
psld->capicity *= 2;
DataType *newArray = (DataType *)malloc(psld->capicity * sizeof(DataType));
assert(newArray != NULL);
//當新的大空間申請成功之後就需要將原來的數據都搬移到新空間中
for (int i = 0; i < psld->size; i++)
{
newArray[i] = psld->arr[i];
}
//此時原來的空間已經沒有用了,將該空間歸還給操作系統
free(psld->arr);
//把我們整理好的新空間給arr就行啦
psld->arr = newArray;
}
void SeqListDPushBack(SeqListD *psld, DataType data)
{
assert(psld != NULL);
//插入之前得先判斷當前是否需要擴充容量
ExpandIfRequired(psld);
//將數據放入空間中
psld->arr[psld->size] = data;
//有效元素個數加1
psld->size++;
}
void SeqListDPushFront(SeqListD *psld, DataType data)
{
assert(psld != NULL);
ExpandIfRequired(psld);
int i = psld->size;
//將當前元素均向後移動一個單位,留下第一個空間進行頭插
for (; i > 0; i--)
{
//當然記得從後往前搬移數據,否則會將數據覆蓋
psld->arr[i] = psld->arr[i - 1];
}
psld->arr[i] = data;
psld->size++;
}
void SeqListDInsert(SeqListD *psld, int pos, DataType data)
{
assert(psld != NULL);
ExpandIfRequired(psld);
int i = psld->size;
//將指定位置之後的元素均向後搬移一個單位,騰出指定位置的空間進行插入數據
for (; i > pos; i--)
{
psld->arr[i] = psld->arr[i - 1];
}
psld->arr[i] = data;
psld->size++;
}
總結:相對於靜態順序表來說,動態順序表對空間的管理相對就靈活些