線性表的順序表示和實現(順序表)
順序表:採用順序儲存結構的線性表稱為順序表
1.順序表的儲存結構
#順序表是線性表的順序儲存表示法,其資料元素用一段連續的地址空間,類似陣列,其特點為邏輯上相鄰,物理次序也是相鄰的。
#假設順序表中每個元素佔用l個儲存單元,並且第一個元素所佔地址為儲存單元的基地址,線性表中第i+1個元素的儲存位置LOC(ai+1)和第i個元素的儲存位置LOC(ai)有以下關係
LOC(ai+1)=LOC(ai)+l
LOC(ai+1)=LOC(a1)+(i-1)*l
#define MAXSIZE 100 //儲存空間分配大小
typedef int ElemType; //給int起別名ElemType
typedef struct
{
ElemType *elem; //儲存空間基地址,首地址.可以理解為順序表為一“動態陣列”,指標變數elem指向陣列的首地址。
int length; //當前長度,用於統計順序表的長度,元素個數。
}SqList;
Tip:①這裡的SqList,相當於給該自定義結構類取了一個別名,定義該自定義型別變數時就可像這樣SqList List;
2.順序表的基本操作與實現
2.1.順序表的初始化 int InitList(SqList *L)
演算法步驟:①為順序表List分配一個預定義大小的陣列空間,elem指向這段空間的基地址。
②分配空間成功,將當前表長設定為0(未插入資料,表長為0);
//1.初始化順序線性表
int InitList(SqList *L)
{
(*L).elem=(ElemType*)malloc(MAXSIZE*sizeof(ElemType));//分配儲存空間
if(!(*L).elem)
{
printf("\n分配空間失敗!!!");
return -1;//空間分配失敗
}
(*L).length=0;//空表長度設定為0
printf("\n分配空間成功!!!");
return 0;
}
Tip:①該順序表初始化函式所傳的引數為指標型別,需建立個指標變數L指向List(上面的SqList List),再將該指標變數L傳入。
②這裡用if( ! (*L).elem )判斷分配空間是否為空,c語言中,變數未賦值時其值是隨機的。因此我們再建立變數List後,將List.elem賦值為NULL;使該判斷有效。
③分配儲存空間後將List.length<==>(*L).length賦值為0,當前表為空表。
2.2.順序表的插入 int ListInsert(SqList *L,int i,ElemType e)
演算法步驟:①首先判斷位置i是否合法(合法範圍是1 <= i <= n+1)n為元素個數即順序表長度。
②判斷順序表的儲存空間是否已滿(這裡暫時不考慮擴充套件空間)。
③將第i個到第n個位置的元素依次向後移動一個位置。
④將要插入的元素e賦值到第i個位置。
⑤表長+1,完成插入。
//2.線性表中插入元素
int ListInsert(SqList *L,int i,ElemType e)
{
if(i<1||i>(*L).length+1)
{
printf("\n插入位置違法!!!");
return -1;
}
if((*L).length==MAXSIZE)
{
printf("\n順序表的儲存空間已滿!!!");
return -1;
}
int j;
for(j=(*L).length-1;j>=i-1;j--)
{
(*L).elem[j+1]=(*L).elem[j];
}
(*L).elem[i-1]=e;
(*L).length++;
printf("\n插入成功!!!");
return 0;
}
Tip:①這裡移動順序標中第i到第n個元素採用的是下標表示法,elem[i-1]對應於第i個元素,這裡要注意。
2.3.順序表的取值 int GetElem(SqList List,int i,ElemType *e)
演算法步驟:①首先判斷取值位置i是否合法(1<= i >=n)
②若取值位置合法,將第i個元素List.elem[i-1]賦值給e。
//3.取出第i個元素的值
int GetElem(SqList List,int i,ElemType *e)
{
if(i<1||i>List.length)
{
printf("\n所取位置違法!!!");
return -1;
}
*e=List.elem[i-1];
printf("\n取值成功!!!");
return 0;
}
Tip:①這裡傳入的是ElemType *e,e是個指向ElemType型別變數的指標,接收該返回值即*e=List.elem[i-1]。
②想要接收第i個元素的值,就事先定義一個ElemType型別的變數e,再定義個該型別的指標變數pe指向變數e(pe>>e)。向函式傳入指標變數pe即可。
2.4.順序表的查詢 int LocateElem(SqList List,ELemType e)
演算法步驟:①從第一個元素開始,依次與查詢的元素e進行比較,若有e==List.elem[i],返回其位置i+1。
②未查到,查詢失敗。
//4.查詢線性表中有無與e值相同的元素,有返回其位置,無返回0
int LocateElem(SqList List,ElemType e)
{
int i;
for(i=0;i<List.length;i++)
{
if(List.elem[i]==e)
{
printf("\n查詢成功!!!");
return i+1;
}
}
printf("\n未找到");
return 0;
}
Tip:①若所查詢的元素值在順序表中有多個,這裡只返回第一個的位置(從第一個元素開始比較)。
2.5.順序表的刪除 int ListDelete(SqList *L,int i)
演算法步驟:①先判斷刪除位置i的合法性(1<= i <=n)。
②將第i+1個到第n個元素依次向前移動一個位置
③刪除成功,表長-1。
//5.刪除i位置的元素
int ListDelete(SqList *L,int i)
{
if(i<1||i>(*L).length)
{
printf("\n刪除位置違法!!!");
return -1;
}
else
{
int j;
for(j=i-1;j<(*L).length-1;j++)
{
(*L).elem[j]=(*L).elem[j+1];
}
(*L).length--;
printf("\n刪除成功!!!");
return 0;
}
}
2.6.順序表的列印 int ListAll(SqList List)
演算法步驟:①首先判斷順序表是否為空表。
②若不為空表,從第一個元素List.elem[0]開始迴圈列印所有元素。
//列印線性表的所有元素
int ListAll(SqList List)
{
if(List.length==0)
{
printf("\n該表為空表");
return -1;
}
int i;
printf("\n輸出表中所有元素:\n");
for(i=0;i<List.length;i++)
{
printf("%d ",List.elem[i]);
}
return 0;
}
3.主函式的實現
int main()
{
int num,i; //初始線性表元素個數num
SqList List;
SqList *L;
L=&List;
InitList(L); //初始化順序表,建立空表
printf("\n請輸入要輸入的線性表元素個數");
scanf("%d",&num);
for(i=0;i<num;i++)
{
printf("\n請輸入第%d個元素:",i+1);
scanf("%d",&List.elem[i]);//給順序表一些元素賦一些值得到一個不為空的初始表
List.length++;
}
printf("請輸入要插入的元素資料:");
ElemType e;
ElemType *pe;
pe=&e;//指標pe指向變數e
scanf("%d",&e);
printf("請輸入要插入的位置:");
scanf("%d",&i);
ListInsert(L,i,e);//在位置i插入元素e
ListAll(List);//順序表的列印
printf("\n請輸入想要取出元素的位置:");
scanf("%d",&i);
if(GetElem(List,i,pe)==0)//取位置為i的元素
{
printf("\n位置合法查詢成功:%d位置的元素為%d",i,e);
}else
{
printf("\n位置不合法查詢元素失敗");
}
printf("\n請輸入要查詢其位置的元素:");
scanf("%d",&e);
int locat=LocateElem(List,e);//查詢元素e的位置
if(locat==0)
{
printf("\n線性表中無此元素");
}
else
{
printf("\n元素%d的位置為:%d",e,locat);
}
printf("\n請輸入要刪除元素的位置:");
scanf("%d",&i);
ListDelete(L,i);//刪除位置i的元素
ListAll(List);//順序表的列印
free(List.elem);//釋放順序表的記憶體空間
return 0;
}
4.結果演示
注意:本文章所有程式碼連起來,即可執行(當然開頭匯入兩個標頭檔案)。
#include<stdio.h>
#include<stdlib.h>