[數據結構——lesson2.順序表]

目錄

學習目標

引言

1.什么是線性表?

2.什么是順序表?

2.1概念及結構

2.2 接口實現

2.2.1順序表的功能

1.順序表的初始化

2.打印數據

3.尾插數據

(1)檢查空間

(2)插入數據

4.尾刪數據

5.頭插數據

6.頭刪數據

7.數據查找

8.指定位置數據修改

9.指定位置數據刪除

10.指定位置數據插入

11.銷毀順序表

完整代碼

1.SeqList.h

2.SeqList.c

2.3 數組相關面試題

2.4 順序表的問題及思考

結束語


學習目標

  • 1.什么是線性表?
  • 什么是順序表?
  • 順序表的接口實現

引言

在?數據結構——lesson1.基礎中我們學習了數據結構的一些基礎知識,今天我們接著來學習一種數據結構——順序表

在學習順序表之前,我們首先要知道

1.什么是線性表

  • 線性表(linear list)是n個具有相同特性的數據元素的有限序列。 線性表是一種在實際中廣泛使用的數據結 構,常見的線性表:順序表、鏈表、棧、隊列、字符串...
  • 線性表在邏輯上是線性結構,也就說是連續的一條直線。但是在物理結構上并不一定是連續的,線性表在物 理上存儲時,通常以數組和鏈式結構的形式存儲。

2.什么是順序表?

2.1概念及結構

順序表是用一段物理地址連續的存儲單元依次存儲數據元素的線性結構,一般情況下采用數組存儲。在數組上完成數據的增刪查改。

順序表一般可以分為:

1. 靜態順序表:使用定長數組存儲元素。

2. 動態順序表:使用動態開辟的數組存儲。

今天我們要學習的是動態順序表

它與數組非常類似,但是相比于靜態順序表有一個非常明顯的優點——可以動態內存增長空間大小。

2.2 接口實現

靜態順序表只適用于確定知道需要存多少數據的場景。靜態順序表的定長數組導致N定大了,空間開多了浪費,開少了不夠用。所以現實中基本都是使用動態順序表,根據需要動態的分配空間大小,所以下面我們實現動態順序表。

2.2.1順序表的功能

順序表可以大致包含如下幾個功能:

1.初始化順序表中的數據。

2.打印順序表中的數據。

3.對順序表進行尾插(末尾插入數據)。

4.對順序表進行尾刪(末尾刪除數據)。

5.對順序表進行頭插(開頭插入數據)。

6.對順序表進行頭刪(開頭刪除數據)。

7.對順序表數據進行查找。

8.對順序表數據進行修改。

9.對指定位置的數據刪除。

10.對指定位置的數據插入。

11.銷毀順序表。

1.順序表的初始化

代碼實現

順序表的初始化我們可以把空間和有效數據個數都設置為0。

void SLInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capacity = 0;
}

2.打印數據

代碼實現

//順序表的打印
void SLPrint(SL* ps)
{assert(ps);if (ps->size == 0){printf("該順序表為空\n");return;}for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}

3.尾插數據

尾插數據就是在順序表的末尾插入數據,在插入數據之前需要先檢查順序表的空間夠不夠,不夠的話我們需要進行擴容處理。

(1)檢查空間
void SLCheckCapacity(SL* ps)
{//插入數據之前先看空間夠不夠if (ps->capacity == ps->size){//申請空間//malloc calloc realloc int arr[100]--->增容realloc//三目表達式int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//創建一個變量,避免申請失敗SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));//判斷是否成功if (tmp == NULL){perror("realloc fail:");exit(1);	//直接退出程序,不再執行}ps->arr = tmp;ps->capacity = newCapacity;}
}
(2)插入數據
//尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);    //檢查空間是否足夠//ps->arr[ps->size] = x;//++ps->size;ps->arr[ps->size++] = x;    //尾插數據
}

4.尾刪數據

尾刪數據十分容易,只需要size--就可以了。但是,要注意:一定要確保順序表中有數據

void SLPopBack(SL* ps)
{assert(ps);//判斷順序表是否為空assert(ps->size);ps->size--;
}

5.頭插數據

頭插數據是指在順序表的起始位置插入數據。

//頭插
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);//讓順序表中已經存在的數據整體往后挪一位for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];	//即arr[1]=arr[0]以此類推}ps->arr[0] = x;ps->size++;
}

6.頭刪數據

刪除頭部數據,需要依次往前覆蓋。

