1. 程式人生 > 其它 >C語言順序表詳解

C語言順序表詳解

技術標籤:成長c語言資料結構

順序表

順序表是什麼?

順序表是在計算機記憶體中以陣列的形式儲存的線性表,線性表是最基本、最簡單、最常用的一種資料結構。線性表中資料元素之間的關係是一對一的關係。

順序表程式碼構思

建立檔案

首先建立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;
}

最後結果:
在這裡插入圖片描述
寫的不好,大家多多包涵,給我點點贊,支援一下,謝謝。