【データ構造とアルゴリズム】 静的・動的シーケンステーブルを線形テーブルで実現

この記事はデータ構造の始まりです。上では、C 言語を使用してアドレス帳に静的、動的、およびファイル操作を実装する方法について学びました。構造のタイプはその中で使用されます。実際には、次のいずれかに属することができます。データ構造の内容 次に、シーケンステーブルについて学びます。


目次

序文

1. リニアテーブル

1. シーケンステーブルとは何ですか?

第二に、解析順序表の実現

3. 静的シーケンステーブル

1. シーケンステーブルの初期化

2.要素を追加する

1.テールプラグ

2.プラグ

3. 要素を削除する

1. 末尾の削除

2. 先頭削除

4. データの変更と検索

5. シーケンステーブルの印刷と破棄

4. ダイナミックシーケンステーブル

1. 初期化

2. 拡張

3. 破壊順序表

5. 完全なコードデモ

1. 静的シーケンステーブル

1.test.c

2.Seqtable.h

3.Seqtable.c

2. ダイナミックシーケンステーブル

1.test.c

2.Seqtable.h

3.Seqtable.c

要約する


序文

データ構造とは何ですか?

誰にとっても、これはまったく新しいコンテンツ モジュールです。データ構造とは、コンピュータがデータを保存および整理する方法です。データ構造は、相互に 1 つ以上の特定の関係を持つデータ要素のコレクションです。多くの場合、データ構造を適切に選択すると、操作効率やストレージ効率が向上しますデータ構造は、多くの場合、効率的な検索アルゴリズムインデックス付け技術に関連付けられています。

次に、データ構造のシーケンステーブルの実装について説明します。


1. リニアテーブル

線形リストは、同じプロパティを持つ n データ要素の有限シーケンスです。線形テーブルは実際に広く使用されているデータ構造であり、一般的な線形テーブル: シーケンシャル リスト、リンク リスト、スタック、キュー、文字列...

線形テーブルは論理的には線形構造、つまり連続した直線です。しかし、物理的な構造は必ずしも連続的であるとは限らず、線形テーブルを物理的に保存する場合、通常は配列や連鎖構造の形で保存される。

実際、シーケンス テーブルとリンク リストを学習すると、スタック、キュー、バイナリ ツリーなどのさまざまな構造を簡単に学ぶことができます。これらはシーケンス テーブルやリンク リストとも呼ばれ、データ構造の基礎であり、ポストシーケンスコンテンツの実現。

1. シーケンステーブルとは何ですか?

1. テーブルの要素を 1 つずつ連続した記憶単位のグループに格納します(この記憶構造はシーケンシャル構造です)。

2. 逐次構造に格納された線形テーブルを逐次テーブルと呼びます。

要約:

順序テーブルは、データ要素を連続した物理アドレスで記憶装置に順次格納する線形構造であり、一般的には配列で格納される。アレイ上のデータを追加、削除、確認、変更します。

第二に、解析順序表の実現

シーケンステーブルは動的シーケンステーブルと静的シーケンステーブルに分かれており、シーケンステーブルの実際の操作機能は大きく分けて追加、削除、変更、確認、さらに先頭と末尾の追加、削除、初期化、シーケンスの破棄などの操作に分かれます。テーブル。

次に、静的および動的シーケンス テーブルがどのように実装されるかを紹介しましょう。

3. 静的シーケンステーブル

使用される構造は次のとおりです。

1. シーケンステーブルの初期化

写真が示すように:

コードデモ:

//初始化函数
void InitSeqtable(Seqtable* st) {
	//for (int i = 0; i < MAX; i++) {
	//	st->date[i] = 0;//初始化为0  实际上可以不用初始化数组
	//}
	st->size = 0;
}

2.要素を追加する

頭挿入と尻挿入に分かれる

1.テールプラグ

写真が示すように:

コードデモ:

//尾插入
void BackSeqtable(Seqtable* st, int data) {
	//尾部插入的时候要进行判别是否为满
	if (st->size == MAX) {
		//表示满了
		perror("顺序表已经满员,无法插入新数据\n");
		exit(-1);//退出就可以
	}
	//没有满员,就加入数据即可
	st->date[st->size++] = data;
}

