算法與數據結構
線性表的定義及實現
定義
用數據元素的有限序列表示,由n(n>=0)個數據元素a1,a2,…,ai-1,ai.ai+1,…,an組成的有限並且有序的序列。
a1爲線性起點,下標是元素的序號,表示元素在表中的位置,ai-1是ai的直接前趨,ai+1 是ai的直接後繼 an爲線性終點
關鍵點: 存在有序關係,必須是按一定序列排列
基本操作
函數 | 作用 |
---|---|
List MakeEmpty() | 初始化一個新的空線性表L |
ElementType FindKth(int K,List L) | 根據指定的爲序K,返回相應元素 |
int Find(ElementType X,List L) | 已知X,返回線性表L中與X相同的第一個元素的相應位序;若不存在則返回空 |
void Insert(ElementType X,int i,List L) | 在指定位序i插入一個新元素X |
void Delete(int i,List L) | 刪除指定位序i的元素 |
int Length(List L) | 返回線性表L的長度 |
這些操作函數都需要自己實現,接下來將會講到
線性表的順序存儲結構
- 按順序方式存儲數據元素稱爲順序表
- 順序表示是把邏輯上相鄰的數據元素存儲在物理上相鄰的存儲單元中的存儲結構
- 假設線性表的每個元素佔用l個存儲單元,線性表中第i+1個數據元素的存儲位置LOC(ai+1)和第i個數據元素的存儲位置LOC(ai)之間滿足下列關係:
LOC(ai+1) = LOC(ai)+l - 線性表第i個數據元素ai的存儲位置爲:
*LOC(ai) = LOC(ai)+(i-1)l
所有元素均按一定的順序排列,可以通過上面這個公式直接獲得元素的地址,如下圖
順序表的特點: 以物理位置相鄰表示邏輯關係,任一元素均可隨機存取
線性表的實現
定義一個線性結構
用結構體來定義一個線性表,代碼如下:
#include <iostream>
#define MAXSIZE 1000001
using namespace std;
typedef struct{
int Data[MAXSIZE];
int Last; // 當前線性表最後一個元素的下標
}LNode;
typedef LNode *List;
List L;
int main() {
return 0;
}
在這個結構中定義了一個一維數組來存放線性表的數據,同時定義了一個整型變量來記錄當前線性表最後一個元素的下標。同時應滿足 Last<MAXSIZE,這是因爲在後續對線性表的操作中會插入數據,而數組的長度是不可變的,所以將線性表的長度設爲小於一維數組的長度,方便後續插入等操作,延長線性表
訪問下標爲i的元素:L->Data[i];
獲取線性表的長度: L->Last+1;
初始化(建立一個空的順序表) MakeEmpty()
定義List MakeEmpty()函數來初始化一個新的空線性表L
List MakeEmpty(){
List L;
L= (List)malloc(sizeof(LNode));
L->Last=-1;
return L;
}
在這個函數中首先定義一個List變量L,再爲它分配一個大小與LNode相同的存儲空間。注意這裏使用完malloc函數後要強制轉換一下。 線性表長度先賦值爲-1。
查找元素
在線性表中查找一個元素所在的位置,函數如下,傳入參數爲要查找的元素,以及順序表
// 給int類型取一個別名,之後直接用別名定義整型變量的線性表元素
int Find(ElementType x,List L){
int i=0;
while(i<=L->Last && L->Data[i]!=x){
i++; // 如果當前這個i沒有到最後一個元素,
//並且當前元素不等於要找的元素就i++
}
if(i>L->Last) return ERROR; // i>L->Last就是沒有找到元素x
else return i; //找到元素x,返回下標
}
插入元素
在線性表中插入元素主要分爲三步:
- 獲得元素要插入的位置i
- 對第i個元素後面的元素進行向右移動一個位置的操作,留出一個位置
- 向留出的位置中插入給定的元素
- 修改Last指針,使線性表長度+1
這麼做的主要是因爲C++的數組的內存存儲關係,存儲地址是連續不可變的,能變的只能是地址上存的數據。
代碼如下:
bool Insert(ElementType X,int i,List L){
if(L->Last ==MAXSIZE-1){
printf("表已存滿,無法再插入元素");
return false;
}
if(i<1 || i>L->Last+2){
printf("插入的位置不合法,無法完成插入操作");
return false;
}
for(int j=L->Last;j>=i-1;j--){
L->Data[j+1]=L->Data[j]; //將插入位置i之後的元素向後移動
}
L->Data[i-1]=x; //插入新元素
L->Last++; // 線性表長度+1,以指向最後一個元素
return true;
}
刪除元素
刪除操作可以理解爲插入操作的一個逆過程,步驟如下:
- 找到要刪除元素的位置i
- 將第i個元素後面的所有元素都向前移動
代碼如下:
bool Delete(int i,List L){
if(i<1 || i>L->Last+1){ //檢查要刪除的位置是否合法
printf("第%d個元素不存在",i);
return false;
}
for(int j=i;j<=L->Last;j++){
L->Data[j-1]=L->Data[j];
//將第i個元素後面的元素向前移動一格
}
L->Last--; //讓Last指向最後一個元素
return true;
}
完整代碼:
#include <iostream>
#include <stdio.h>
#include <malloc.h>
#include <iostream>
#define MAXSIZE 1000001
using namespace std;
typedef struct{
int Data[MAXSIZE];
int Last; // 當前線性表最後一個元素的下標
}LNode;
typedef LNode *List;
List L;
List MakeEmpty(){
List L;
L= (List)malloc(sizeof(LNode));
L->Last=-1;
return L;
}
typedef int ElementType;
// 給int類型取一個別名,之後直接用別名定義整型變量的線性表元素
int Find(ElementType x,List L){
int i=0;
while(i<=L->Last && L->Data[i]!=x){
i++; // 如果當前這個i沒有到最後一個元素,
//並且當前元素不等於要找的元素就i++
}
if(i>L->Last) return -1; // i>L->Last就是沒有找到元素x
else return i; //找到元素x,返回下標
}
bool Insert(ElementType x,int i,List L){
if(L->Last ==MAXSIZE-1){
printf("表已存滿,無法再插入元素");
return false;
}
if(i<1 || i>L->Last+2){
printf("插入的位置不合法,無法完成插入操作");
return false;
}
for(int j=L->Last;j>=i-1;j--){
L->Data[j+1]=L->Data[j]; //將插入位置i之後的元素向後移動
}
L->Data[i-1]=x; //插入新元素
L->Last++; // 線性表長度+1,以指向最後一個元素
return true;
}
bool Delete(int i,List L){
if(i<1 || i>L->Last+1){ //檢查要刪除的位置是否合法
printf("第%d個元素不存在",i);
return false;
}
for(int j=i;j<=L->Last;j++){
L->Data[j-1]=L->Data[j];
//將第i個元素後面的元素向前移動一格
}
L->Last--; //讓Last指向最後一個元素
return true;
}
int main() {
return 0;
}