線性表

線性表定義以及基本操作

定義

  • 相同數據類型的n個數據元素組成的有限序列,n>=0
  • 除第一個元素以外,每個元素有且只有一個直接前驅
  • 除最後一個元素以外,每個元素有且只有一個直接後繼
  • 線性表屬於邏輯結構

基本操作

  • InitList ( &L ):初始化表,構造一個空的線性表
  • Length ( L ):返回線性表L的長度
  • LocateElem ( L , e ):按值查找
  • GetElem ( L , i ):按位查找
  • ListInsert( &L , i , e ):插入操作,在表L中第i個位置插入指定元素e
  • ListDelete( &L , i , e ):刪除操作,刪除表L中第i個位置的元素,並用e返回刪除元素的值
  • PrintList( L ):輸出操作,按照前後順序輸出線性表L中的元素
  • Empty( L ):判空操作,空爲true,非空爲false
  • DestroyLise( &L ):銷燬操作。銷燬線性表,並且釋放空間

1 順序表示

1.1 定義

  • 順序存儲又稱爲順序表
  • 用一組地址連續的存儲單元依次存儲線性表中的數據元素
  • 邏輯上相鄰的兩個元素物理位置上也相鄰
  • 邏輯順序與物理順序相同
  • 最主要特點是隨機訪問

1.2 基本操作的實現

  • 定義實現
    • 靜態分配
#define MAXSIZE 1000
typedef struct
{
    ElemType data[MAXSIZE];
    int length;
}SqList;
  • 動態分配
#define MAXSIZE 1000
typedef struct
{
    ElemType *data;
    int MaxSize,length;
}SqList
//C的初始動態分配語句
L.data=(ElemType*)malloc(sizeof(ElemType)*InitSize);
//C++的初始動態分配語句
L.data=new ElemType[InitSize];
  • 插入操作 O(n)
bool ListInsert(SqList &L,int i,ElemType e)
{
    if(i<1||i>L.length+1) return false;//判定i的範圍是否有效
    if(L.length>=MaxSize) return false;//判斷當前L的長度是否達到最大長度
    for(int j=L.length-1;j>=i;j--)
    {
        L.data[j]=L.data[j-1];
    }
    L.data[i-1]=e;
    L.length++;
    return true;
}
  • 刪除操作 O(n)
bool ListDelete(SqList &L,int i,ElemType &e)
{
    if(i<1||i>L.length) return false;
    e=L.data[i-1];
    for(int j=i;i<L.length;j++)
    {
        L.data[j-1]=L.data[j];
    }
    return true;
}
  • 按值查找 O(n)
    • 從前往後依次遍歷即可

1.3 問題解決

  • 設將n(n>1)個整數存放到一維數組中,將R中保存的序列循環左移P個位置,即將R中的數據由(1 2 3 4 5 6…n)變爲(3 4 5 6…n 1 2)
    • 算法思想:分成兩段,分別顛倒,再將總序列顛倒
    • 1 2 3 4 5 6 -> 2 1 6 5 4 3 -> 3 4 5 6 1 2
void Reverse(int R[],int from,int to)
{
    int k;
    for(int i=0;i<(to-from+1)/2;i++)
    {
        k=R[from+i];
        R[from+i]=R[to-i];
        R[to-i]=k;
    }
}
void Converse(int R[],int n,int p)
{
    Reverse(R,0,p-1);
    Reverse(R,p,n-1);
    Reverse(R,0,n-1);
}
  • 給定一個長度爲n一維數組,尋找出現次數最多的元素
    • 算法思想:利用map<int,int>存不同元素出現次數
int Search(int a[],int length)
{
    map<int,int>m;
    for(int i=0;i<length;i++)
    {
        ++m[a[i]];
    }
    int value=(m.begin())->first;
    int max=(m.begin())->second;
    for(map<int,int>::iterator iter=m.begin();iter!=m.end();iter++)
    {
        if(iter->second>max)
        {
            value=iter->first;
            max=iter->second;
        }
    }
    return value;
}

2 鏈式表示

2.1 單鏈表

  • 2.1.1 單鏈表定義

    • 通過一組任意的存儲單元來存儲線性表中的數據元素
typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LNode,*LinkList;
  • 2.1.2 基本操作實現

    • 建立單鏈表
      • 頭插法 O(n)
LinkList List_HeadInsert(LinkList &L)
{
    LNode *s;
    int k;
    L=(LinkList)malloc(sizeof(LNode));//創建頭節點,並且分配內存
    L->next=NULL;
    cin>>k;
    while(k!=9999)//選擇一個終止條件,這裏用x=9999來代替
    {
        s=(LNode*)malloc(sizeof(LNode));
        s->data=k;
        s->next=L->next;
        L->next=s;
        cin>>k;
    }
    return L;
}
  • 尾插法 O(n)
LinkList list_TailInsert(LinkList &L)
{
    LNode *s;
    LNode *r=L;
    int k;
    L=(LinkList)malloc(sizeof(LNode));//創建頭節點,並且分配內存
    L->next=NULL;
    cin>>k;
    while(k!=9999)//選擇一個終止條件
    {
        s=(LNode*)malloc(sizeof(LNode));
        s->data=k;
        s->next=r->next;
        r->next=s;
        r=s;
        cin>>k;
    }
    return L;
}

  • 按位查找(查找的是節點)
LNode *GetELem(LinkList L,int i)
{
    int j=1;
    LNode *p=L->next;
    if(i==0)
        return L;
    if(i<1)
        return NULL;
    while(j<i&&p)
    {
        p=p->next;
        j++;
    }
    return p;
}
  • 按值查找(從頭遍歷,和上面差不多,方法定義的時候也是尋找節點)
  • 插入節點(隨便想想啦,注意指針順序)
  • 刪除節點(同上)

2.2 雙鏈表

  • 擁有兩個指針,分別指向前驅節點和後驅節點
typedef struct DNode
{
    Elemtype data;
    struct Dnode *piror,*next;
}DNode.*Dlinklist;

2.3 循環鏈表

  • 循環單鏈表
    • 判空條件爲:L->next==L
  • 循環雙鏈表
    • 判空條件爲:L->next == L && L->piror == L

2.4 靜態鏈表

  • 藉助數組來描述線性表的鏈式存儲結構
#define MaxSize 100
typedef struct
{
    ElemType data; //保存數據
    int next;  //保存下一個節點的數組下標
}SLinkList[MaxSize];

+結束標誌爲:next==-1

順序表與鏈表的比較

  • 總結一下大概就是順序表存取方便,鏈表操作方便
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章