2.プラグ

写真が示すように:

 コードは以下のように表示されます:

//头插入
void FrontSeqtable(Seqtable* st, int data) {
	//一样先进行判断是否满员
	if (st->size == MAX) {
		perror("满员无法插入");
		exit(-1);
	}
	//头部插入。就是将原有数据向后移动一个位置
	int num = st->size - 1;
	for (int i = num; i>=0; i--) {
		st->date[i + 1] = st->date[i];
	}
	//while (num>=0) {
	//	st->date[num + 1] = st->date[num];
	//	num--;
	//}
	//最后插入数据
	st->date[0] = data;
	st->size++;
}

3. 要素を削除する

先頭削除と末尾削除に分かれる

1. 末尾の削除

写真が示すように:

 コードは以下のように表示されます:

//尾删除
void SeqtablePopBack(Seqtable* st) {
	//尾删除,需要判断是否为空
	assert(st->size > 0);//断言判断
	st->size--;//直接元素个数减去一个就可以

}

2. 先頭削除

写真が示すように:

 コードは以下のように表示されます:

//头删除
void SeqtablePopFront(Seqtable* st) {
	//头部删除,也要判空
	assert(st->size > 0);//断言
	//将后面的数据覆盖前面的数据
	for (int i = 0; i < st->size-1; i++) {
		st->date[i] = st->date[i + 1];
	}
	st->size--;//size减去一个元素即可
}

4. データの変更と検索

指定した添え字のデータを変更したい場合は、検索したい要素を入力してデータを変更します。まず対応する座標を検索し、値を簡単に変更し、重複の問題を考慮せず、順番にクエリする必要があります。左から右へ

コードは以下のように表示されます:

//查找
int SearchSeqtable(Seqtable* st) {
	assert(st->size > 0);//如果为空,不用查找,直接报错
	int num = 0;
	scanf("%d", &num);//输入查找的元素
	for (int i = 0; i < st->size; i++) {
		if (st->date[i] == num) {
			return i;//找到返回下标
		}
	}
	return -1;//没找到返回-1
	
}

void ChangeSeqtable(Seqtable* st) {
	int num=SearchSeqtable(st);//进入查找,返回下标
	if (num == -1) {
		printf("顺序表中没有该元素,无法修改\n");
		return;
	}
	int a = 0;
	scanf("%d", &a);//输入想要更改的数据
	st->date[num] = a;
}

5. シーケンステーブルの印刷と破棄

コードは以下のように表示されます:

//摧毁顺序表
void SeqtableDestory(Seqtable* st) {
	//摧毁的话,静态表直接初始化为0
	st->size = 0;
}

//打印
void PrintSeqtable(Seqtable* st) {
	for (int i = 0; i < st->size; i++) {
		printf("%d ", st->date[i]);
	}
}

4. ダイナミックシーケンステーブル

動的シーケンステーブルと静的シーケンステーブルの違いは、シーケンステーブルの構造、初期化、破壊、拡張です。

構造は次のとおりです。

//动态顺序表
typedef struct Seqtable {
	int* data;//数据域
	int size;//个数
	int capacity;//容量
}Seqtable;

//实际上动态顺序表和静态顺序表,只有在初始化、销毁、扩容的时候不一样

1. 初期化

//初始化顺序表
void InitSeqtable(Seqtable* st) {
	st->size = st->capacity = 0;
	st->data = NULL;
}

2. 拡張

写真が示すように: 

コードデモ:

//扩容
void Expansion(Seqtable* st) {
	//1.直接扩容二倍,这样防止后序一致扩容
	int newcapacity = st->capacity = 0 ? 4 : st->capacity * 2;
	int* tmp = (int*)realloc(st->data, newcapacity * sizeof(int));
	if (tmp == NULL) {
		//表示创建失败
		perror("realloc fail\n");
		exit(-1);
	}
	//创建成功  tmp给data
	st->data = tmp;
	st->capacity = newcapacity;
}

