1. 程式人生 > >資料結構------------線性表(上篇)

資料結構------------線性表(上篇)

線性表:由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

下篇見 ̄へ ̄