順序表中基本操作的實現
//庫函式標頭檔案包含
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
//函式狀態碼定義
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
//順序表的儲存結構定義
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
typedef int ElemType; //假設線性表中的元素均為整型
typedef struct//注意這裡的寫法
{
ElemType* elem; //儲存空間基地址
int length; //表中元素的個數
int listsize; //表容量大小
} SqList; //順序表型別定義
一、順序表的初始化
Status InitList_Sq(SqList &L)
{
L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));//注意是給L.elem分配空間//在初始化的時候,有長度限制,因為是順序結構
if (!L.elem) exit(OVERFLOW);
L.length=0;
L.listsize=LIST_INIT_SIZE;
}
注意: (1)是給L.elem分配空間,而不是L,不要和連結串列混淆 (2)在給L.elem分配空間的時候,LIST_INIT_SIZE*sizeof(ElemType),會有具體的長度,因為是順序結構,有明確的長度,不要和連結串列混淆,連結串列才沒有具體的長度 (3)在初始化的時候,順序表長度為0,容量大小為分配空間的大小
演算法時間複雜度:O(1)
二、順序表的建立
Status ListCreate_Sq(SqList &L)
{
ElemType n,m;
scanf("%d",&n);
L.elem=(ElemType*)malloc(n*sizeof(ElemType));//雖然之前已經確定了分配的空間,但是,之後因為有確定的數字了,所以重新分配空間;
if(!L.elem) exit(OVERFLOW);
L.length=n;
L.listsize=n;
for(int i=0; i<n; i++)
{
scanf("%d",&m);
L.elem[i]=m;
//scanf("%d",&L.elem[i]);//這種方法也是對的
}
return OK;
}
ListCreate_Sq 和 InitList_Sq是不同的,InitList_Sq是結構初始化,初始化的時候,L.length=0;L.listsize=LIST_INIT_SIZE。ListCreate_Sq 是建立一個順序表,L.length和L.listsize由輸入的值確定。但是兩者還是有共同點的,兩者都先L.elem=(ElemType*)malloc(....*sizeof(ElemType));
一般是先InitList_Sq(La);
然後再CreateList_Sq(La);
三、順序表的插入
1、指定插入位置
方法1:
Status ListInsert_Sq(SqList &L, int pos, ElemType e)//插入必須要看空間問題,不夠的話就重新分配,倒著賦值//注意pos是位置,從1開始的
{
ElemType* newbase;
if(pos>=1&&pos<=L.length+1)//pos是位置,別忘記對length+1(length為元素的個數),因為可以插入的位置有n+1個;
{
if(L.length>=L.listsize)//這裡別忘記等於號,因為等於的話,再插入也會超過記憶體大小;
{
newbase=(ElemType*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType));//與LISTINCREMENT相加的是listsize而不是length,因為是增大記憶體//給newbase動態分配一個長度為LISTINCREMENT的新空間
if(!newbase) exit(OVERFLOW);//在分配空間方面,都要進行這樣的判斷;
L.elem=newbase;//新分配空間的基地址
L.listsize+=LISTINCREMENT;//重新分配空間了,所以別忘記改變容量的大小。
}
for(int i=L.length;i>=pos;i--)
L.elem[i]=L.elem[i-1];
L.elem[pos-1]=e;
L.length++;//多了一個數據元素,所以length也要加一;
return OK;
}
else return ERROR;//別忘記else
}
方法2:
Status ListInsert_Sq(SqList &L,int pos,ElemType e)//在pos位置插入e元素
{
ElemType* newbase;//newbase是ElemType*類型的,別定義錯了
if(pos>=1&&pos<=L.length+1)//可以插入的有n+1個位置,所以,別忘了+1//pos是位置,別忘記對length+1(length為元素的個數),因為可以插入的位置有n+1個;
{
if(L.length>=L.listsize)//這裡別忘記等於號,因為等於的話,再插入也會超過記憶體大小;
{
newbase=(ElemType*)realloc(L.elem,(LISTINCREMENT+L.listsize)*sizeof(ElemType));//注意是在L.listsize基礎上進行的擴充,因為是增大記憶體,
if(!newbase) exit(OVERFLOW);//在分配空間方面,都要進行這樣的判斷;
L.elem=newbase;
L.listsize+=LISTINCREMENT;//重新分配空間了,所以別忘記改變容量的大小。
}
ElemType *p,*q;
p=&(L.elem[pos-1]);
for(q=&(L.elem[L.length-1]);q>=p;q--)
*(q+1)=*q;
*p=e;
L.length++;
return OK;
}
else return ERROR;//別忘記else
}
注意:
(1)對於在順序表中插入一個數來說,一定要先判斷插入的位置是否是在1—length+1
的範圍內,在的話,看資料多少是否超過了儲存空間的大小,超過了的話,要進行空間重新分配,空間重新分配的時候還不要忘記判斷是否分配成功。成功的話,改變記憶體大小,然後將要插入的位置記錄下來,倒著賦值,賦值的時候注意臨界點的判斷,最後不要忘記長度加一。
(2)newbase到底是什麼型別的,自己要分清了
(3)重新分配的時候,是LISTINCREMENT+L.listsize與sizeof相乘
(4)別忘記對於地址的儲存
演算法的時間複雜度為:O( ListLength(L) )
2、給出一定的條件,插入資料 例如:有序插入函式,L是一個遞增的有序順序表,函式Status ListInsert_SortedSq(SqList &L, ElemType e)用於向順序表中按遞增的順序插入一個數據。 比如:原資料有:2 5,要插入一個元素3,那麼插入後順序表為2 3 5。 要考慮擴容的問題。
Status ListInsert_SortedSq(SqList &L, ElemType e)
{
int i=0;
for(int j=0;j<L.length;j++)
{
if(L.elem[j]>e) break;//注意臨界判斷條件
else i++;
}
for(int j=L.length; j>=i+1; j--) L.elem[j]=L.elem[j-1];
L.elem[i]=e;
L.length++;//這裡不要忘記;
return OK;
}
注意:
Status ListInsert_SortedSq(SqList &L, ElemType e)
{
ElemType i=0;
while(L.elem[i]<e)
{
i++;
}
for(int j=L.length-1;j>=i;j--)
L.elem[j+1]=L.elem[j];
L.elem[i]=e;
L.length++;//這裡不要忘記;
return OK;
}
這個是錯誤的,因為,萬一想要插入的數比所有的數都打的話,那麼i就會無限制地增加
改成
Status ListInsert_SortedSq(SqList &L, ElemType e)
{
int i=0;
while(L.elem[i]<e&&i<L.length)//千萬不要忘記i<L.length這個條件
{
i++;
}
for(int j=L.length-1;j>=i;j--)
L.elem[j+1]=L.elem[j];
L.elem[i]=e;
L.length++;//這裡不要忘記;
return OK;
}
注意:增加元素的同時,不要忘記將長度加1;
四、順序表的刪除
刪除pos位置處的元素,並給e賦值為pos位置處的元素
方法1:
Status ListDelete_Sq(SqList &L, int pos, ElemType &e)
{
if(pos>=1&&pos<=L.length)
{
e=L.elem[pos-1];
for(int i=pos-1;i<=L.length-2;i++)
L.elem[i]=L.elem[i+1];
L.length--;
}
else return ERROR;
}
方法2:
Status ListDelete_Sq(SqList &L, int pos, ElemType &e)//刪除不用考慮空間問題,一個個前移就好,最後別忘記L.length--
{
if(pos>=1&&pos<=L.length)
{
ElemType *p;
e=L.elem[pos-1];//先將e賦值,也就是返回刪掉了哪個數
for(p=&(L.elem[pos-1]);p<=&(L.elem[L.length-2]);p++)
*p=*(p+1);
L.length--;
}
else return ERROR;
}
注意: (1)刪除元素的同時,不要忘記將長度減1; (2)刪除是正向賦值,插入是倒敘賦值
演算法的時間複雜度為:O( ListLength(L) )
五、查詢某元素的位置
查詢元素e在順序表的位次並返回
int ListLocate_Sq(SqList L, ElemType e)
{
int a=-1;
int i;
for(i=0; i<L.length; i++)
{
if(L.elem[i]==e)
{
a=1;
break;
}
else continue;
}
if(a==-1)
{
return 0;
}
else return i+1;
}
六、對於符合某條件的元素的定位
Status Equal(ElemType a,ElemType b)
{
if(a==b) return true;
else return false;
}
int LocateElem_Sq(SqList L,ElemType e,Status(*compare)(ElemType,ElemType))//在表中查詢第一個值與e滿足compare()的元素的位序
{
ElemType *p;
int i=1;//i的初值為第1個元素的位序
p = L.elem; //p的初值為第1個元素的儲存位置
while(i <= L.length && !(* compare)(*p++,e)) i++;
if(i <= L.length) return i;
else return 0;
}
/////////////////////////////////用法
if(!LocateElem_Sq(La,elem,Equal))
ListInsert_Sq(Lc,Lc.length+1,elem);
演算法的時間複雜度為:O( ListLength(L) )