図に示すように、別の拡張方法については、動的アドレス帳の拡張に関するこの記事で説明されています(メッセージ数 24 件) [C 言語] C 言語を使用して静的および動的アドレス帳を実現する (わかりやすい)_小Wang Xuecode のブログ - CSDN ブログ

3. 破壊順序表

void SeqListDestory(Seqtable* ps) {
	free(ps->data);//直接释放a的空间 
	ps->data = NULL;//然后指向NULL
	ps->capacity = ps->size = 0;
}

なお、静的シーケンステーブルとほぼ同じです。

5. 完全なコードデモ

1. 静的シーケンステーブル

いわゆる静的とは、シーケンス テーブル内の記憶要素の最大数が変更できない、多く残っている、または十分ではない可能性があることを意味します。

1.test.c

main関数の使い方

#define _CRT_SECURE_NO_WARNINGS
#include"Seqtable.h"
//实现顺序表
void test1()
{
	Seqtable st;
	InitSeqtable(&st);//初始化
	//尾插
	BackSeqtable(&st, 1);
	BackSeqtable(&st, 2);
	BackSeqtable(&st, 3);
	BackSeqtable(&st, 4);
	BackSeqtable(&st, 5);
	//打印
	PrintSeqtable(&st);
	printf("\n");
	//头插
	FrontSeqtable(&st, 1);
	FrontSeqtable(&st, 2);
	FrontSeqtable(&st, 3);
	FrontSeqtable(&st, 4);
	FrontSeqtable(&st, 5);
	PrintSeqtable(&st);
	//尾巴删除
	SeqtablePopBack(&st);
	SeqtablePopBack(&st);
	SeqtablePopBack(&st);
	SeqtablePopBack(&st);
	SeqtablePopBack(&st);
	printf("\n");
	//打印
	PrintSeqtable(&st);
	//头删除
	SeqtablePopFront(&st);
	printf("\n");
	//打印
	PrintSeqtable(&st);

	摧毁顺序表
	//SeqtableDestory(&st);
	printf("\n");
	//打印
	ChangeSeqtable(&st);
	PrintSeqtable(&st);
}
int main()
{	//实现静态顺序表
	test1();
	return 0;
}

2.Seqtable.h

ヘッダーファイルの使用

#define _CRT_SECURE_NO_WARNINGS

//头文件,进行函数的声明
//		结构体的实现

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>

#define MAX 100
//静态顺序表的实现
typedef struct Seqtable {
	int date[MAX];//数据域
	int size;//数据个数
}Seqtable;



//实现函数声明

//初始化函数
void InitSeqtable(Seqtable* st);

//尾插入
void BackSeqtable(Seqtable* st, int data);

//头插入
void FrontSeqtable(Seqtable* st, int data);

//尾删除
void SeqtablePopBack(Seqtable* st);

//头删除
void SeqtablePopFront(Seqtable* st);

//摧毁顺序表
void SeqtableDestory(Seqtable* st);

//打印
void PrintSeqtable(Seqtable* st);

//查找指定元素
//有 返回 下标
//没有 返回 -1

int SearchSeqtable(Seqtable* st);
//更改数据
void ChangeSeqtable(Seqtable* st);

3.Seqtable.c

関数の実装

#define _CRT_SECURE_NO_WARNINGS
#include"Seqtable.h"
//实现方法
//顺序表的,头插尾插,头删尾删
//初始化,和销毁

//静态顺序表

//初始化函数
void InitSeqtable(Seqtable* st) {
	for (int i = 0; i < MAX; i++) {
		st->date[i] = 0;//初始化为0  实际上可以不用初始化数组
	}
	st->size = 0;
}
//尾插入
void BackSeqtable(Seqtable* st, int data) {
	//尾部插入的时候要进行判别是否为满
	if (st->size == MAX) {
		//表示满了
		perror("顺序表已经满员,无法插入新数据\n");
		exit(-1);//退出就可以
	}
	//没有满员,就加入数据即可
	st->date[st->size++] = data;
}
//头插入
void FrontSeqtable(Seqtable* st, int data) {
	//一样先进行判断是否满员
	if (st->size == MAX) {
		perror("满员无法插入");
		exit(-1);
	}
	//头部插入。就是将原有数据向后移动一个位置
	int num = st->size - 1;
	for (int i = num; i>=0; i--) {
		st->date[i + 1] = st->date[i];
	}
	//while (num>=0) {
	//	st->date[num + 1] = st->date[num];
	//	num--;
	//}
	//最后插入数据
	st->date[0] = data;
	st->size++;
}

