首頁 > 軟體

C語言資料結構順序表的進階講解

2022-04-12 19:00:08

前言

在學習連結串列之前先掌握順序表

什麼是順序表?

順序表是用一段實體地址連續的儲存單元依次儲存資料元素的線性結構一般情況下采用陣列儲存,在陣列上完成資料的增刪查改。

順序表一般可分為:

  • 1.靜態順序表:使用定長陣列儲存。
  • 2.動態順序表:使用動態開闢的陣列儲存。

提示:由於靜態功能有限,這裡主要討論動態順序表

一、順序表的構造VS功能

1.順序表的構造

範例:

typedef int SeqDataType
// 順序表的動態儲存
typedef struct SeqList
{
 SeqDataType* a; // 指向動態開闢的陣列
 size_t size ; // 有效資料個數
 size_t capicity ; // 容量空間的大小
}SeqList;

這裡使用SeqDataType定義是由於我們不知道a是什麼型別的陣列,因此我們要靈活運用功能就要事先定義SeqDataType的型別(此例為int),以便後續結構型別改變時容易操作

2.介面實現(功能)

// 基本增刪查改介面
// 順序表初始化
void SeqListInit(SeqList* psl, size_t capacity);
// 順序表銷燬
void SeqListDestory(SeqList* psl);
// 順序表列印
void SeqListPrint(SeqList* psl);
// 檢查空間,如果滿了,進行增容
void CheckCapacity(SeqList* psl);
// 順序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x);
// 順序表尾刪
void SeqListPopBack(SeqList* psl);
// 順序表頭插
void SeqListPushFront(SeqList* psl, SLDataType x);
// 順序表頭刪
void SeqListPopFront(SeqList* psl);
// 順序表查詢
int SeqListFind(SeqList* psl, SLDataType x); 

二、功能具體分析

1.初始化

在實現具體專案功能之前,要事先做好準備,即初始化,將其置空,assert函數下文講解

程式碼如下(範例):

void SeqListInit(SeqList* pq)//初始化
{
	assert(pq);//斷言,判斷是否可以執行1/0
	pq->a = NULL;
	pq->size = 0;
	pq->capacity = 0;
}

2.銷燬

銷燬是在結束之後需要進行的操作,因為這裡是動態,需要考慮空間釋放,以免造成空間洩露。(先提到銷燬是因為其與初始化為首位)

程式碼如下(範例):

void SeqListDestory(SeqList* pq)
{
	assert(pq);
	free(pq->a);
	pq->a = NULL;
	pq->capacity = pq->size = 0;
}

3.檢查size與capacity是否溢位

動態進行就是根據輸入的資料改變自身陣列的大小,故我們需要對溢位的情況進行正確的規避,至於為什麼會溢位,因為我們在初始化的時候將其空間為0,無論第一次輸入多少資料都會溢位。

void SeqCheckCapacity(SeqList* pq)
{
	if (pq->size == pq->capacity)//滿了,需要增容
	{
		int newcapacity = pq->capacity == 0 ? 4 : pq->capacity * 2;
	//SeqDataType* newA = malloc(sizeof(SeqDataType) * newcapacity);
	  SeqDataType* newA  =realloc(pq->a,sizeof(SeqDataType)* newcapacity);//或者直接擴容
		if (newA == NULL)
		{
			printf("realloc failn");
			exit(-1);
		}
		pq->a = newA;
		pq->capacity = newcapacity;
	}
}

習慣上在擴容時我們習慣將其放大二倍的操作,由於realloc擴容分為兩種情況(這裡暫時不討論),故如果擴容失敗我們需要截止,並列印錯誤。

4.尾增功能(實現)

先上程式碼:

void SeqListPushBack(SeqList* pq, SeqDataType x)
{
	assert(pq);
	SeqCheckCapacity(pq);
	pq->a[pq->size] = x;
	pq->size++;
}

