- 線性表的基本操作
//線性表的基本操作 /* Status,自定義的一個枚舉類型, enum Status{ success(成功),fail(失敗),fatal(內存分配失敗),range_error(連續空間訪問失敗越界) } */ Status List_Init(SqListPtr L);//初始化線性表 void List_Clear(SqListPtr L);//清空線性表 void List_Destory(SqListPtr L);//銷毀線性表 bool List_Empty(SqListPtr L);//判斷線性表是否為空 int List_Size(SqListPtr L);//線性表中元素的個數或線性表的長度 Status List_Retrival(SqListPtr L,int pos,ElemType *elem);//在線性表L中的pos那個位置取出數據放在elem指針中 Status List_Locate(SqListPtr L,ElemType elem,int *pos);//在線性表L中找出元素elem的位置放在pos指針中 Status List_Prior(SqListPtr L,int pos,ElemType *elem);//在線性表L中求出pos那個位置元素的直接前驅放在elem指針中 Status List_Next(SqListPtr L,int pos,ElemType *elem);//在線性表L中求出pos那個位置元素的直接后繼放在elem指針中 //以上函數的參數是指針類型的,通常是指:我們希望通過函數所獲得結果放到指針當中 Status List_Insert(SqListPtr L,int pos,ElemType elem);//在線性表中插入一個元素 Status List_Delete(SqListPtr L,int pos)://在線性表中刪除一個元素
- 定義線性表結構體(空間分配,靜態:數組;動態:指針)
//定義線性表的結構體 #define LIST_TNIT_SIZE 100 //線性表初始大小100 #define LIST_INCREAMENT 10 //增量 typedef int ElemType; typedef struct SqList{ ElemType *elem;//elem指針,指向ElemType數據元素類型,連續存儲空間的首地址的指針 int length=0;//線性表的長度,初始線性表的長度為0 int list_size;//線性表內存空間的大小 }SqList,*ptr; typedef ptr SqListPtr;
一、線性表的順序存儲結構
1、初始化—創建線性表
//初始化,創建線性表 Status List_Init(SqListPtr L){ Status s=success;//狀態初始假設是成功的 L->list_size=LIST_INIT_SIZE; L->length=0;//沒有數據元素,線性表的初始長度為0 L->elem=(ElemType*)malloc(sizeof(ElemType)*L->list_size); if(L->elem==NULL) s=fatal;//內存分配失敗,創建線性表失敗 return s; //返回函數狀態 }
2、線性表順序存儲結構上的查找(按位置查找值、按值查找位置)
- 按位置查找值,首先確保位置是合法的,若查找成功,返回位置元素的詳細信息,否則返回錯誤信息
//按位置查找 Status List_Retrival(SqListPtr L,int pos,ElemType *elem){//查找在線性表pos位置的元素,放在elem指針中,該函數實現查找是否成功的狀態信息 Status s=range_error;//假設初始狀態,找不到,發生越界錯誤 if(L){//如果線性表存在 if((pos-1)>=0&&(pos-1)<L->length){//判斷位置的合法性,邏輯位置與實際位置差1 *elem=L->elem[pos-1];//將查找pos位置的元素放在elem指針中 s=success//函數狀態返回查找成功 } else s=fatal;//查找失敗 return s;//返回函數狀態 }
- 按值查找位置,需要將線性表中的每一個元素進行比較,從第一個元素開始,一直比較到最后一個元素,時間復雜度根據差找的元素位置不同而有所,若查找的元素在線性表的前面,則查找速度快些,若在后面,則查找的速度慢些。
//按值查找 Status List_Locate(SqListPtr L,ElemType elem,int *pos){//找elem在線性表L當中的位置放在pos指針中 Status s=range_error; if(L){//如果線性表存在 for(int i=0;i<L->length;i++){//對線性表中每一個元素和elem比較是否相等,如果相等則查找成功,否則查找失敗 if(L->elem[i]==elem){ *pos=i+1; s=success; break; } } } else s=fatal;//查找失敗 return s;//返回函數的狀態 }
注:如果找到了就不找到需要再往后面找了,break跳出for循環,該按值查找的時間復雜度,最好的情況就是在第一個位置就找到,只需要比較1次,最壞的情況所查元素在最后一個或沒有,需要比較n次,平均比較n/2次,時間復雜度是O(n)。
3、線性表的順序存儲—插入操作
- 檢查插入位置是否合法,如果合法則繼續,否則退出。
- 判斷表是否占滿,因為事先分配空間,可能存在所分配的存儲空間全部被占用的情況,此時也不能事先插入。
- 若前面檢查通過,則數據元素依次向后移動一個位置,為避免覆蓋源數據,應從最后一個依次向前移動。
- 新的數據元素放到恰當的位置。
- 表長加1。
//線性表的順序存儲—插入操作 Status List_Insert(SqListPtr L,int pos,ElemType elem){//在線性表中pos位置插入新元素elem Status s=range_error; if((pos-1)>=0&&(pos-1)<L->length-1){//如果插入位置合法 if(L&&L->length<L->List_Size){//如果線性表存在 for(int i=L->length-1;i>=pos-1;i--) L->elem[i+1]=L->elem[i];//從最后一個元素開始向后移動 L->elem[pos-1]=elem;//將元素插入指定的pos位置 L->length++;//最后表長加1 s=success; } } else s=fail;//插入失敗 return s; //返回函數狀態 }
注:順序表上實現插入操作需要移動表中一辦的數據元素。時間復雜度為O(n),最壞的情況是在第一個元素插入(i=1),需要向后移動n個元素。這種順序存儲結構需要移動大量的數據元素,而每個數據元素可能是占據很大的內存空間,所以這種方法的效率是很低的。
4、線性表的順序存儲—刪除操作
- 檢查刪除位置是否合法,同時判斷線性表是否為空,因為空的線性表不能進行刪除操作
- 若檢查通過,數據元素依次向前移動一個位置
- 表長減1
//線性表的順序存儲—刪除操作 Status List_Delete(SqListPtr L,int pos){//在線性表L中的pos位置刪除元素 Status s=range_error; if((pos-1)>=0&&(pos-1)<L->length){//判斷刪除位置是否合法 if(L&&L->length>0){//判斷線性表是否存在,且不為空 for(int i=pos-1;i<L->length;i++) L->elem[i]=L->elem[i+1];//移動 L->length--;//表長減1 s=success;//修改狀態 } } else s=fail;//刪除失敗 return s; //返回函數狀態 }
注:插入和刪除的基本操作就是移動數據元素,最好的情況下,刪除最后一個,移動一個元素;最差的情況下,刪除第一個元素,移動n-1個元素;平均情況下:刪除第i個元素,需要移動第n-i個元素
5、銷毀線性表
//銷毀線性表 void List_Destry(SqListPtr L){ if(L->elem) free(L->elem);//釋放指針 L->length=0;//表長置0 }
6、清空線性表
void List_Clear(SqListPtr L){ L->length=0; }
7、判斷線性表是否為空
//判斷線性表是否為空 bool List_Empty(SqListPtr L){ if(L->length==0) return true; else return false; } //或者用下面的函數也可以判斷 bool List_Empty(SqListPtr L){ return L->length==0; }
8、求線性表的前驅
Status List_Prior(SqListPtr L,int pos,ElemType *elem){//求線線表pos位置元素的前驅,將結果存放在elem指針中 Ststus s=fail; if(pos>=2&&pos<=L->length){//判斷pos位置是否合法 *elem=L->elem[pos-2]; s=success; } else s=fail; return s; }
9、求線性表長度
//求線性表長度 int List_Length(SqListPtr L){ return L->length; }
10、求線性表的后繼
//求線性表的后繼 Status List_Next(SqListPtr L,int pos,ElemType *elem){//求線性表pos位置元素的后繼,將結果存放在elem指針中 Status s=fail; if(pos>=1&&pos<L->length){//判斷pos位置是否合法 *elem=L->elem[pos]; s=successs; } else s=fail; return s; }