//尾删除
void SeqtablePopBack(Seqtable* st) {
	//尾删除,需要判断是否为空
	assert(st->size > 0);//断言判断
	st->size--;//直接元素个数减去一个就可以

}
//头删除
void SeqtablePopFront(Seqtable* st) {
	//头部删除,也要判空
	assert(st->size > 0);//断言
	//将后面的数据覆盖前面的数据
	for (int i = 0; i < st->size-1; i++) {
		st->date[i] = st->date[i + 1];
	}
	st->size--;//size减去一个元素即可
}
//摧毁顺序表
void SeqtableDestory(Seqtable* st) {
	//摧毁的话,静态表直接初始化为0
	st->size = 0;
}

//打印
void PrintSeqtable(Seqtable* st) {
	for (int i = 0; i < st->size; i++) {
		printf("%d ", st->date[i]);
	}
}

//查找
int SearchSeqtable(Seqtable* st) {
	assert(st->size > 0);//如果为空,不用查找,直接报错
	int num = 0;
	scanf("%d", &num);//输入查找的元素
	for (int i = 0; i < st->size; i++) {
		if (st->date[i] == num) {
			return i;//找到返回下标
		}
	}
	return -1;//没找到返回-1
	
}

void ChangeSeqtable(Seqtable* st) {
	int num=SearchSeqtable(st);//进入查找,返回下标
	if (num == -1) {
		printf("顺序表中没有该元素,无法修改\n");
		return;
	}
	int a = 0;
	scanf("%d", &a);//输入想要更改的数据
	st->date[num] = a;
}

2. ダイナミックシーケンステーブル

いわゆる動的とは、realloc などの関数を使用して動的に領域を解放し、シーケンス テーブルの領域を合理的にしようとすることです。

1.test.c

シーケンステーブルをテストして使用するための主な機能

#define _CRT_SECURE_NO_WARNINGS
#include"动态顺序表.h"

void test2() {
	Seqtable st;
	InitSeqtable(&st);//初始化
	//尾插
	BackSeqtable(&st, 1);
	BackSeqtable(&st, 2);
	BackSeqtable(&st, 3);
	BackSeqtable(&st, 4);
	BackSeqtable(&st, 5);
	//打印
	PrintSeqtable(&st);
	printf("\n");
	//头插
	FrontSeqtable(&st, 1);
	FrontSeqtable(&st, 2);
	FrontSeqtable(&st, 3);
	FrontSeqtable(&st, 4);
	FrontSeqtable(&st, 5);
	PrintSeqtable(&st);
	//尾巴删除
	SeqtablePopBack(&st);
	SeqtablePopBack(&st);
	SeqtablePopBack(&st);
	SeqtablePopBack(&st);
	SeqtablePopBack(&st);
	printf("\n");
	//打印
	PrintSeqtable(&st);
	//头删除
	SeqtablePopFront(&st);
	printf("\n");
	//打印
	PrintSeqtable(&st);
	摧毁顺序表
	SeqListDestory(&st);
	//printf("\n");
	打印
	//PrintSeqtable(&st);
}

int main()
{
	test2();
	return 0;
}

2.Seqtable.h

関数の宣言と構造体の作成

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>
//动态顺序表
typedef struct Seqtable {
	int* data;//数据域
	int size;//个数
	int capacity;//容量
}Seqtable;

//实际上动态顺序表和静态顺序表,只有在初始化、销毁、扩容的时候不一样


//实现函数声明

//初始化函数
void InitSeqtable(Seqtable* st);

//尾插入
void BackSeqtable(Seqtable* st, int data);

//头插入
void FrontSeqtable(Seqtable* st, int data);

//尾删除
void SeqtablePopBack(Seqtable* st);

