順序表是最簡單的一種線性結構,邏輯上相鄰的數據在計算機內的存儲位置也是相鄰的,可以快速定位第幾個元素,中間不允許有空,所以插入、刪除時需要移動大量元素。
順序表可以分配一段連續的存儲空間Maxsize,用elem記錄基地址,用length記錄實際的元素個數,即順序表的長度,
結構體的定義:
結構體定義後,如果要定義個順序表L,就可以寫:
SqList L;
1. 順序表初始化
初始化是指給順序表分配一個預定義大小的空間,用基地址elem記錄這段空間的首地址,裏面什麼都沒用,元素個數爲0。前面我們已經預定義好了一個最大空間數Maxsize,那麼就用new分配這麼大的空間,分配成功會返回空間的首地址。假設順序表裏面需要存儲整型數,那麼就可以這樣初始化:
boolInitList(SqList &L) //構造一個空的順序表L
{ //L加&表示引用類型參數,函數內部的改變跳出函數仍然有效
//不加&內部改變,跳出函數後無效
L.elem=new int[Maxsize]; //爲順序表分配Maxsize個空間
if(!L.elem) return false; //存儲分配失敗
L.length=0; //空表長度爲0
return true;
}
2. 順序表創建
順序表創建是向順序表中輸入數據,輸入數據的類型要與類型定義中的類型一致。假設順序表裏面需要存儲整型數,那麼就可以這樣創建:
boolCreateList(SqList &L) //創建一個順序表L
{ //L加&表示引用類型參數,函數內部的改變跳出函數仍然有效
//不加&內部改變,跳出函數後無效
int a,i=0;
while(a!=-1)
{
cin>>a;
if(L.length==Maxsize)
{
cout<<”順序表已滿!”
return false;
}
L.elem[i++]=a;
L.length++;
}
return true;
}
3. 順序表取值
順序表中的任何一個元素都可以立即找到,稱爲隨機存取方式,例如我們我取第i個元素,只要i值是合理的(1≤i≤L.length),那麼立即就可以找到該元素L.elem[i-1]:
bool GetElem(SqList L,int i,int &e)
{
if (i<1||i>L.length) return false;
//判斷i值是否合理,若不合理,返回false
e=L.elem[i-1]; //第i-1的單元存儲着第i個數據
return true;
}
4. 順序表查找
在順序表中查找一個元素e,需要從第一個元素開始順序查找,依次比較每一個元素值,如果相等,則返回元素位置(第幾個元素),如果查找整個順序表都沒找到,則返回-1:
int LocateELem(SqList L,int e)
{
for (i=0;i< L.length;i++)
if (L.elem[i]==e) return i+1; //第幾個元素,例如第5個元素,下標其實爲4
return -1;
}
時間複雜性分析:
最好情況:如果元素正好在第一個位置,一次比較成功;時間複雜度爲O(1);
最壞情況:如果元素正好在最後一個位置,需要比較n次成功,時間複雜度爲O(n);
平均情況:假設每個元素查找概率均等,在第一個位置需要比較1次,第二個位置需要比較2次,…,最後一個位置,需要比較n次,把n種情況加起來平均,平均時間複雜度也爲O(n):
5. 順序表插入
在順序表中第i個位置之前插入一個元素e,需要從最後一個元素開始後移,…,直到把第i個元素也後移一位,然後把e放入第i個位置。
(1)判斷插入位置i是否合法(1≤i≤L.length+1),可以在第n+1個元素之前插入。
(2)判斷順序表的存儲空間是否已滿。
(3)將第n至第i 位的元素依次向後移動一個位置,空出第i個位置。
(4)將要插入的新元素e放入第i個位置。
(5)表長加1,插入成功返回true。
bool ListInsert_Sq(SqList &L,int i ,int e)
{
if(i<1 || i>L.length+1) return false; //i值不合法
if(L.length==Maxsize) return false; //存儲空間已滿
for(j=L.length-1;j>=i-1;j--)
L.elem[j+1]=L.elem[j]; //從最後一個元素開始後移,直到第i個元素後移
L.elem[i-1]=e; //將新元素e放入第i個位置
L.length++; //表長增1
return true;
}
時間複雜性分析:
假設每個位置插入的概率均等,可以在第一個位置之前插入,第二個位置之前插入,…,最後一個位置之前,第n+1個位置之前,一共有n+1種情況,每種情況移動元素的個數是n-i+1,把所有情況加起來平均,平均時間複雜度爲O(n):
6. 順序表刪除
在順序表中刪除第i個元素,需要把該元素暫存到變量e,然後從i+1個元素開始前移,…,直到把第n個元素也前移一位,然後把e放入第i個位置。
(1)判斷插入位置i是否合法(1≤i≤L.length)。
(2)將欲刪除的元素保留在e中。
(3)將第i+1至第n 位的元素依次向前移動一個位置。
(4)表長減1,刪除成功返回true。
bool ListDelete_Sq(SqList &L,int i, int &e)
{
if((i<1)||(i>L.length)) return false; //i值不合法
e=L.elem[i-1]; //將欲刪除的元素保留在e中
for (j=i;j<=L.length-1;j++)
L.elem[j-1]=L.elem[j]; //被刪除元素之後的元素前移
L.length--; //表長減1
return true;
}
時間複雜性分析:
假設刪除每個元素的概率均等,一共有n種情況,每種情況移動元素的個數是n-i,把所有情況加起來平均,平均時間複雜度爲O(n):
完整代碼
#include <iostream>
using namespace std;
#define Maxsize 100 //最大空間
typedef struct{
int *elem;
int length; // 順序表的長度
}SqList;
bool InitList(SqList &L) //構造一個空的順序表L
{ //L加&表示引用類型參數,函數內部的改變跳出函數仍然有效
//不加&內部改變,跳出函數後無效
L.elem=new int[Maxsize]; //爲順序表分配Maxsize個空間
if(!L.elem) return false; //存儲分配失敗
L.length=0; //空表長度爲0
return true;
}
bool CreateList(SqList &L) //創建一個順序表L
{ //L加&表示引用類型參數,函數內部的改變跳出函數仍然有效
//不加&內部改變,跳出函數後無效
int a,i=0;
cin>>a;
while(a!=-1)
{
if(L.length==Maxsize)
{
cout<<"順序表已滿!";
return false;
}
L.elem[i++]=a;
L.length++;
cin>>a;
}
return true;
}
bool GetElem(SqList L,int i,int &e)
{
if (i<1||i>L.length) returnfalse;
//判斷i值是否合理,若不合理,返回false
e=L.elem[i-1]; //第i-1的單元存儲着第i個數據
return true;
}
int LocateELem(SqList L,int x)
{
for (int i=0;i<L.length;i++)
if (L.elem[i]==x) return i+1;//第幾個元素,例如第5個元素,下標其實爲4
return -1;
}
bool ListInsert_Sq(SqList &L,int i ,int e)
{
if(i<1 || i>L.length+1)return false; //i值不合法
if(L.length==Maxsize) returnfalse; //存儲空間已滿
for(intj=L.length-1;j>=i-1;j--)
L.elem[j+1]=L.elem[j]; //從最後一個元素開始後移,直到第i個元素後移
L.elem[i-1]=e; //將新元素e放入第i個位置
L.length++; //表長增1
return true;
}
bool ListDelete_Sq(SqList &L,int i,int &e)
{
if((i<1)||(i>L.length))return false; //i值不合法
e=L.elem[i-1]; //將欲刪除的元素保留在e中
for (int j=i; j<=L.length-1; j++)
L.elem[j-1] =L.elem[j]; //被刪除元素之後的元素前移
L.length--; //表長減1
return true;
}
void print(SqList L)
{
cout << "輸出順序表" <<endl;
for(int j=0;j<=L.length-1;j++)
cout<<L.elem[j]<<" ";
cout<<endl;
}
void DestroyList(SqList &L)
{
if (L.elem) delete []L.elem; //釋放存儲空間
}
int main()
{
SqList myL;
int i,e,x;
cout << "1. 初始化\n";
cout << "2. 創建\n";
cout << "3. 取值\n";
cout << "4. 查找\n";
cout << "5. 插入\n";
cout << "6. 刪除\n";
cout << "7. 輸出\n";
cout << "8. 銷燬\n";
cout << "0. 退出\n";
int choose = -1;
while (choose != 0)
{
cout << "請選擇:";
cin >> choose;
switch (choose)
{
case 1://初始化順序表
cout << "順序表初始化..." <<endl;
if(InitList(myL))
cout <<"順序表初始化成功!" << endl;
else
cout <<"順序表初始化失敗!" << endl;
break;
case 2://創建順序表
cout << "順序表創建..." <<endl;
cout << "輸入整型數,輸入-1結束" <<endl;
if(CreateList(myL))
cout <<"順序表創建成功!" << endl;
else
cout <<"順序表創建失敗!" << endl;
break;
case 3://取值
cout << "輸入整型數i,取第i個元素輸出" <<endl;
cin>>i;
if(GetElem(myL,i,e))
cout <<"第i個元素是: " <<e<< endl;
else
cout <<"順序表取值失敗!" << endl;;
cout << "第i個元素是: "<<e<< endl;
break;
case 4://查找
cout << "請輸入要查找的數x:";
cin>>x;
if(LocateELem(myL,x)==-1)
cout <<"查找失敗!" << endl;
else
cout <<"查找成功!" << endl;
break;
case 5://插入
cout << "請輸入要插入的位置和要插入的數據元素e:";
cin>>i>>e;
if(ListInsert_Sq(myL,i,e))
cout <<"插入成功!" << endl;
else
cout <<"插入失敗!" << endl;
break;
case 6://刪除
cout << "請輸入要刪除的位置i:";
cin>>i;
if(ListDelete_Sq(myL,i,e))
cout <<" 刪除成功!" << endl;
else
cout <<"刪除失敗!" << endl;
break;
case 7://輸出
print(myL);
break;
case 8://銷燬
cout << "順序表銷燬..."<<endl;
DestroyList(myL);
break;
}
}
return 0;
}
原文:https://blog.csdn.net/rainchxy/article/details/77946835