資料結構 第二章(學習筆記一)

面臨禿頭的初學者發表於2020-10-04

線性表之順序儲存

線性表
線性表(linear list)是最基本、最簡單、也是最常用的一種資料結構。線性表是資料結構的一種,一個線性表是n個具有相同特性的資料元素的有限序列。
線性表是具有相同特徵的資料元素的一個有限序列。

**線性表(linear list)**由n(n>=0)個資料元素(結點)a1,a2,…,an組成的有限序列
線性表中元素的個數n(n≥0)稱為線性表的長度,n=0時稱為空表。
對於非空的線性表或線性結構,特點為:
1.存在唯一的一個被稱作"第一個"的資料元素;
2.存在唯一的一個被稱作"最後一個"的資料元素;
3.除第一個之外,結構中的每個資料元素均只有一個前驅;
4.除最後一個之外,結構中的每個資料元素均只有一個後繼。
此圖更直觀的描述它們之間的關係:
在這裡插入圖片描述
型別定義
抽象資料型別線性表的定義如下:
在這裡插入圖片描述
基本操作:
InitList(&L) (Initialization List)初始
//構造一個空的線性表L

DestroyList(&L) 銷燬
//銷燬線性表L

ClearList(&L) 清空
//將線性表L重置為空表

ListEmpty(L)
//判斷線性表L是否為空表,若為空表則返回TURE;否則返回FALSE

ListLength(L) 計算長度
//返回線性表L中的資料元素個數

GetElem(L,i,&e) 獲取元素
//條件:1< = i < = ListLength(L)
//用e返回線性表L中第i個資料元素的值

LocateElem(L,e)
//返回L中第1個值與e相同的元素在L中的位置。若這樣的元素不存在,則返回值為0

PriorElem(L,cue_e,&pre_e) 求前驅
//若cur_e是L的資料元素,且不是第一個,則用pre_e返回他的前趨;否則操作失敗,pre_e無意義

NextElem(L,cur_e,&next_e) 求後繼
//若cur_e是L的資料元素,且不是最後一個,則用next_e返回他的後繼;否則操作失敗,next_e無意義

ListInsert(&L,i,e) 插入元素
//在第L的第i個位置之前插入新的資料元素e,L的長度加一

ListDelete(&L,i) 刪除元素
//刪除L的第i個資料元素,L的長度減一

ListTraverse(L) 遍歷
//對線性表L進行遍歷,在遍歷過程中對L的每個結點訪問一次

線性表的順序表
順序表是在計算機記憶體中以陣列的形式儲存的線性表,採用順序儲存結構的線性表通常稱為順序表。順序表是將表中的結點依次存放在計算機記憶體中一組地址連續的儲存單元中。

線性表的順序儲存
線性表的順序儲存是指用一組地址連續的儲存單元依次儲存線性表中的各個元素、使得線性表中在邏輯結構上相鄰的資料元素儲存在相鄰的物理儲存單元中,即通過資料元素物理儲存的相鄰關係來反映資料元素之間邏輯上的相鄰關係。

邏輯位序和物理位序相差1

線性表順序儲存結構佔用一片連續的儲存結構。知道某個元素的儲存位置就可以知道其他元素的儲存位置,所以線性表的順序儲存結構是一種隨機存取的儲存結構。
假設線性表的每個元素佔 l 個儲存單元,則第 l+1個資料元素的儲存位置和第i個資料元素的儲存位置之間滿足關係:
LOC(ai+1)= LOC(ai)+ l
由此,所有資料元素的儲存位置均可由第一個資料元素的儲存位置得到:
LOC(ai+1)= LOC(ai)+(i-1) * l

C語言中:
陣列靜態記憶體分配

#define MAXSIZE 100  //線性表儲存空間的初始分配量
typedef struct {
	ElemType elem[MAXSIZE];
	int length;             //當前長度
}SqList;                    //順序表型別

陣列動態記憶體分配

#define  MAXSIZE 100       //線性表儲存空間的初始分配量
typedef  struct{
  ElemType *elem;           //儲存空間的基地址
  int length;               //當前長度
}SqList;                    //順序表型別

C++實現順序表基本操作

#include<stdio.h>
#include<iostream>

using namespace std;

//函式結果狀態程式碼
#define TRUE   1
#define FALSE  0
#define OK     1
#define ERROR  0
#define INFEASIBLE -1
#define OVERFLOW   -2
//Status 是函式的型別,其值是函式結果狀態程式碼
typedef int Status;    // Status 相當於 int 
typedef char ElemType; //Elemtype 相當於 char 
#define  MAXSIZE  100       //線性表儲存空間的初始分配量
typedef  struct {
	ElemType* elem;           //儲存空間的基地址
	int length;               //當前長度
}SqList;                    //順序表型別名稱為Sqlist 

