C語言順序表詳解
阿新 • • 發佈:2021-02-07
順序表
順序表是什麼?
順序表是在計算機記憶體中以陣列的形式儲存的線性表,線性表是最基本、最簡單、最常用的一種資料結構。線性表中資料元素之間的關係是一對一的關係。
順序表程式碼構思
建立檔案
首先建立3個檔案分別是一個頭檔案和二個原始檔
建立結構體
在標頭檔案 SeqLIst.h 裡面寫
建立一個結構體型別,typedef定義一下方便之後寫程式碼,名字隨便取
typedef int SLDataType; //重新命名
typedef struct Seqlist
{
SLDataType* a;
int size; //儲存有效資料
int capacity; //容量
}SL;
在原始檔 test.c 裡面寫
建立一個結構體
int main()
{
SL s; //建立結構體
system("pause");
return 0;
}
初始化
在標頭檔案 SeqLIst.h 裡面寫
void SeqListInit(SL* ps); //初始化
在原始檔 SeqList.c 裡面寫
void SeqListInit(SL* ps) //初始化
{
ps->a = (SLDataType*)malloc(sizeof(SLDataType)*4); //開闢記憶體 16位元組 SLDataType是int 4位元組
if (ps->a == NULL) //如果初始化失敗,就沒有必要繼續下去了
{
printf("申請記憶體失敗\n");
exit(-1); //退出
}
ps->size = 0; //目前容量,因為還沒有使用,所有為0
ps->capacity = 4; //總容量
尾插
在標頭檔案 SeqLIst.h 裡面寫
void SeqListPushBack(SL* ps, SLDataType x); //尾插
在原始檔 SeqList.c 裡面寫
SeqListCapacity(ps);這個擴容函式先不管,後面會說
void SeqListPushBack(SL* ps, SLDataType x) //尾插
{
SeqListCapacity(ps); //擴容
ps->a[ps->size] = x; //size是最大有效資料就是最後一行,直接賦值
ps->size++; //因為尾插了一個數據,所以要增加一個有效資料
}
記憶體擴容
在標頭檔案 SeqList.h 裡面寫
void SeqListCapacity(SL* ps); //記憶體不夠,就擴容
在原始檔 SeqList.c 裡面寫
如果一直插入記憶體就會面臨一個問題,就會越界,這個時候就需要去擴容
ps->size是目前使用記憶體
ps->capacity是所擁有的記憶體
目前使用記憶體大於所擁有記憶體就需要擴容,不然就越界,程式掛掉
void SeqListCapacity(SL* ps) //擴容
{
assert(ps); //斷言
if (ps->size >= ps->capacity) //記憶體如果不夠就擴容
{
ps->capacity *= 2; //提升2被空間,防止不斷申請記憶體
ps->a = (SLDataType*)realloc(ps->a, sizeof(SLDataType)*ps->capacity);//申請新增記憶體
if (NULL == ps->a) //擴容失敗檢查
{
printf("申請空間失敗\n");
exit(-1); //退出
}
}
}
尾刪
在標頭檔案 SeqList.h 裡面寫
void SeqListPopBack(SL* ps);//尾刪
在原始檔 SeqList.c 裡面寫
void SeqListPopBack(SL* ps) //尾刪
{
if (ps->size > 0) //不能小於零,否則變成-1就會出問題,因為如果下次要插入就等於沒有插入
{
ps->size--; //有效資料刪除
}
}
列印
寫了這些程式碼,我們還需要看看實際效果
在標頭檔案 SeqList.h 裡面寫
加上const防止修改,只需要列印就行了
void SeqListprint(const SL* ps); //列印
在原始檔 SeqList.c 裡面寫
void SeqListprint(const SL* ps) //列印
{
int i = 0;
for (i = 0; i < ps->size; i++)
{
printf("%d ",ps->a[i]);
}
}
在main函式裡面寫看看效果
int main()
{
SL s;
SeqListInit(&s); //初始化
SeqListPushBack(&s, 1); //尾插
SeqListPushBack(&s, 2); //尾插
SeqListPushBack(&s, 3); //尾插
SeqListPushBack(&s, 4); //尾插
SeqListPushBack(&s, 5); //尾插第5個數據的時候已經擴容了
SeqListprint(&s); // 列印
printf("尾插兩個資料\n"); //換行
SeqListPopBack(&s);//尾刪
SeqListprint(&s); // 列印
printf("尾刪一個刪除\n"); //換行
system("pause");
return 0;
}
結果:
頭插
在標頭檔案 SeqList.h 裡面寫
void SeqListPushFront(SL* ps, SLDataType x); //頭插
在原始檔 SeqList.c 裡面寫
void SeqListPushFront(SL*ps, SLDataType x) //頭插入
{
int i = 0;
SLDataType* tmp = NULL; //交換容器
SeqListCapacity(ps); //檢查擴容
ps->size++; //增加有效資料
for (i = 0; i < ps->size;i++) //因為頭插在最前面,所以需要迴圈ps->size次
{
tmp = ps->a[ps->size - i]; //從後向前交換,不會覆蓋掉資料
ps->a[ps->size - i] = ps->a[ps->size - i -1];
ps->a[ps->size - i - 1] = tmp;
}
ps->a[0] = x; //頭插入資料
}
頭刪
在標頭檔案 SeqList.h 裡面寫
void SeqListPopFront(SL* ps);//頭刪
在原始檔 SeqList.c 裡面寫
void SeqListPopFront(SL* ps)//頭刪
{
SLDataType* tmp = NULL;
int i = 0;
for (i = 0; i < ps->size; i++)
{
tmp = ps->a[i]; //從前向後交換
ps->a[i] = ps->a[i + 1];
ps->a[i + 1] = tmp;
}
ps->size--; //刪除-1;
}
任意位置插入
在標頭檔案 SeqList.h 裡面寫
void SeqListInsert(SL* ps, int pos, SLDataType x); //中間插入 pos要插入的位置
在原始檔 SeqList.c 裡面寫
void SeqListInsert(SL* ps, int pos, SLDataType x) //中間插入
{
SeqListCapacity(ps); //檢查擴容
SLDataType* tmp = NULL;
int i = 0;
if (pos > 0 && pos <= ps->size) //判斷插入位置是否合理
{
pos--; //非程式設計師心理,不可能從0開始想
ps->size++; //插入就要加一個位置
for (i = 0; i < ps->size-pos; i++) //互換次數
{
tmp = ps->a[ps->size-i]; //從後向前交換
ps->a[ps->size - i] = ps->a[ps->size - i - 1];
ps->a[ps->size - i - 1] = tmp;
}
ps->a[pos] = x; //插入要插入的位置
}
else
{
printf("插入的位置有誤\n");
}
}
任意位置刪除
在標頭檔案 SeqList.h 裡面寫
void SeqListDelete(SL* ps, int pos);//任意位置刪除 //pos要刪除的位置
在原始檔 SeqList.c 裡面寫
void SeqListDelete(SL* ps, int pos) //任意位置刪除
{
SLDataType* tmp = NULL;
int i = 0;
if (pos > 0 && pos <= ps->size) //判斷刪除位置是否合理
{
pos--; //使用者心理,不可能從0開始想
for (i = 0; i < ps->size - pos; i++)
{
tmp = ps->a[pos + i]; //交換
ps->a[pos + i] = ps->a[pos + 1 + i];
ps->a[pos + 1 + i] = tmp;
}
ps->size--; //有效資料刪除 假刪除
}
}
解釋的不好,最後獻上完整程式碼
標頭檔案 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 SeqListCapacity(SL* ps); //記憶體不夠,擴容
void SeqListprint(const SL* ps); //列印
void SeqListPushBack(SL* ps, SLDataType x); //尾插
void SeqListPopBack(SL* ps);//尾刪
void SeqListPushFront(SL* ps, SLDataType x); //頭插
void SeqListPopFront(SL* ps);//頭刪
void SeqListInsert(SL* ps, int pos, SLDataType x); //任意插入 //pos要插入的位置
void SeqListDelete(SL* ps, int pos);//任意位置刪除 //pos要刪除的位置
原始檔 SeqList.c 程式碼
#include"SeqLIst.h"
void SeqListprint(const SL* ps) //列印
{
int i = 0;
for (i = 0; i < ps->size; i++)
{
printf("%d ",ps->a[i]);
}
}
void SeqListInit(SL* ps) //初始化
{
ps->a = (SLDataType*)malloc(sizeof(SLDataType)*4); //開闢記憶體 16位元組 SLDataType是int 4位元組
if (ps->a == NULL)
{
printf("申請記憶體失敗\n");
exit(-1);
}
ps->size = 0;
ps->capacity = 4;
}
void SeqListCapacity(SL* ps) //擴容
{
assert(ps);
if (ps->size >= ps->capacity) //記憶體如果不夠就擴容
{
ps->capacity *= 2; //提升2被空間,防止不斷申請記憶體
ps->a = (SLDataType*)realloc(ps->a, sizeof(SLDataType)*ps->capacity);
if (NULL == ps->a) //擴容檢查
{
printf("申請空間失敗\n");
exit(-1);
}
}
}
void SeqListPushBack(SL* ps, SLDataType x) //尾插
{
SeqListCapacity(ps); //擴容
ps->a[ps->size] = x; //size是最大有效資料就是最後一行
ps->size++;
}
void SeqListPopBack(SL* ps) //尾刪
{
if (ps->size > 0) //不能小於零,否則變成-1就會出問題
{
ps->size--;
}
}
void SeqListPushFront(SL*ps, SLDataType x) //頭插入
{
int i = 0;
SLDataType* tmp = NULL;
SeqListCapacity(ps); //擴容
ps->size++; //增加有效資料
for (i = 0; i < ps->size;i++)
{
tmp = ps->a[ps->size - i]; //交換
ps->a[ps->size - i] = ps->a[ps->size - i -1];
ps->a[ps->size - i - 1] = tmp;
}
ps->a[0] = x; //頭插入資料
}
void SeqListPopFront(SL* ps)//頭刪
{
SLDataType* tmp = NULL;
int i = 0;
for (i = 0; i < ps->size; i++)
{
tmp = ps->a[i]; //交換
ps->a[i] = ps->a[i + 1];
ps->a[i + 1] = tmp;
}
ps->size--; //刪除-1;
}
void SeqListInsert(SL* ps, int pos, SLDataType x) //中間插入
{
SeqListCapacity(ps); //檢查擴容
SLDataType* tmp = NULL;
int i = 0;
if (pos > 0 && pos <= ps->size) //判斷插入位置是否合理
{
pos--; //使用者心理,不可能從0開始想
ps->size++; //插入就要加一個位置
for (i = 0; i < ps->size-pos; i++) //互換次數
{
tmp = ps->a[ps->size-i]; //交換
ps->a[ps->size - i] = ps->a[ps->size - i - 1];
ps->a[ps->size - i - 1] = tmp;
}
ps->a[pos] = x; //插入要插入的位置
}
else
{
printf("插入的位置有誤\n");
}
}
void SeqListDelete(SL* ps, int pos) //中間刪除
{
SLDataType* tmp = NULL;
int i = 0;
if (pos > 0 && pos <= ps->size) //判斷刪除位置是否合理
{
pos--; //使用者心理,不可能從0開始想
for (i = 0; i < ps->size - pos; i++)
{
tmp = ps->a[pos + i]; //交換
ps->a[pos + i] = ps->a[pos + 1 + i];
ps->a[pos + 1 + i] = tmp;
}
ps->size--; //有效資料刪除 假刪除
}
}
原始檔 test.c 程式碼
#include"SeqLIst.h"
int main()
{
SL s;
SeqListInit(&s); //初始化
SeqListPushBack(&s, 1); //尾插
SeqListPushBack(&s, 2); //尾插
SeqListPushBack(&s, 3); //尾插
SeqListPushBack(&s, 4); //尾插
SeqListPushBack(&s, 5); //尾插第5個數據的時候已經擴容了
SeqListprint(&s); // 列印
printf("尾插兩個資料\n"); //換行
SeqListPopBack(&s);//尾刪
SeqListprint(&s); // 列印
printf("尾刪一個刪除\n"); //換行
SeqListInsert(&s, 3, 20); //任意位置插入
SeqListprint(&s); // 列印
printf("任意位置插入\n");
SeqListDelete(&s, 2); //任意位置刪除
SeqListprint(&s); // 列印
printf("任意位置刪除\n");
system("pause");
return 0;
}
最後結果:
寫的不好,大家多多包涵,給我點點贊,支援一下,謝謝。