顧名思義就是在尾部增添內容,size正對應有效陣列下標的下一位,對該位置進行賦值,最後有效陣列size應+1,由於尾增之前我們不知道其capacity是否等於size

故我們需要進行檢查seqCheckCapacity,如果相等,則需要擴容。

5.列印

void SeqListPrint(SeqList* pq)
{
	assert(pq);
	for (int i = 0; i < pq->size; ++i)
	{
		printf("%d ", pq->a[i]);
	}
	printf("n");
}

這裡具體就沒什麼了,只是為了保證程式功能能夠具體完整實現

其他功能看下面程式碼

三、實現具體功能內碼錶(SeqList.c)

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
#include<assert.h>
void SeqListInit(SeqList* pq)//初始化
{
	assert(pq);//斷言,判斷是否可以執行1/0
	pq->a = NULL;
	pq->size = 0;
	pq->capacity = 0;
}
void SeqListDestory(SeqList* pq)
{
	assert(pq);
	free(pq->a);
	pq->a = NULL;
	pq->capacity = pq->size = 0;
}
void SeqCheckCapacity(SeqList* pq)
{
	if (pq->size == pq->capacity)//滿了,需要增容
	{
		int newcapacity = pq->capacity == 0 ? 4 : pq->capacity * 2;
	//SeqDataType* newA = malloc(sizeof(SeqDataType) * newcapacity);
	  SeqDataType* newA  =realloc(pq->a,sizeof(SeqDataType)* newcapacity);//或者直接擴容
		if (newA == NULL)
		{
			printf("realloc failn");
			exit(-1);
		}
		pq->a = newA;
		pq->capacity = newcapacity;
	}
}
void SeqListPushBack(SeqList* pq, SeqDataType x)
{
	assert(pq);
	SeqCheckCapacity(pq);
	pq->a[pq->size] = x;
	pq->size++;
}

void SeqListPrint(SeqList* pq)
{
	assert(pq);
	for (int i = 0; i < pq->size; ++i)
	{
		printf("%d ", pq->a[i]);
	}
	printf("n");
}
void SeqListPushFront(SeqList* pq, SeqDataType x)
{
	assert(pq);
	SeqCheckCapacity(pq);
	int end = pq->size - 1;
	while (end >= 0)
	{
		pq->a[end + 1] = pq->a[end];	
		end--;
	}
	pq->a[0] = x;
	pq->size++;

}
void SeqListPopBack(SeqList* pq)
{
	assert(pq);
	assert(pq->size > 0);
	--pq->size;
}
void SeqListPopFront(SeqList* pq);//尾刪暫時不實現

test.c主函數內碼錶

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include"SeqList.h"

void TestSeqList1()
{
	SeqList s;
	SeqListInit(&s);//ʼ
	SeqListPushBack(&s, 1);
	SeqListPushBack(&s, 2);
	SeqListPushBack(&s, 3);
	SeqListPushBack(&s, 4);
	SeqListPushBack(&s, 5);
    SeqListPushFront(&s, 0);
    SeqListPushFront(&s, 0);
    SeqListPushFront(&s, 0);
    SeqListPushFront(&s, 0);
	SeqListPrint(&s);
	SeqListPopBack(&s);
	SeqListPrint(&s);
	SeqListPopBack(&s);
	SeqListPrint(&s);
	SeqListDestory(&s);//
}
int main()
{
	TestSeqList1();
	return 0;
}

四.總結

順序表型別實現通訊錄後期會更,此目的是為了捋清楚如何構造各項結構與結構之間的關係->資料結構,尾刪,首刪,首增功能都較為容易,可以看上部分SeqList.c。此外,assert函數為斷言,目的是防止出現錯誤卻找不到並且執行的情況,其參照的標頭檔案為:assert.h。

到此這篇關於C語言資料結構順序表的進階講解的文章就介紹到這了,更多相關C語言 順序表內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com