1. 程式人生 > >c/c++常用演算法(1) -- 資料結構(線性表的順序儲存)

c/c++常用演算法(1) -- 資料結構(線性表的順序儲存)

一、線性表描述

      線性結構是最常用、最簡單的一種資料結構。而線性表是一種典型的線性結構。其基本特點是線性表中的資料元素是有序且是有限的。

在這種結構中:

            ①存在一個唯一的被稱為“第一個”的資料元素;

            ②存在一個唯一的被稱為“最後一個”的資料元素;

            ③除第一個元素外,每個元素均有唯一一個直接前驅;

            ④除最後一個元素外,每個元素均有唯一一個直接後繼。

二、線性表定義

      線性表(Linear List):是由n(n≧0)個數據元素(結點)a1,a2,…an組成的有限序列。該序列中的所有結點具有相同的資料型別。其中資料元素的個數n稱為線性表的長度。

      當n=0時,稱為空表。

      當n>0時,將非空的線性表記作: (a1,a2,…an)        

      a1稱為線性表的第一個(首)結點,an稱為線性表的最後一個(尾)結點。

      a1,a2,…ai-1都是ai(2≦i≦n)的前驅,其中ai-1是ai的直接前驅;

      ai+1,ai+2,…an都是ai(1≦i≦n-1)的後繼,其中ai+1是ai的直接後繼。


三、線性表的邏輯結構

      線性表中的資料元素ai所代表的具體含義隨具體應用的不同而不同,線上性表的定義中,只不過是一個抽象的表示符號。

      ◆  線性表中的結點可以是單值元素(每個元素只有一個數據項)。

      例1: 26個英文字母組成的字母表:(A,B,C、…、Z)

      例2 :某校從1978年到1983年各種型號的計算機擁有量的變化情況:(6,17,28,50,92,188)

      例3 :一副撲克的點數    (2,3,4,…,J,Q,K,A)

      ◆  線性表中的結點可以是記錄型元素,每個元素含有多個數據項,每個項稱為結點的一個域 。每個元素有一個可以唯一標識每個結點的資料項組,稱為關鍵字。

      例4 :某校2001級同學的基本情況:{(‘2001414101’,‘張裡戶’,‘男’,06/24/1983), (‘2001414102’,‘張化司’,‘男’,08/12/1984)…, (‘2001414102’,‘李利辣’,‘女’,08/12/1984)}

      ◆若線性表中的結點是按值(或按關鍵字值)由小到大(或由大到小)排列的,稱線性表是有序的。

      ◆線性表是一種相當靈活的資料結構,其長度可根據需要增長或縮短。

      ◆對線性表的資料元素可以訪問、插入和刪除。


四、線性表的抽象資料型別定義

ADT List{
    資料物件:D = { ai | ai∈ElemSet,  i=1,2,…,n, n≧0 }
    資料關係:R = {<ai-1, ai> | ai-1, ai∈D,  i=2,3,…,n }
    基本操作:
    InitList( &L )
    操作結果:構造一個空的線性表L;
    ListLength( L )
    初始條件:線性表L已存在;
    操作結果:若L為空表,則返回TRUE,否則返回FALSE;
    ….
    GetElem( L, i, &e )
    初始條件:線性表L已存在,1≦i≦ListLength(L);
    操作結果:用e返回L中第i個數據元素的值;
    ListInsert ( L, i, &e )
    初始條件:線性表L已存在,1≦i≦ListLength(L) ;
    操作結果:線上性表L中的第i個位置插入元素e;
    …
    } ADT List

五、線性表的順序儲存結構

      順序儲存:把線性表的結點按邏輯順序依次存放在一組地址連續的儲存單元裡。用這種方法儲存的線性表簡稱順序表。

      順序儲存的線性表的特點:

             ◆ 線性表的邏輯順序與物理順序一致;

             ◆ 資料元素之間的關係是以元素在計算機內“物理位置相鄰”來體現。

      設有非空的線性表:(a1,a2,…an)。順序儲存如圖2-1所示。

六、實現程式碼(順序表操作示例):

sequenceList.h

#ifndef __CHelloWorld__sequenceList__
#define __CHelloWorld__sequenceList__

#include <iostream>
#include <string.h>

#define MAXLEN 100  //定義順序表的最大長度

typedef struct
{
    char key[10];   //結點的關鍵字
    char name[20];
    int age;
}DATA;              //結點型別

typedef struct
{
    DATA ListData[MAXLEN + 1];  //儲存順序表的結構陣列
    int ListLen;                //順序表已存結點的數量
}SLType;