// 頭刪
void SLPopFront(SL* ps)
{assert(ps);//判斷順序表是否為空assert(ps->size);//數據整體往前移動一位for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

7.數據查找

輸入參數,在順序表找到指定的值并返回下標,找不到則返回-1。

//順序表的查找
int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){//找到if (ps->arr[i] == x){return i;}}//沒找到return -1;
}

8.指定位置數據修改

//指定位置數據修改
void SLModify(SL* ps, int pos, SLDataType x)
{assert(ps);assert(ps->size);assert(pos>=0 && pos < ps->size);ps->arr[pos] = x;
}

9.指定位置數據刪除

//指定位置刪除數據
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;  //有效數據-1
}

10.指定位置數據插入

//在指定位置之前插入數據
//pos為指定位置
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//先檢查空間夠不夠SLCheckCapacity(ps);//讓pos及之后的數據整體向后移動一位for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}

11.銷毀順序表

//順序表的銷毀
void SLDestroy(SL* ps)
{if (ps->arr){free(ps->arr);}ps->arr = NULL;ps->size = ps->capacity = 0;
}

完整代碼

1.SeqList.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//定義順序表的結構//define N 100
//靜態順序表
//struct SeqList
//{
//	int arr[N];
//	int size;	//有效數據個數
//}typedef int SLDataType;
//動態順序表
typedef struct SeqList
{SLDataType* arr;int size;		//有效數據個數int capacity;	//空間大小
}SL;//順序表初始化
void SLInit(SL* ps);
//順序表的銷毀
void SLDestroy(SL* PS);
//順序表的打印
void SLPrint(SL s);//尾部插入
void SLPushBack(SL* ps, SLDataType x);
//頭部插入
void SLPushFront(SL* ps, SLDataType x);//尾部刪除
void SLPopBack(SL* ps);
//頭部刪除
void SLPopFront(SL* ps);//指定位置之前插入
void SLInsert(SL* ps, int pos, SLDataType x);
//指定位置刪除數據
void SLErase(SL* ps, int pos);
//查找數據
int SLFind(SL* ps, SLDataType x);

2.SeqList.c

#include"SeqList.h"void SLInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capacity = 0;
}//順序表的銷毀
void SLDestroy(SL* ps)
{if (ps->arr){free(ps->arr);}ps->arr = NULL;ps->size = ps->capacity = 0;
}void SLCheckCapacity(SL* ps)
{//插入數據之前先看空間夠不夠if (ps->capacity == ps->size){//申請空間//malloc calloc realloc int arr[100]--->增容realloc//三目表達式int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//創建一個變量,避免申請失敗SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));//判斷是否成功if (tmp == NULL){perror("realloc fail:");exit(1);	//直接退出程序,不再執行}ps->arr = tmp;ps->capacity = newCapacity;}
}//尾插
void SLPushBack(SL* ps, SLDataType x)
{/*if (ps == NULL){return;}*/assert(ps);/*ps->arr[ps->size] = x;++ps->size;*/SLCheckCapacity(ps);ps->arr[ps->size++] = x;
}//頭插
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);//讓順序表中已經存在的數據整體往后挪一位for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];	//即arr[1]=arr[0]以此類推}ps->arr[0] = x;ps->size++;
}//順序表的打印
void SLPrint(SL* ps)
{assert(ps);if (ps->size == 0){printf("該順序表為空\n");return;}for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}void SLPopBack(SL* ps)
{assert(ps);//判斷順序表是否為空assert(ps->size);ps->size--;
}// 頭刪
void SLPopFront(SL* ps)
{assert(ps);//判斷順序表是否為空assert(ps->size);//數據整體往前移動一位for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}//在指定位置之前插入數據
//pos為指定位置
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//先檢查空間夠不夠SLCheckCapacity(ps);//讓pos及之后的數據整體向后移動一位for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}//指定位置刪除數據
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;  
}//順序表的查找
int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){//找到if (ps->arr[i] == x){return i;}}//沒找到return -1;
}//指定位置數據修改
void SLModify(SL* ps, int pos, SLDataType x)
{assert(ps);assert(ps->size);assert(pos>=0 && pos < ps->size);ps->arr[pos] = x;
}

2.3 數組相關面試題

  • . 原地移除數組中所有的元素val,要求時間復雜度為O(N),空間復雜度為O(1)。OJ鏈接
  • 2. 刪除排序數組中的重復項。OJ鏈接
  • 3. 合并兩個有序數組。OJ鏈接

2.4 順序表的問題及思考

問題:

  • 1. 中間/頭部的插入刪除,時間復雜度為O(N)
  • 2. 增容需要申請新空間,拷貝數據,釋放舊空間。會有不小的消耗。
  • 3. 增容一般是呈2倍的增長,勢必會有一定的空間浪費。例如當前容量為100,滿了以后增容到200,我們 再繼續插入了5個數據,后面沒有數據插入了,那么就浪費了95個數據空間。

