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所代表的具體含義隨具體應用的不同而不同,線上性表的定義中,只不過是一個抽象的表示符號。
◆ 線性表中的結點可以是單值元素(每個元素只有一個數據項)。
例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++常用演算法手冊》 《資料結構-清華大學嚴蔚敏》