class SequenceList
{
public:
    void SLInit(SLType* SL);                    //初始化
    int SLLength(SLType* SL);                   //返回順序表的元素數量
    int SLInsert(SLType* SL,int n,DATA data);   //插入資料
    int SLAdd(SLType* SL,DATA data);            //增加資料
    int SLDelete(SLType* SL,int n);             //刪除資料
    DATA *SLFindByNum(SLType *SL,int n);        //按序號查詢資料
    int SLFindByCout(SLType *SL,char *key);     //按key查詢資料
    int SLAll(SLType *SL);                      //遍歷結點
};

#endif /* defined(__CHelloWorld__sequenceList__) */
sequenceList.cpp
#include "sequenceList.h"
using namespace std;

void SequenceList::SLInit(SLType *SL)
{
    SL->ListLen = 0;
}

int SequenceList::SLLength(SLType *SL)
{
    return (SL->ListLen);
}

int SequenceList::SLInsert(SLType *SL, int n, DATA data)
{
    int i;
    if(SL->ListLen >= MAXLEN)
    {
        cout<<"順序表已滿,不能插入結點!"<<endl;
        return 0;
    }
    if (n<1 || n>SL->ListLen - 1)
    {
        cout<<"插入元素序號錯誤,不能插入元素!"<<endl;
        return 0;
    }
    
    for (i = SL->ListLen; i >= n; i--)
    {
        SL->ListData[i+1] = SL->ListData[i];
    }
    SL->ListData[n] = data;
    SL->ListLen++;
    return 1;
}

int SequenceList::SLAdd(SLType *SL, DATA data)
{
    if (SL->ListLen >= MAXLEN)
    {
        cout<<"順序表已滿,不能再新增結點!"<<endl;
        return 0;
    }
    SL->ListData[++SL->ListLen] = data;
	return 1;
}

int SequenceList::SLDelete(SLType *SL, int n)
{
    int i;
    if (n<1 || n>SL->ListLen+1)
    {
        cout<<"刪除結點序號錯誤,不能刪除結點!"<<endl;
        return 0;
    }
    
    for (i = n; i < SL->ListLen; i++)
    {
        SL->ListData[i] = SL->ListData[i+1];
    }
    SL->ListLen--;
    return 1;
}

DATA *SequenceList::SLFindByNum(SLType *SL, int n)
{
    if (n<1 || n>SL->ListLen+1)
    {
        cout<<"結點序號錯誤,不能返回結點!"<<endl;
        return NULL;
    }
    return &(SL->ListData[n]);
}


int SequenceList::SLFindByCout(SLType *SL, char *key)
{
    int i;
    for (i = 1; i<= SL->ListLen;i++)
    {
        if (strcmp(SL->ListData[i].key, key))
        {
            return i;
        }
    }
    return 0;
}

int SequenceList::SLAll(SLType *SL)
{
    int i;
    for (i = 1; i<=SL->ListLen; i++)
    {
        printf("(%s,%s,%d)\n",SL->ListData[i].key,SL->ListData[i].name,SL->ListData[i].age);
    }
    return 0;
}
main.cpp
#include "sequenceList.h"
using namespace std;

int main(int argc, const char * argv[])
{

    int i;
    SLType SL;
    DATA data;
    DATA *pdata;
    char key[10];
    std::cout << "順序表操作演示\n";
    SequenceList *myList = new SequenceList();
    myList->SLInit(&SL);
    std::cout << "初始化完成\n";
    
    do
    {
        std::cout << "輸入新增的結點(學號 姓名 年齡):";
        fflush(stdin);  //清空輸入緩衝區
        scanf("%s%s%d",&data.key,&data.name,&data.age);
        
        if (data.age)   //年齡不能為0
        {
            if (!myList->SLAdd(&SL, data))
            {
                break;
            }
        }
        else
        {
            break;
        }
    } while (1);
    std::cout << "\n順序表中的結點順序為:\n";
    myList->SLAll(&SL);
    
    fflush(stdin);
    std::cout << "\n要取出結點的序號:\n";
    scanf("%d",&i);
    pdata = myList->SLFindByNum(&SL, i);
    if (pdata)
    {
         printf("第%d個結點為:(%s,%s,%d)\n",i,pdata->key,pdata->name,pdata->age);
        
    }
    delete myList;
    
    // insert code here...
    std::cout << "Hello, World!\n";
    return 0;
}

執行結果:

                        

參考書籍:《C/C++常用演算法手冊》  《資料結構-清華大學嚴蔚敏》