1. 程式人生 > >初識線性表之------------靜態順序表

初識線性表之------------靜態順序表

       靜態順序表是藉助陣列實現的,但與陣列不同的是,在順序表中資料是連續儲存的,這是順序表與陣列的區別。        下面是關於靜態順序表的實現:

       首先,先定義順序表的結構體:        

順序表的定義

//因為是藉助陣列實現的,因此,需要定義陣列的大小,在這裡用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;
}

以上即是本篇的所有內容,不足之處還望指正。