初識線性表之------------靜態順序表
阿新 • • 發佈:2018-12-11
靜態順序表是藉助陣列實現的,但與陣列不同的是,在順序表中資料是連續儲存的,這是順序表與陣列的區別。 下面是關於靜態順序表的實現:
首先,先定義順序表的結構體:
順序表的定義
//因為是藉助陣列實現的,因此,需要定義陣列的大小,在這裡用MAX 表示陣列大小。 //因為還需要多用一個變數來表示順序表中的元素個數,因此,將兩個變數封裝成一個結構體,方便傳參和儲存資料。 typedef int DataType; #define MAX 100 typedef struct SeqList { DataType data[MAX]; //順序表 int sz; //順序表中的元素個數 }SeqList, *pSeqList;
對於一個順序表來說,需要實現的功能基本包括:順序表的初始化、銷燬、插入資料、刪除資料、查詢資料等,下面一一進行實現。
順序表的初始化:
//對於順序表來說,陣列的大小是確定的
//因此在初始化階段只需要將表示元素個數的 sz 成員的值修改為 0 即可
void InitSeqList(pSeqList ps) //初始化
{
assert(ps != NULL); //因為下面要對 ps 解引用,因此先檢測 ps 的有效性
ps->sz = 0;
}
順序表的銷燬:
//原理與初始化相同,只需要通過修改表示資料個數的 sz 的值即可 void DestroySeqList(pSeqList ps) { assert(ps != NULL); ps->sz = 0; }
順序表的插入:
順序表的插入分為三種,即:頭插、尾插和指定位置插入,而指定位置插入又分為給出值查詢位置插入和給定下標插入。
- 頭插: 將新的元素放在順序表的首元素的位置。當插入資料時,首先判斷順序表的使用情況,如果順序表的元素個數已經達到了陣列的大小,那麼就表示順序表已滿,不能執行插入。如果未滿,就可以執行插入操作。當插入時,如果順序表不為空,那麼,首元素的位置就已經有其他元素了,所以我們需要先將順序表的所有元素從後到前依次後挪一個位置。留出一個可以插入資料的位置。
//頭插 void PushFront(pSeqList ps, DataType d) { int i = 0; assert(ps != NULL); if (ps->sz == MAX) { printf("滿了!\n"); return; } for (i = ps->sz; i > 0; i--) { ps->data[i] = ps->data[i - 1]; } ps->data[0] = d; ps->sz++; }
- 尾插:將新的元素放在順序表的尾部。當插入資料時,我們同樣先判斷順序表的使用情況。如果順序表已滿,不能執行插入,如果未滿就執行插入操作。
sz
表示的是順序表中元素的個數,也是下一次需要插入的元素的位置。
//尾插
void PushBack(pSeqList ps, DataType d)
{
assert(ps != NULL);
if (ps->sz == MAX){
printf("SeqList Full, Can't Push");
return;
}
ps->data[ps->sz] = d;
ps->sz++;
}
- 在給定的下標處插入:給定一個下標,如果該下標處有值或該下標上一個有值(保證順序表的連續性)執行插入。如果空間未滿,則執行插入操作,先從順序表的最後一個開始,將元素依次向後挪一位,將指定下標處空出來,將新元素插入。插入完成後
sz++
//在給定下插入
void Insert(pSeqList ps, int pos, DataType d)
{
int i = 0;
assert(ps != NULL);
if (ps->sz == MAX) { //順序表滿了
printf("滿了!\n");
return;
}
if (pos <= 0 || pos > ps->sz) { //給定下標錯誤
return;
}
for (i = ps->sz; i > pos; i--) {
ps->data[i] = ps->data[i - 1];
}
ps->data[pos] = d;
ps->sz++;
}
- 在給定的值前面插入:給定一個值,先在順序表中查詢,如果可以找到,就在該值的前面插入,如果找不到就返回。當執行插入操作時,因為經過查詢找到了給定值的下標,那麼只需要執行一次給定下標插入即可。
//在給定值的前面插入
void DataInsert(pSeqList ps, DataType src, DataType d)
{
int i = 0;
assert(ps != NULL);
i = Find(ps, src); //在後面實現
if (i == -1) {
printf("插入失敗!");
return;
}
PosInsert(ps, i, d);
}
順序表的查詢
順序表的查詢只需要像陣列查詢元素一樣遍歷陣列即可,如果找到了返回元素所在位置的下標,如果找不到那麼返回-1
//順序表的查詢
int Find(pSeqList ps, DataType d)
{
int i = 0;
assert(ps != NULL);
for (i = 0; i < ps->sz; i++) {
if (d == ps->data[i]) {
return i;
}
}
printf("未找到!\n");
return -1;
}
順序表的查詢還可以用二分查詢的方式來做,由於二分查詢的前提是有序,因此首先需要對順序表進行排序。
//順序表的排序
void Sort(pSeqList ps)
{
int i = 0;
int j = 0;
int flag = 0;
assert(ps != NULL);
if (ps->sz <= 1) {
return;
}
for (i = 0; i < ps->sz - 1; i++) {
for (j = 0; j < ps->sz - i - 1; j++) {
if (ps->data[j] > ps->data[j + 1]) {
DataType tmp = ps->data[j];
ps->data[j] = ps->data[j + 1];
ps->data[j + 1] = tmp;
flag = 1;
}
}
if (flag == 0) {
break;
}
flag = 0;
}
}
//順序表的二分查詢
int BinarySearch(pSeqList ps, DataType d)
{
int left = 0;
int right = 0;
int mid = 0;
assert(ps != NULL);
right = ps->sz - 1;
while (left <= right) {
mid = left + ((right - left) >> 1);
if (d < ps->data[mid]) {
right = mid - 1;
}
else if (d > ps->data[mid]) {
left = mid + 1;
}
else if (d == ps->data[mid]) {
return mid;
}
}
return -1;
}
順序表的刪除:
順序表的刪除分為三種:頭刪、尾刪、和給定值刪。而給定值刪又分為,給定下標和給定元素。給定元素又分為,只刪除第一次遇見的,和刪除所有的。
- 頭刪:當順序表不為空時,刪除順序表的第一個元素,並將剩下的
sz - 1
個元素向前挪一個位置,並將sz
減一。 執行完頭刪之後,原來的頭元素就被覆蓋了。
//頭刪
void PopFront(pSeqList ps)
{
int i = 0;
assert(ps != NULL);
if (ps->sz == 0) {
return;
}
for (i = 0; i < ps->sz - 1; i++) {
ps->data[i] = ps->data[i + 1];
}
ps->sz--;
}
- 尾刪:當順序表不為空時,刪除順序表中下標位
sz - 1
的元素,並將sz
減一。執行尾刪時,可以不改變最後一個元素的值,只需要將表示順序表元素個數的sz
減一,這樣也可以達到刪除的目的。
//尾刪
void PopBack(pSeqList ps)
{
assert(ps != NULL);
if (ps->sz == 0) {
return;
}
ps->sz--;
}
- 刪除第一次遇到的給定元素 :當給定元素進行刪除時,只需要遍歷順序表,找出需要刪除的元素刪除即可,如果未找到需要刪除的元素,那麼不執行刪除操作,直接返回。
//指定元素進行刪除
void Remove(pSeqList ps, DataType d)
{
int i = 0;
int j = 0;
assert(ps != NULL);
for (i = 0; i < ps->sz; i++) {
if (d == ps->data[i]) {
break;
}
}
if (i == ps->sz) {
printf("未找到, 無法刪除!\n");
return;
}
else {
for (j = i; j < ps->sz - 1; j++) {
ps->data[j] = ps->data[j + 1];
}
ps->sz--;
}
}
- 刪除所有給定元素:刪除所有給定元素的查詢範圍是整個順序表,也就是說,當執行完一次刪除之後,並不是結束刪除,而是從當前位置開始繼續往後查詢刪除,直到整個順序表中都刪除完成。
void RemoveALL(pSeqList ps, DataType d)
{
int i = 0;
int j = 0;
assert(ps != NULL);
for (i = 0; i < ps->sz; i++) {
if (ps->data[i] != d) {
ps->data[j] = ps->data[i];
j++;
}
}
ps->sz = j;
}
最後是順序表的幾個狀態函式:
//返回順序表中元素個數
int SeqList_Size(const pSeqList ps)
{
assert(ps != NULL);
return ps->sz;
}
//檢視順序表是否為空
bool SeqListEmpty(const pSeqList ps)
{
assert(ps != NULL);
return ps->sz == 0;
}
//檢視順序表是否已滿
bool SeqListFull(const pSeqList ps)
{
assert(ps != NULL);
return ps->sz == MAX;
}
以上即是本篇的所有內容,不足之處還望指正。