//头删除
void SeqtablePopFront(Seqtable* st);

//摧毁顺序表
void SeqtableDestory(Seqtable* st);

//打印
void PrintSeqtable(Seqtable* st);

//查找
int SearchSeqtable(Seqtable* st);
//更改
void ChangeSeqtable(Seqtable* st);


3.Seqtable.c

コード:

#define _CRT_SECURE_NO_WARNINGS
#include"动态顺序表.h"
//动态顺序表

//初始化顺序表
void InitSeqtable(Seqtable* st) {
	st->size = st->capacity = 0;
	st->data = NULL;
}
//扩容
void Expansion(Seqtable* st) {
	//1.直接扩容二倍,这样防止后序一致扩容
	int newcapacity = st->capacity = 0 ? 4 : st->capacity * 2;
	int* tmp = (int*)realloc(st->data, newcapacity * sizeof(int));
	if (tmp == NULL) {
		//表示创建失败
		perror("realloc fail\n");
		exit(-1);
	}
	//创建成功  tmp给data
	st->data = tmp;
	st->capacity = newcapacity;
}

//尾插入
void BackSeqtable(Seqtable* st, int data) {
	//判断是否满员
	if (st->size == st->capacity) {
		//满员进行扩容
		//两个方法
		//1.直接扩容二倍,这样防止后序一致扩容
		Expansion(st);
	}
	//如果没有满员,就正常使用
	st->data[st->size++] = data;
}
//头插入
void FrontSeqtable(Seqtable* st, int data) {
	//使用动态的
	if (st->size == st->capacity) {
		Expansion(st);
	}
	int end = st->size - 1;
	while (end >= 0) {
		st->data[end + 1] = st->data[end];
		--end;
	}
	st->data[0] = data;
	st->size++;
}
//尾删除
void SeqtablePopBack(Seqtable* st) {
	//尾删除,需要判断是否为空
	assert(st->size > 0);//断言判断
	st->size--;//直接元素个数减去一个就可以

}
//头删除
void SeqtablePopFront(Seqtable* st) {
	//头部删除,也要判空
	assert(st->size > 0);//断言
	//将后面的数据覆盖前面的数据
	for (int i = 0; i < st->size - 1; i++) {
		st->data[i] = st->data[i + 1];
	}
	st->size--;//size减去一个元素即可
}
//打印
void PrintSeqtable(Seqtable* st) {
	for (int i = 0; i < st->size; i++) {
		printf("%d ", st->data[i]);
	}
}
//摧毁动态顺序表
//void SeqtableDestory(Seqtable* st) {
//	//先释放空间
//	free(st->data);
//	st->data = NULL;
//	free(st);
//	st->size = st->capacity = 0;
//}
void SeqListDestory(Seqtable* ps) {
	free(ps->data);//直接释放a的空间 
	ps->data = NULL;//然后指向NULL
	ps->capacity = ps->size = 0;
}

//查找
int SearchSeqtable(Seqtable* st) {
	assert(st->size > 0);//如果为空,不用查找,直接报错
	int num = 0;
	scanf("%d", &num);//输入查找的元素
	for (int i = 0; i < st->size; i++) {
		if (st->data[i] == num) {
			return i;//找到返回下标
		}
	}
	return -1;//没找到返回-1

}

void ChangeSeqtable(Seqtable* st) {
	int num = SearchSeqtable(st);//进入查找,返回下标
	if (num == -1) {
		printf("顺序表中没有该元素,无法修改\n");
		return;
	}
	int a = 0;
	scanf("%d", &a);//输入想要更改的数据
	st->data[num] = a;
}

要約する

今回は線形テーブルにおける数列テーブルの使い方について説明しました.データ構造の基礎となる静的数列テーブルと動的数列テーブルをそれぞれ実装しました.次に説明するのは線形テーブルにおけるリンクリストです.

さて、本文はこれで終わりです。この間の励ましとサポートに感謝します。Xiao Wang はコードを学ぶために引き続き努力します。一緒に頑張りましょう!

おすすめ

転載: blog.csdn.net/qq_63319459/article/details/128760646