數據結構之線性表的順序存儲結構實現
1 定義
- 線性表(List,鏈表):零個或多個數據元素的有限序列
元素之間是有順序的,若存在多個元素,則第一個元素無前驅,最後一個元素無後繼,其他每個元素都有且只有一個前驅和後繼。 - 線性表的順序存儲是指在內存中用地址連續的一塊存儲空間順序存放線性表的各元素。可以使用一維數組來實現順序存儲結構。
2 數據結構及操作
2.1 數據結構
typedef struct _tag_SeqList
{
int capacity;
int length;
unsigned int * node;
}TSeqList;
這裏使用 typedef void SeqListNode 即:void 類型作爲數據節點,可以存儲任意類型的數據元素。
順序存儲的三個屬性:
- 存儲空間:node
- 鏈表的最大容量:capacity
- 鏈表的當前長度:length
2.2 操作
/*
* seqList.h
*/
#ifndef __MY_SEQLIST_H
#define __MY_SEQLIST_H
typedef void SeqList;
typedef void SeqListNode;
SeqList* SeqList_Create(int capacity);
void SeqList_Destroy(SeqList* list);
void SeqList_Claer(SeqList* list);
int SeqList_length(SeqList* list);
int SeqList_Capacity(SeqList* list);
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);
SeqListNode* SeqList_Get(SeqList* list, int pos);
SeqListNode* SeqList_Delete(SeqList* list, int pos);
#endif // __MY_SEQLIST_H
3 主要操作實現
3.1 創建一個新鏈表
SeqList* SeqList_Create(int capacity)
{
int ret = 0;
TSeqList* tmp = NULL;
tmp = (TSeqList *)malloc(sizeof(TSeqList));
if(tmp == NULL)
{
ret = -1;
printf("func SeqList_Create() err: %d\n", ret);
return NULL;
}
tmp->node = (unsigned int *)malloc(sizeof(unsigned int *) * capacity);
if(tmp->node == NULL)
{
ret = -2;
printf("func SeqList_Create malloc err: %d\n", ret);
return NULL;
}
tmp->length = 0;
tmp->capacity = capacity;
return tmp;
}
3.2 銷燬
//銷燬鏈表
void SeqList_Destroy(SeqList* list)
{
TSeqList * tlist = NULL;
if(list == NULL)
{
return;
}
tlist = (TSeqList *)list;
if(tlist->node != NULL)
{
free(tlist->node);
}
free(tlist);
return;
}
3.3 插入操作
在鏈表 list 的第 pos 位置,插入元素node。
操作:
1)判斷list,node,pos的合法性。
2)如果鏈表已滿,返回。
3)從最後一個元素開始向前遍歷到第pos個位置,分別將他們都向後移動一個位置。
4)將要插入元素填入位置pos處。
5)表長加1。
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)
{
int ret = 0, i = 0;
TSeqList *tlist = NULL;
if(list == NULL || node == NULL || pos < 0)
{
ret = -1;
printf("func SeqList_Insert err:%d\n", ret);
return -1;
}
tlist = (TSeqList *)list;
//鏈表已滿
if(tlist->length == tlist->capacity)
{
ret = -2;
printf("func SeqList_Insert err:%d\n", ret);
return -1;
}
//容錯修正 如果鏈表已有6個元素, 容量爲20, 用戶在pos=10處插入
if(pos > tlist->length)
{
pos = tlist->length;
}
for(i = tlist->length; i > pos; i--)
{
tlist->node[i] = tlist->node[i - 1];
}
tlist->node[pos] = node;
tlist->length++;
return 0;
}
3.4 獲取元素操作
注意:下標從0開始計算,即第一個元素在第0個位置。
SeqListNode* SeqList_Get(SeqList* list, int pos)
{
int ret = 0;
TSeqList *tlist = NULL;
if(list == NULL || pos < 0)
{
ret = -1;
printf("func SeqList_Get err:%d\n", ret);
return NULL;
}
tlist = (TSeqList *)list;
return tlist->node[pos];
}
3.5 刪除操作
刪除鏈表list第pos個位置的元素,並返回其元素。
操作:
1)判斷合法性。
2)取出元素。
3)從第pos個位置開始遍歷到最後一個元素位置,並分別將它們都向前移動一個位置。
4)表長減1.
SeqListNode* SeqList_Delete(SeqList* list, int pos)
{
int ret = 0, i = 0;
TSeqList *tlist = NULL;
if(list == NULL || pos < 0)
{
ret = -1;
printf("func SeqList_Delete err:%d\n", ret);
return NULL;
}
tlist = (TSeqList *)list;
SeqListNode *tmp = (SeqListNode *)tlist->node[pos];
for(i = pos+1; i < tlist->length; i++)
{
tlist->node[i-1] = tlist->node[i];
}
tlist->length--;
return tmp;
}
3.6 測試
/*
* seqlistTest.cpp
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "seqList.h"
typedef struct _Teacher
{
int age;
char name[64];
}Teacher;
int main()
{
int ret = 0, i = 0;
Teacher t1, t2, t3, t4, t5;
t1.age = 31;
t2.age = 32;
t3.age = 33;
t4.age = 34;
t5.age = 35;
SeqList* list = SeqList_Create(10);
if(list == NULL)
{
printf("func SeqLisat_Create() ret :%d\n", ret);
return;
}
//插入節點
ret = SeqList_Insert(list, (SeqListNode*)&t1, 0); //頭插法
ret = SeqList_Insert(list, (SeqListNode*)&t2, 0);
ret = SeqList_Insert(list, (SeqListNode*)&t3, 0);
ret = SeqList_Insert(list, (SeqListNode*)&t4, 0);
ret = SeqList_Insert(list, (SeqListNode*)&t5, 0);
//遍歷
for(i = 0; i < SeqList_length(list); i++)
{
Teacher* tmp = SeqList_Get(list, i);
printf("tmp->age:%d ", tmp->age);
}
//刪除節點
while(SeqList_length(list) > 0)
{
SeqList_Delete(list, 0);
}
system("pause");
return 0;
}
3.7 線性表順序存儲的優缺點
優點:
- 無須爲表示表中元素之間的邏輯關係額增加額外的存儲空間。
- 可以快速地存取表中任一位置的元素
缺點:
- 插入和刪除操作需要移動大量元素
- 當線性表長度變化較大時,難以確定存儲空間的容量
- 造成存儲空間的碎片