思考:如何解決以上問題呢?下一節內容我們將給出了鏈表的結構來看看。

結束語

這一節我們了解到了第一個數據結構——順序表

非常感謝你的點贊關注和收藏!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/96150.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/96150.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/96150.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ChatGPT大模型訓練指南:如何借助動態代理IP提高訓練效率

隨著人工智能技術的飛速發展&#xff0c;ChatGPT等大型語言模型&#xff08;LLM&#xff09;已成為科技界和產業界關注的焦點。模型的訓練過程耗時、耗資源且對網絡環境要求極高。尤其是在需要模擬真實用戶行為、進行大規模數據爬取或分布式訓練的場景下&#xff0c;單一IP地址…

Docker 學習筆記(六):多容器管理與集群部署實踐

Docker Docker-compose 單個 Dockerfile 可定義單容器應用&#xff0c;但日常工作中&#xff0c;Web 項目等常需 Web 服務、數據庫、負載均衡等多容器配合&#xff0c;手動按序啟停容器會導致維護量大、效率低。 Docker Compose 是高效的多容器管理工具&#xff0c;通過單個 do…

C++類和對象初識

面向過程 1.1 面向過程特點 1.2 通俗解釋&#xff1a;煮方便面 1.3 面向過程實現代碼 1.4 特點總結面向對象 2.1 面向對象特點 2.2 通俗解釋&#xff1a;對象協作思維 2.3 面向對象實現代碼 2.4 特點總結面向對象和面向過程總結C 面向對象介紹 4.1 面向對象三大基本特征封裝&am…

C++ Int128 —— 128位有符號整數類實現剖析

&#x1f9e0; C Int128 —— 128位有符號整數類實現剖析 引用&#xff1a;openppp2/ppp/Int128.h &#x1f3d7;? 1. 存儲結構設計 #mermaid-svg-2JDFsdz6MTbX253D {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-sv…

【C 語言生成指定范圍隨機數(整數 + 小數):原理、實現與避坑指南】

概述 在 C 語言開發中&#xff0c;生成指定范圍的隨機數是高頻需求&#xff08;如游戲隨機道具、數據模擬、測試用例生成等&#xff09;。但很多新手會卡在 “范圍控制”“隨機數重復”“小數生成” 等問題上。本文結合實戰場景&#xff0c;從原理到代碼詳細講解如何生成 1100、…

一個簡單的langgraph agent系統

本文基于langgraph的預制件 Agent Chat UI和《搭建一個本地langgraph服務》中的本地服務構建一個簡單的agent系統。 說明&#xff1a;Agent Chat UI需要nodejs版本18及以上&#xff0c;而nodejs18需要的glibc版本為2.28&#xff0c;本人使用操作系統為ubuntu18.04&#xff0c;g…

通過SSH來推送本地文件夾到Github

配置SSH git使用SSH配置&#xff0c; 初始需要以下三個步驟 使用秘鑰生成工具生成rsa秘鑰和公鑰 將rsa公鑰添加到代碼托管平臺 將rsa秘鑰添加到ssh-agent中&#xff0c;為ssh client指定使用的秘鑰文件 具體操作如下&#xff1a; 第一步&#xff1a;檢查本地主機是否已經存在…

視頻轉webp批量處理工具哪個好?這里有答案

你是不是也遇到過這樣的困擾&#xff1a;手機里存滿了精彩的短視頻&#xff0c;想做成動圖分享到社交媒體&#xff0c;卻發現轉換后的GIF文件巨大無比&#xff0c;畫質還慘不忍睹&#xff1f;要怎么把手機視頻轉webp&#xff0c;才能既保持高清畫質&#xff0c;又能大幅減小文件…

【Fastjson】Fastjson2 在不同 Modules 模塊包下,@JSONField name映射無法反序列化的 BUG 及解決

問題&#xff1a;在使用 alibaba fastjson2 做 JSONField 字段名映射時&#xff0c;在同模塊包下 Flink Jar 任務正常映射&#xff0c;本地測試正常映射&#xff0c;但是將兩個模塊包上傳至 Flink Cluster 之后&#xff0c;出現反序列化異常&#xff0c;子模塊無法反序列化父模…

Go語言基礎---數據類型間的故事

