資料結構------------線性表(上篇)
線性表:由n(n>=0)個數據特性相同的元素構成的有限序列
線性表中的袁旭個數n(n>=0)定義為線性表的長度,n=0時為空表
非空的線性表或線性結構特點:
1)存在唯一的一個數被稱為“第一個”的資料元素;
2)存在唯一的一個數被稱為“最後一個”的資料元素;
3)除第一個之外,結構中的每個資料元素均只有一個前驅(predecessor);
4)除最後一個之外,結構中的每個資料元素均只有一個後繼(successor);
線性表的型別定義
//ADT = Abstract Date Type 抽象資料型別
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ADT List{
資料物件:D={ai | ai∈ElemSet,i=1,2,3,...,n,n>=0}
資料關係:R={< > = <= >= !=.....}
基本操作:
IntList(&L) //操作結果 初始化 構造一個空的線性表L
DestroyList(&L) //操作結果 銷燬線性表L
ClearList(&L) //操作結果 置空 將線性表重置為空表
ListInsert(&L,i,e) //操作結果 插入 在L中第i位置之前插入新的資料元素e,L的長度加一。
ListDelete(&L,i) //操作結果 刪除 刪除L的第i個數據元素,L 的長度減一。
//-------------分割線 前面都是對L的操作 即L的內容會隨這些操作而發生變化------------
ListEmpty(L) //操作結果 判空 即若L是空表,則返回true,否則返回false
ListLength(L) //操作結果 返回L中資料元素的個數
GetElem(L,i,&e) //操作結果 取值 用e返回L中第i個數據元素的值
LocateElement(L,e) //操作結果 定位 返回L中第一個值與e相同的元素在L中的位置,若不存在則返回0
PriorElem(L,cur_e,&npre_e) //操作結果 前驅 若cur_e是L的資料元素,且不是第一個,則用pre_e 返回其前驅,否則操作失敗 pre_e無定義
NextElem(L,cur_e,&next_e) //操作結果 後驅 若cur_e是L的資料元素,且不是最後一個,則用next_e 返回其前驅,否則操作失 敗, next_e無定義
TraverseList(L) //操作結果 遍歷 對線性表L進行遍歷,在遍歷過程中對每個結點訪問一次
}ADT List
------------------------------------------------------其實這些函式完全可以按照自己的想法來定義-------------------------------------------------------
順序表: 線性表按順序儲存 (隨機存取)
鏈式表:線性表按鏈式儲存 (順序存取)
一 、
//---------------順序表的儲存結構--------------
#define MAXSIZE 100 //分配陣列空間大小 當然可以自己定義
typedef struct
{
ElemType *elem; //儲存空間的基地址
//ElemType指的是陣列的型別可根據實際需要更換成 int char double 等
int length; //當前長度
//同時也指的是邏輯長度 跟陣列下標錯1
} SqList; //順序表的結構型別為SqList
邏輯長度(從1開始)與陣列下標(從0開始)存在偏差
假設定義了一個順序表結構體型別的變數 SqList L;
訪問其陣列的第一個元素 即 L.elem[0]
訪問其陣列的最後一個元素 即 L.elem[L.length-1]
二、順序表中基本操作的實現
ps: 這裡return 0 可不是主函式裡面的return 0 奧
1、初始化
【演算法描述】
Status InitList(SqList &L)
{
L.elem=new ElemType[MAXSIZE] //為順序表分配一個大小為MAXSIZE大小的陣列空間
if(!L.elem) exit (-2); //儲存分配失敗退出
//exit() 直接結束當前程序 括號裡面是0正常結束 否為不正常結束
L.length=0; //空表長度為0
return 1;
}
2、遍歷
【演算法描述】
void TraverseList(SqList L)
{
for(int i=0;i<L.length;i++)
cout<<L.elem[i]<<endl; //遍歷輸出
}
【指標】 -------皮一下很開心 罒ω罒
void TraverseList(SqList L)
{
ElemType *p;
for(p=L.elem;p<L.elem+L.length-1;p++)
cout<<*p<<endl; //遍歷輸出
}
3、取值
【演算法描述】
Status GetElem(SqList L,int i,ElemType &e)
{
if(i<1||i>L.length)
return 0; //判斷i值是否合理
e=L.elem[i-1]; //我們要取的是第i號元素 在陣列中的下標是i-1 嘛
return 1;
}
【演算法分析】
一遍過 自然時間複雜度為O(1)
4、查詢
【演算法描述】
int 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;
}
查詢用指標的話會相對來說稍微麻煩了點 還需要再加個記錄位置的計數器 所以就不寫了=_=||
【演算法分析】
假設每個元素查詢的概率相等
最好的情況下查詢1次 最壞的情況下查詢n次
總的查詢次數為1+2+3+....+n=(1+n)*n/2
一共有n種可能
ASL(Average Search Length 平均查詢長度)=(1+n)/ 2
時間複雜度為O(n)
5、插入
【演算法描述】
Status ListInsert(SqList &L,int i,ElemType e)
{
if((i<1)||(i>L.length+1)) return -2; //i的位置不合法
if(L.length==MAXSIZE) return -2; //當前儲存空間已滿
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.elem[j+1]=e; 迴圈結束後j的位置為i-2
L.length++; //表長加1
return 1;
}
關於插入數e的位置 還是畫個圖吧 更容易理解為什麼是i-1 或者是j+1 ^_^
【指標】
Status ListInsert(SqList &L,int i,ElemType e)
{
SqList *p;
if((i<1)||(i>L.length+1)) return -2; //i的位置不合法
if(L.length==MAXSIZE) return -2; //當前儲存空間已滿
for(p=L.length-1;p>=L.elem+i-1;p--)
*(p+1)=*p; //插入位置及之後的元素後移
*(p+1)=e; //將新元素e放入第i個位置
L.length++; //表長加1
return 1;
}
【演算法分析】
假設每個元素查詢的概率相等
最好的情況下移動0次 最壞的情況移動下n次
總的查詢次數為0+1+2+3+....+n=n*(1+n)/2
一共有n+1種可能
ASL(Average Search Length 平均查詢長度)= n / 2
時間複雜度為O(n)
6、刪除
【演算法描述】
Status ListDelete(SqList &L,int i)
{
if((i<1)||(i>L.length)) return -2; //i的位置不合法
for(int j=i;j<=L.length-1;j++)
L.elem[j-1]=L.elem[j]; //後一個元素覆蓋前一個元素
L.length--; //表長減1
return 1;
}
【指標】
Status ListDelete(SqList &L,int i)
{
SqList *p;
if((i<1)||(i>L.length)) return -2; //i的位置不合法
for(p=L.elem+i;p<=L.elem+L.length-1;p++)
*(p-1)=*p; //後一個元素覆蓋前一個元素
L.length--; //表長減1
return 1;
}
【演算法分析】
假設每個元素查詢的概率相等
最好的情況下移動0次 最壞的情況移動下n-1次
總的查詢次數為0+1+2+3+....+n-1=(n-1)*n/2
一共有n種可能
ASL(Average Search Length 平均查詢長度)= (n-1) / 2
時間複雜度為O(n)
簡單順序表(int資料)
#include<iostream>
#define MAXSIZE 100
using namespace std;
typedef struct
{
int *elem;
int length;
}SqList;
int InitList(SqList &L)//初始化
{
L.elem=new int[MAXSIZE];
if(!L.elem) return 0;
L.length=0;
return 1;
}
int ClearList(SqList &L)//重置為空表
{
L.length=0;
return 1;
}
int ListLength(SqList L)//長度
{
return L.length;
}
int GetElem(SqList L,int i,int &e)//取值
{
if(i<1||i>L.length) return 0;
e=L.elem[i-1];return 1;
}
int LocateElem(SqList L,int e)//查詢
{
for(int i=0;i<L.length ;i++)
{
if(L.elem[i]==e) return i+1;
}
return 0;
}
int PriorElem(SqList L,int cur_e,int &pre_e) //返回前驅
{
if(cur_e!=L.elem[0])
{
for(int i=0;i<L.length ;i++)
{
if(L.elem [i]==cur_e)
{
pre_e= L.elem[i-1];
return 1;
}
}
}
return 0;
}
int NextElem(SqList L,int cur_e,int &next_e) //返回後繼
{
if(cur_e!=L.elem[L.length -1])
{
for(int i=0;i<L.length ;i++)
{
if(L.elem [i]==cur_e)
{
next_e= L.elem[i+1];
return 1;
}
}
}
return 0;
}
void ListInsert(SqList &L,int i,int e) //插入
{
for(int j=L.length-1 ;j>=i-1;j--)
L.elem [j+1]=L.elem [j];
L.elem [i-1]=e;
L.length ++;
}
void ListDelete(SqList &L,int i)//刪除
{
for(int j=i-1;j<L.length ;j++)
L.elem [j]=L.elem [j+1];
L.length --;
}
int main()
{
cout<<"1.初始化"<<endl;
cout<<"2.置空"<<endl;
cout<<"3.輸入"<<endl;
cout<<"4.長度"<<endl;
cout<<"5.取值"<<endl;
cout<<"6.查詢"<<endl;
cout<<"7.返回前驅"<<endl;
cout<<"8.返回後繼"<<endl;
cout<<"9.插入"<<endl;
cout<<"10.刪除"<<endl;
cout<<"11.遍歷"<<endl;
cout<<"0.退出"<<endl<<endl;
int choose;
cout<<"請選擇你的操作:";
cin>>choose;
while(choose)
{
SqList L;
int n,i,e;
switch(choose){
case 1://初始化
if(InitList(L)==1)
cout<<"初始化成功"<<endl<<endl;
break;
case 2://置空
if(ClearList(L)==1)
cout<<"置空成功"<<endl<<endl;
break;
case 3://輸入
{cout<<"輸入陣列長度:";
cin>>n;int p;
cout<<"輸入各個元素:";
for(p=0;p<n;p++)
{
cin>>L.elem[p];
L.length++;
}
cout<<endl;
}
break;
case 4://長度
cout<<"該線性表中元素個數為"<< ListLength(L)<<"個"<<endl<<endl;
break;
case 5://取值
cout<<"請輸入您要取值的位置:";
cin>>i;
if(GetElem(L,i,e))
cout<<"第"<<i<<"個元素是"<<e<<endl<<endl;
else
cout<<"取值失敗!"<<endl<<endl;
break;
case 6://查詢
int e;
cout<<"請輸入您要查詢的元素:";
cin>>e;
if(LocateElem(L,e)==0)
cout<<"查無此元素"<<endl<<endl;
else
cout<<"元素"<<e<<"線上性表的位置是" <<LocateElem(L,e)<<endl<<endl;
break;
case 7://前驅
{int cur_e,pre_e;
cout<<"請輸入一個元素:" ;
cin>>cur_e;
int temp=cur_e;
if(PriorElem(L,cur_e,pre_e))
cout<<"元素"<<temp<<"的前驅是"<<pre_e<<endl<<endl;
else
cout<<"返回失敗!"<<endl<<endl;}
break;
case 8://後繼
{int next_e,cur_e;
cout<<"請輸入一個元素:";
cin>>cur_e;
int temp=cur_e;
if(NextElem(L,cur_e,next_e))
cout<<"元素"<<temp<<"的後繼是"<<next_e<<endl<<endl;
else
cout<<"返回失敗!"<<endl<<endl;}
break;
case 9://插入
cout<<"請分別輸入帶插入元素的位置和元素值:";
cin>>i>>e;
if(i<=L.length&&i>=0)
{
ListInsert(L,i,e);
cout<<"插入成功"<<endl<<endl;
}
else
cout<<"插入失敗"<<endl<<endl;
break;
case 10://刪除
cout<<"請輸入要刪除的元素位置:";
cin>>i;
if(i<=L.length&&i>0)
{
ListDelete(L,i);
cout<<"刪除成功"<<endl<<endl;
}
else
cout<<"刪除失敗"<<endl<<endl;
break;
case 11://遍歷
int q=0;
cout<<"該線性表為:";
for(int p=0;p<L.length;p++)
{
cout<<L.elem[p]<<" ";
q++;
if(q==10)
{
cout<<endl;
q=0;
}
}
cout<<endl<<endl;
break;
}
cout<<"請選擇你的操作:";
cin>>choose;
}
cout<<"程式已退出"<<endl;
return 0;
}
下篇 鏈式表 o(╥﹏╥)oo(╥﹏╥)oo(╥﹏╥)o
下篇見 ̄へ ̄