動態順序表

動態順序表將順序表進行動態存儲

在這裏我們在堆上創建一段空間(堆上的空間便於擴充,因爲堆上的空間是我們自己進行動態管理的)

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++;
}

總結:相對於靜態順序表來說,動態順序表對空間的管理相對就靈活些

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章