線性表的順序存儲結構及基本操作

學習書籍《大話數據結構》,自學完後,總結一下,以後也好複習 ,歡迎互相交流。

線性表的基本操作功能如下:

InitList(*L):          初始化操作,建立一個空的線性表L

ListEmpty(L):      若線性表爲空,返回true,否則返回false

ClearList(*L):      將線性表清空

GetElem(L,i,*e) : 將線性表L中的第i個位置元素返回給e

LocateElem(L,e) : 在線性表L中查找與給定值e相等的元素,如果查找成功,返回該元素在表中序號表示成功;否則,返回0表示失敗     

ListInsert(*L,i,e):    在線性表L中的第i個位置插入新元素e

ListDelete(*L,i,*e):  刪除線性表L中第i個位置元素,並用e返回其值

ListLength(L):          返回線性表L的元素個數
 

 對於不同的應用,線性表的基本操作不同,對於現實中更復雜的操作,完全可以用這些基本操作完成。

例如:要實現兩個線性表集合的並,將結果存入集合C中。先將集合A插入集合C中,再循環B集合中的每個元素,判斷集合A中是否存在,不存在,則插入C。具體實現本代碼的void unionL(SqList *Lc, SqList Lb,SqList La);

          要實現兩個線性表集合的交,將結果存入集合C中。分析略(和交集類似,就不寫了),具體實現本代碼void insertction(SqList La, SqList Lb, SqList *Lc);

代碼如下(編譯軟件vs2013):
 

#include <stdio.h>
#include <stdlib.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAXSIZE 30   /*存儲空間初始分配量*/

typedef int Status;/*status是函數的類型,其值是函數結果狀態代碼,如OK等*/
typedef int ElemType;  /*ElemType類型根據實際情況而定,這裏假設爲int*/


//輸出元素c
Status visit(ElemType c)
{
	printf("%d ", c);
	return OK;
}

//線性表的順序存儲結構
typedef struct                 
{
	ElemType data[MAXSIZE];//數組存儲數據元素,最大值爲MAXSIZE
	int length;           //線性表當前長度
}SqList;

//初始化順序線性表
Status InitList(SqList *L)
{
	L->length = 0;
	return OK;
}

/*初始條件:順序線性表L存在。操作結果:若L爲空表,則返回FALSE,否則返回TRUE*/
Status ListEmpty(SqList L)
{
	if (L.length == 0)
		return FALSE;
	else
		return TRUE;
}

//初始條件:順序線性表L已存在。操作結果:將L重置爲空表
Status ClearList(SqList *L)
{
	L->length = 0;
	return OK;
}

//初始條件:順序線性表L已存在。操作結果:返回線性表L元素個數
int ListLength(SqList L)
{
	return L.length;
}

/*初始條件:順序線性表L已存在,1<=i<=ListLength(L)
  操作結果:用e返回L中第i個數據元素的值,注意i是指位置,第1個位置的數組是從0開始*/
Status GetElem(SqList L, int i, ElemType *e)
{
	if (L.length == 0 || i<1 || i>L.length)
		return ERROR;
	*e = L.data[i - 1];
	return OK;
}

/*初始條件:順序線性表L已存在
   操作結果:返回L中第1個與e滿足關係的數據元素的位序
    若這樣的數據元素不存在,則返回值爲0*/
int LocateElem(SqList L, ElemType e)
{
	int i;
	if (L.length)                 //順序線性表L存在且不爲空
	{
		for (i = 0; i < L.length;i++)
		if (L.data[i] == e)
			return i+1;
	}
	return 0;
}

/*初始條件:順序線性表L已存在,1<=i<=ListLength(L)
   操作結果:在L中第i個位置之前插入新的數據元素e,L中的長度加1*/
Status ListInsert(SqList *L, int i, ElemType e)
{
	int k;
	if (L->length == MAXSIZE || i < 1 || i>L->length + 1) //L滿或i小於1或大於最後一個位置+1
		return ERROR;
	else
	{
		if (i <= L->length)
		{
			for (k = L->length; k >= i; k--)
				L->data[k] = L->data[k - 1];
		}
		L->data[i - 1] = e;
		L->length++;
		return OK;
	}
}

