1.線性表
線性表(linear list)是n個具有相同特性的數據元素的有限序列。線性表是一種在實際中廣泛使用的數據結構,常見的線性表:順序表、鏈表、棧、隊列、字符串…
線性表在邏輯上是線性結構,也就說是連續的一條直線。但是在物理結構上并不一定是連續的,線性表在物理上存儲時,通常以數組和鏈式結構的形式存儲。
2.順序表
2.1概念及結構
順序表是用一段物理地址連續的存儲單元依次存儲數據元素的線性結構,一般情況下采用數組存儲。在數組上完成數據的增刪查改。
順序表就是數組,但是在數組的基礎上,它還要數據是連續存儲的,不能跳躍間隔。
#pragma once
#define N 100
typedef int SLDataType;//靜態順序表
typedef struct SeqList
{SLDataType arr[N];int size;//表示數組中存了多少個數據
}SL;//接口函數
//靜態特點:滿了就不讓插入,很難確定給多少空間void SeqListInit(SL* ps);
//尾插
void SeqListPushBack(SL* ps, SLDataType x);
//尾刪
void SeqListPopBack(SL* ps);
//頭插
void SeqListPushFront(SL* ps, SLDataType x);
//頭刪
void SeqListPopFront(SL* ps);
靜態順序表不夠靈活,我們接下來要學習的是動態順序表;
學習動態順序表前先說一個我犯過的錯誤,希望你們可以避一下
所以要傳的是地址
順序表一般可以分為:
1.靜態順序表:使用定長數組存儲元素
2.動態順序表:使用動態開辟的數組存儲
3.順序表的實現
3.1尾插:在順序表末尾插入數據
實現步驟:
1.檢查空間是否足夠,不足需要繼續開辟空間
1.1如果容量為0先分配一個初始容量,后面容量不夠可以進行2倍擴容
1.2通過realloc開辟空間,將這個空間的地址賦值給一個定義的指針變量
1.3如果這個指針變量為NULL,即空間開辟失敗進行相應的保護
1.4令順序表的空間地址等于定義的指針變量,同時將新的容量賦值給原容量
2.空間足夠
2.1將數據直接插入當前順序表尾部
2.2++當前的有效數據個數
void SeqListPushBack(SL* ps, SLDataType x)
{//當空間為0或空間不夠時,要開辟空間if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDataType* tmp=(SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));if (tmp == NULL){perror(realloc);exit(-1);//不可以寫return -1;因為return沒有終止掉程序}ps->a = tmp;ps->capacity = newcapacity;}//空間充足,直接插入數據即可ps->a[ps->size] = x;ps->size++;
}
如果對動態內存管理的函數不太了解可以看看我這一篇文章:
理清C語言中動態內存管理相關函數-CSDN博客
3.2尾刪
直接減小size就行
void SeqListPopBack(SL* ps)
{//兩種方式都可以/*if (ps->size > 0){ps->size--;}*/assert(ps->size > 0);ps->size--;
}
3.3頭插
和尾插一樣,先判斷空間是否充足
為了方便我直接將擴容的功能封裝成一個函數
void SeqListCheckcapacity(SL* ps)
{//當空間為0或空間不夠時,要開辟空間if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));if (tmp == NULL){perror(realloc);exit(-1);//不可以寫return -1;因為return沒有終止掉程序}ps->a = tmp;ps->capacity = newcapacity;}
}
頭插數據最簡單的方法就是把現在數組的數據都往后挪一位,再把要插入的數據放在順序表頭部
void SeqListPushFront(SL* ps, SLDataType x)
{SeqListCheckcapacity(ps);//挪動數據int end = ps->size - 1;while (end >= 0){ps->a[end + 1] = ps->a[end];end--;}ps->a[0] = x;ps->size++;
}
3.4頭刪
從第二個數據開始往前挪,覆蓋第一個數據,然后size-1
void SeqListPopFront(SL* ps)
{assert(ps->size > 0);int start = 0;while (start < ps->size-1){ps->a[start] = ps->a[start + 1];start++;}ps->size--;
}
3.5搜尋數據
遍歷一遍順序表即可
//找到了返回x位置的下標,沒有找到返回-1
int SeqListFind(SL* ps, SLDataType x)
{int j = -1;for (int i = 0; i < ps->size; i++){if (ps->a[i] == x){j = i;}}return j;
}
3.6在指定位置插入數據
和頭插的邏輯一樣,也是將數據往后挪
void SeqListInsert(SL* ps, int pos, SLDataType x)
{assert(pos >= 0 || pos <= ps->size);SeqListCheckcapacity(ps);//空間充足int end = ps->size-1;while (end >=pos){ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = x;ps->size++;}
3.7刪除指定位置的數據
//刪除pos位置的數據
void SeqListErase(SL* ps, int pos)
{SeqListCheckcapacity(ps);int start = pos;while (start < ps->size - 1){ps->a[start] = ps->a[start + 1];start++;}ps->size--;
}
3.9銷毀順序表
void SeqListDestory(SL* ps)
{free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0;
}
完整的工程:
main.c
#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"void TestList1();int main()
{TestList1();return 0;
}void TestList1()
{SL plist;SeqListInit(&plist);SeqListPushBack(&plist, 1);SeqListPushBack(&plist, 2);SeqListPushBack(&plist, 3);SeqListPushBack(&plist, 4);SeqListPushBack(&plist, 5);// ListPushFront(plist, 0);SeqListPrint(&plist);}
SeqList.h
#pragma once //防止重復包含#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int SLDataType;//動態順序表
typedef struct SeqList
{SLDataType* a; //指向開辟數組的指針int size; //表示數組中存了多少個數據int capacity; //數組實際能存數據的空間容量是多大
}SL;//接口函數
//初始化
void SeqListInit(SL* ps);
//尾插
void SeqListPushBack(SL* ps, SLDataType x);
//尾刪
void SeqListPopBack(SL* ps);
//頭插
void SeqListPushFront(SL* ps, SLDataType x);
//頭刪
void SeqListPopFront(SL* ps);
//找到了返回x位置的下標,沒有找到返回-1
int SeqListFind(SL* ps, SLDataType x);
//指定pos下標位置插入
void SeqListInsert(SL* ps, int pos, SLDataType x);
//刪除pos位置的數據
void SeqListErase(SL* ps, int pos);//打印順序表
void SeqListPrint(SL* ps);
//銷毀順序表
void SeqListDestory(SL* ps);
//查看順序表空余的容量
void SeqListCheckcapacity(SL* ps);
SeqList.c
#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"//初始化
void SeqListInit(SL* ps)
{ps->a = NULL;ps->size = ps->capacity = 0;
}void SeqListDestory(SL* ps)
{free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0;
}void SeqListPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}void SeqListCheckcapacity(SL* ps)
{//當空間為0或空間不夠時,要開辟空間if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));if (tmp == NULL){//perror(realloc);exit(-1);//不可以寫return -1;因為return沒有終止掉程序}ps->a = tmp;ps->capacity = newcapacity;}
}//尾插:在順序表末尾插入數據
void SeqListPushBack(SL* ps, SLDataType x)
{//當空間為0或空間不夠時,要開辟空間if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));if (tmp == NULL){//perror(realloc);exit(-1);//不可以寫return -1;因為return沒有終止掉程序}ps->a = tmp;ps->capacity = newcapacity;}//空間充足,直接插入數據即可ps->a[ps->size] = x;ps->size++;
}//尾刪
void SeqListPopBack(SL* ps)
{//兩種方式都可以/*if (ps->size > 0){ps->size--;}*/assert(ps->size > 0);ps->size--;
}//頭插
void SeqListPushFront(SL* ps, SLDataType x)
{SeqListCheckcapacity(ps);//挪動數據int end = ps->size - 1;while (end >= 0){ps->a[end + 1] = ps->a[end];end--;}ps->a[0] = x;ps->size++;
}
//頭刪
void SeqListPopFront(SL* ps)
{assert(ps->size > 0);int start = 0;while (start < ps->size - 1){ps->a[start] = ps->a[start + 1];start++;}ps->size--;
}//找到了返回x位置的下標,沒有找到返回-1
int SeqListFind(SL* ps, SLDataType x)
{int j = -1;for (int i = 0; i < ps->size; i++){if (ps->a[i] == x){j = i;}}return j;
}//指定pos下標位置插入
void SeqListInsert(SL* ps, int pos, SLDataType x)
{assert(pos >= 0 || pos <= ps->size);SeqListCheckcapacity(ps);//空間充足int end = ps->size - 1;while (end >= pos){ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = x;ps->size++;}//刪除pos位置的數據
void SeqListErase(SL* ps, int pos)
{SeqListCheckcapacity(ps);int start = pos;while (start < ps->size - 1){ps->a[start] = ps->a[start + 1];start++;}ps->size--;
}
上一篇:
算法的時間復雜度和空間復雜度_算法復雜度 計算復雜度和存儲復雜度-CSDN博客
下一篇:
(數據結構)鏈表-CSDN博客