Status InitList(SqList& L);   //初始化操作,建立一個空的線性表L 

void DestroyList(SqList& L);  //銷燬線性表L 

void ClearList(SqList& L);    //清空線性表L 

int ListEmpty(SqList L);      //判斷線性表L是否為空表 

int ListLength(SqList L);     //返回線性表L中的資料元素個數

Status GetElem(SqList L, int i, ElemType& e);       //用e返回線性表L中第i個元素 

Status LocateElem(SqList L, ElemType e);    //返回L中第1個值與e相同的元素在L中的位置。若這樣的元素不存在,則返回值為0

Status ListInsert(SqList& L, int i, ElemType e);    //線上性表L的第i個位置插入元素e 

Status ListDelete(SqList& L, int i, ElemType& e);   //刪除線性表L中第i個元素並用e返回 

void ListTraversals(SqList& L);  //對線性表L進行遍歷,在遍歷過程中對L的每個結點訪問一次


int main() {

	SqList L;   //建立線性表L 

	if (InitList(L))
		cout << "線性表L建立成功" << endl;

	//	ListInsert(L,1,'s');  
	if (ListInsert(L, 1, 's'))  //線上性表第一個位置裡放入元素
		cout << "插入成功" << endl;
	else
		cout << "插入失敗" << endl;

	//	ListInsert(L,2,'m');
	if (ListInsert(L, 2, 'm'))
		cout << "插入成功" << endl;
	else
		cout << "插入失敗" << endl;

	//	ListInsert(L,3,'h');
	if (ListInsert(L, 3, 'h'))
		cout << "插入成功" << endl;
	else
		cout << "插入失敗" << endl;

	cout << "遍歷線性表:" << endl;

	ListTraversals(L);

	cout << "線性表長度:" << ListLength(L) << endl;

	ElemType e;
	ListDelete(L, 1, e);
	cout << "被刪除的元素:" << e << endl;
	cout << "被刪除後線性表的長度:" << ListLength(L) << endl;

	ElemType a = 'm';
	int aa = LocateElem(L, a);
	cout << "該元素" << a << "在表中序號為:" << aa << endl;

	GetElem(L, 1, e);
	cout << "線性表L第一個元素:" << e << endl;

	cout << "清空線性表" << endl;
	ClearList(L);


	ListEmpty(L);
	if (ListEmpty(L))
		cout << "線性表為空" << endl;
	else
		cout << "線性表非空" << endl;

	DestroyList(L);
	cout << "線性表已銷燬" << endl;

	return 0;
}

Status  InitList(SqList& L){       //構造一個空的順序表L
	L.elem = new ElemType[MAXSIZE]; //為順序表分配空間
	if (!L.elem) exit(OVERFLOW);   //儲存分配失敗
	L.length = 0;                    //空表長度為0
	return OK;
}

void DestroyList(SqList& L) {
	if (L.elem)delete L.elem;   //釋放儲存空間
}

void ClearList(SqList& L) {
	L.length = 0;                //將線性表的長度設定為0
}

int ListEmpty(SqList L) {
	if (L.length == 0) return 1;
	else return 0;
}

int ListLength(SqList L) {
	return (L.length);       //呼叫SqList結構裡length 
}

Status  GetElem(SqList L, int i, ElemType& e){
	if (i < 1 || i > L.length)  return ERROR;  //判斷i值是否合理
	e = L.elem[i - 1];                        //elem[i-1]儲存第i個資料元素
	return OK;
}

Status  LocateElem(SqList L, ElemType e) {    //線上性表L中查詢值為e的資料元素,返回其序號(是第幾個元素)

	for (int i = 0; i < L.length; i++)
		if (L.elem[i] == e)   return i + 1;  //查詢成功,返回序號i+1
	return 0;                            //查詢失敗,返回0
}

Status  ListInsert(SqList& L, int i, ElemType e){
	if ((i < 1) || (i > L.length + 1))   
		return ERROR;
	if (L.length == MAXSIZE)       
		return ERROR;
	for (int j = L.length - 1; j >= i - 1; j--) {
		L.elem[j + 1] = L.elem[j];        //插入位置及之後的元素後移
	}
	L.elem[i - 1] = e;                  //將新元素 e 放入第 i 個位置
	++L.length;                       //表長加1
	return OK;
}

Status  ListDelete(SqList& L, int  i, ElemType& e){
	if ((i < 1) || (i > L.length))       
		return ERROR;
	e = L.elem[i - 1];
	for (int j = i; j <= L.length - 1; j++)
		L.elem[j - 1] = L.elem[j];        //被刪除元素之後的元素前移
	--L.length;                      //表長減1
	return OK;
}

void ListTraversals(SqList& L) {      //遍歷一遍 
	for (int i = 0; i < L.length; i++) {
		cout << L.elem[i] << endl;
	}
}

相關文章