/*初始條件:順序線性表L已存在,1<=i<=ListLength(L)
操作結果:刪除L的第i個元素,並用e返回其值,L的長度減1*/
Status ListDelete(SqList *L, int i, ElemType *e)
{
	int k;
	if (L->length == MAXSIZE || i < 1 || i>L->length) //L滿或i小於1或大於最後一個位置
		return ERROR;
	*e = L->data[i - 1];  //用e保存要刪除的元素
	if (i<L->length)
	for (k = i - 1; k < L->length-1; k++)
		L->data[k] = L->data[k + 1];
	L->length--;
	return OK;
}

/*初始條件:順序線性表L已存在
  操作結果:依次對L中的每個元素輸出*/
Status ListTraverse(SqList L)
{
	int i;
	for (i = 0; i < L.length; i++)
		visit(L.data[i]);
	printf("\n");
	return OK;
}

//實現兩個線性表集合的並集操作
//將所有的線性表中元素不重複的存入Lc中
void unionL(SqList *Lc, SqList Lb,SqList La)
{
	int La_len, Lb_len,Lc_len, i,j;
	ElemType e;   //聲明La與Lb相同的元素e
	La_len = ListLength(La);
	Lb_len = ListLength(Lb);
	ClearList(Lc);
	Lc_len = ListLength(*Lc);
	for (j = 1; j <= La_len; j++)
	{
		GetElem(La, j, &e);    //取La中第i個元素賦給e
		ListInsert(Lc, ++Lc_len, e); //插入
	}
	for (i = 1; i <= Lb_len; i++)
	{
		GetElem(Lb, i, &e);    //取Lb中第i個元素賦給e
		if (!LocateElem(*Lc, e)) //La中不存在和e相同數據元素
			ListInsert(Lc, ++Lc_len, e); //插入
	}
}

//實現兩個集合的交集操作
//將所有的在線性表Lb中且在La中的數據元素插入到Lc中
void insertction(SqList La, SqList Lb, SqList *Lc)
{
	int La_len, Lb_len, Lc_len, i;
	ElemType e;
	La_len = ListLength(La);
	Lb_len = ListLength(Lb);
	ClearList(Lc);
	Lc_len = ListLength(*Lc);
	for (i = 1; i <= Lb_len; i++)
	{
		GetElem(Lb, i, &e);
		if (LocateElem(La,e))  //La中存在和e相同數據元素
			ListInsert(Lc, ++Lc_len, e); //插入
	}
}
int main()
{
	SqList L;
	ElemType e;
	Status i;
	int j, k;
	i = InitList(&L);
	printf("初始化L後:L.length=%d\n", L.length);
	for (j = 0; j < 8; j++)
		ListInsert(&L, 1, j);
	printf("L表頭依次插入0--7:");
	ListTraverse(L);

	printf("L是否爲空:(1否0是)%d\n", ListEmpty(L));
	ClearList(&L);
	printf("清空線性表L\n");
	printf("L是否爲空:(1否0是)%d\n", ListEmpty(L));

	for (int j = 1; j <=10; j++)
	{
		ListInsert(&L, j, j-1);
	}
	printf("在L表中1--10位置輸入0--9數字:");
	ListTraverse(L);
	GetElem(L, 3, &e);
	printf("輸出L中第3個元素:%d\n",e );
	k = LocateElem(L, 3);
	if (k)
	printf("找出L中第一個3所在的位置:%d\n",k);
	else
	{
		printf("L中無此元素\n");
	}
	k = ListDelete(&L, 4, &e);
	if (k)
		printf("刪除L中第4個元素值爲: %d\n", e);
	else
		printf("刪除失敗\n");
	printf("輸出L中所有的元素:");
	ListTraverse(L);;

	SqList Lb;
	SqList Lc;
	InitList(&Lc);
	InitList(&Lb);
	for (j = 0; j < 7; j++)
	{
		ListInsert(&Lb, j, j + 5);
	}
	printf("輸出Lb中所有的元素:");
	ListTraverse(Lb);
	unionL(&Lc,L, Lb);
	printf("輸出L和Lb標的並集:");
	ListTraverse(Lc);

	
	insertction(L, Lb, &Lc);
	printf("輸出L和Lb標的交集:");
	ListTraverse(Lc);
	system("pause");
	return 0;
}

結果截圖:

插入和刪除的平均時間複雜度:O(n)

線性表順序存儲結構的優缺點:
優點: 1.無須爲表示表中元素之間的邏輯關係而增加額外的存儲空間

             2.可以快速地存取表中任一位置的元素

缺點: 1.插入和刪除操作需要移動大量元素

             2.當線性表長度變化較大時,難以確定存儲空間的容量

             3.造成存儲空間的“碎片”

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