Go語言基礎—數據類型間的故事 目錄 前言基本數據類型 整形字節特殊整形unsafe.Sizeof數字字面量語法浮點型布爾值字符串byte和rune類型 運算符 算術運算符關系運算符邏輯運算符位運算符賦值運算符 前言 Go語言是Google開發的一種靜態強類型、編譯型語言。Go語言語法與C相近…

dedecms軟件等級★號改成圖片圖標顯示的辦法

我們在用到dedecms織夢的軟件模型&#xff0c;在調用軟件星級的時候&#xff0c;要把默認的星號改為圖片&#xff0c;這個要怎么操作呢&#xff1f;1、軟件模型管理里面-字段管理-字段配置softrankislink一行改為&#xff1a;<field:softrank itemname軟件等級 typeint isnu…

windows下安裝claude code+國產大模型glm4.5接入(無需科學上網)

下載安裝node.js https://nodejs.org/en/download 安裝版.msi 直接下載安裝即可 免安裝版.zip 1.解壓下載的壓縮包 2.創建數據緩存存儲目錄cache和全局安裝工具目錄global 3.配置環境變量 【我的電腦】右鍵選中【屬性】-> 找到【高級系統設置】-> 右下角【環境變量…

嵌入式 - ARM4

裸機實現LED閃爍一、啟動代碼1. 異常向量表配置1. .global匯編器指令&#xff0c;全局定義標簽_start&#xff0c;作為匯編程序的默認起點2. 配置標簽配置標簽時可以前置加_ &#xff0c;以便和普通標簽或系統標簽做區分3. 異常向量表ARM架構規定異常向量表位置固定&#xff0c…

《C++ 108好庫》之2 多線程庫thread,mutex,condition_variable,this_thread

《C 108好庫》之之2 多線程庫thread&#xff0c;mutex&#xff0c;condition_variable&#xff0c;this_thread《C 108好庫》之2 多線程庫thread&#xff0c;mutex&#xff0c;condition_variable&#xff0c;this_threadstd::thread類??互斥量&#xff08;Mutex&#xff09;…

Android系統框架知識系列(二十):專題延伸:JVM vs ART/Dalvik - Android運行時演進深度解析

?關鍵詞?&#xff1a;運行時優化、AOT編譯、JIT編譯、內存管理、電池效率、性能分析一、Android運行時演進背景1. 移動環境的特殊挑戰Android運行時環境的演進源于移動設備的獨特限制&#xff1a;?移動設備約束條件?&#xff1a;?有限的內存資源?&#xff1a;早期設備僅1…

ubuntu 22 安裝輕量級桌面Xfce并使用xrdp遠程桌面連接

1.安裝Xfce:sudo apt install xubuntu-desktop -y2.安裝xrdp:sudo apt install xrdp -y3.配置xrdp&#xff0c;nano /etc/xrdp/xrdp.ini:[Globals] ... port3389 ; 遠程連接端口&#xff0c;默認是3389&#xff0c;可以改成自己喜歡的端口... ; ; Session types ;; Some sess…

【Flask】測試平臺開發,數據看板開發-第二十一篇

概述&#xff1a;在前面我們已經實現了我們的產品創建管理&#xff0c;應用管理管理&#xff0c;需求提測管理但是每周提測了多少需求&#xff0c;創建了哪些產品&#xff0c;我們是不是看著不是很直觀&#xff0c;接下來我們就需要開發一個數據看板功能&#xff0c;實現能夠看…

我是程序員,不是程序猿:請別把我當猴耍——拒絕被低估,用專業贏得尊重

摘要 本文旨在深度剖析“程序員”與“程序猿”一字之差背后所反映的職業尊嚴與身份認同問題。我們生活在一個技術驅動的時代&#xff0c;但對技術創造者的認知卻常常被“程序猿”、“碼農”等標簽簡單化、甚至矮化。本文將從正名開始&#xff0c;辨析“程序員”的專業內涵&…

C++中vector刪除操作的安全隱患與最佳實踐

std::vector 是C標準模板庫&#xff08;STL&#xff09;中最常用的動態數組容器&#xff0c;提供了高效的隨機訪問和動態擴容能力。然而&#xff0c;其刪除操作如果使用不當&#xff0c;會引入嚴重的安全隱患&#xff0c;包括未定義行為、內存泄漏和數據競爭等問題。本文將深入…

Unix/Linux 系統中的 `writev` 系統調用

<摘要> 本文對 Unix/Linux 系統中的 writev 系統調用進行了全面深入的解析。內容涵蓋了其產生的背景&#xff08;從傳統 write 的局限性到分散/聚集 I/O 概念的引入&#xff09;、核心概念&#xff08;如 struct iovec、系統調用流程&#xff09;。重點剖析了其設計意圖&…