データ構造とアルゴリズム(線形テーブル)
線形テーブル(線形ストレージ構造)
データをつなぎ合わせて物理アドレスに保存することです。「1対1」の関係にあるデータは、物理空間に「線形」に格納されます。この格納構造は、線形格納構造(線形テーブルと呼ばれます)と呼ばれます。
シーケンシャルストレージ構造
図3aに示すように、データは連続する物理アドレスに格納されます。シーケンステーブルにデータが格納されている場合、すべてのデータは連続したアドレスに格納され、間にギャップはありません。
シーケンステーブルの初期化
シーケンステーブルを使用する前に、スペースを申請し、要求されたストレージ容量とデータ要素の数をテーブルに記録する必要があります。
- 線形テーブルを定義し、その中に要素を配置します
#include <stdio.h>
#include <stdlib.h>
typedef struct Table{
int * head;
int length;
int size;
}table;
table initTable(){
table t;
t.head=(int*)malloc(5*sizeof(int));
if(!t.head){
printf("初始化失败");
exit(0);
}else{
printf("初始化成功!");
}
t.length=0;
t.size=5;
return t;
}
int main(int argc, char *argv[]) {
table t=initTable();
printf("表的大小为%d",t.length);
int i;
for(i=0;i<5;i++){
t.head[i]=i;
t.length++;
}
for(i=0;i<t.size;i++){
printf("\n");
printf("%d",t.head[i]);
}
return 0;
}
シーケンステーブル挿入要素
- ヘッダーに挿入
- 表の最後に挿入します
- 途中で
要素を挿入するには、挿入する位置の要素とそれに続く要素全体を後方に移動し、要素を空の位置に追加するという2つの操作を実行します。
// 在指定位置插入元素
table addElement(table t,int element,int pos){
// 插在表尾部
if(pos==t.length){
// 重新申请大小
t.head=(int*)realloc(t.head,(t.size+1)*sizeof(int));
if(!t.head){
printf("扩容失败!");
return t;
}
t.size+=1;
}
if(pos>t.size+1 || pos<1){
printf("插入位置错误");
exit(0);
}
// 将插入位置以及之后的元素向后移动
int i;
for(i=t.length-1;i>=pos-1;i--){
t.head[i+1]=t.head[i];
}
// 将元素放到空的位置
t.head[pos-1]=element;
t.length++;
return t;
}
シーケンステーブル削除要素
指定された削除位置の後の要素を1つ前方に移動するだけで、値として指定された線形テーブルが削除されます。
table delTable(table t, int add) {
int i;
if (add > t.length || add < 1) {
printf("被删除元素的位置有误");
exit(0);
}
//删除操作
for (i = add; i < t.length; i++) {
t.head[i - 1] = t.head[i];
}
t.length--;
return t;
}
要素を見つける
-
ターゲット要素を見つけます。
-
要素の値を直接変更します。
//更改函数,其中,elem为要更改的元素,newElem为新的数据元素
table amendTable(table t, int elem, int newElem) {
int add = selectTable(t, elem);
t.head[add - 1] = newElem;//由于返回的是元素在顺序表中的位置,所以-1就是该元素在数组中的下标
return t;
}
チェーン収納構造
図3bに示すように、番号データは物理アドレスに格納されますが、データの順序は変更されず、データ間の論理的な順序は1行で維持されます。
チェーンストレージの特徴
データ要素を格納するために、任意のストレージユニットのグループが使用されます。このストレージユニットのグループは、連続的または非連続的です。
リンクリスト
リンクリストの概念
- データドメイン:データ要素情報を格納するドメインは、データドメインと呼ばれます。
- ポインタフィールド:直後の後続の位置を格納するフィールドは、ポインタフィールドと呼ばれます。
- n個のノードがリンクリストにリンクされます。これは線形リストのチェーンストレージ構造です。
単一のリスト
リンクリストの各ノードにはポインタフィールドが1つだけ含まれ、ポインタフィールドに格納されている情報はチェーンと呼ばれ、チェーンの各ノードには1つしかありません。リンクリストの最初のノードの保存場所はヘッドポインタと呼ばれます。リンクリストにヘッドノードがある場合、ヘッドポインタはヘッドノードのデータフィールドへのポインタです。
ノードの定義
// 定义链表
typedef struct Node{
// 数据域
Item item;
// 指向后继节点的指针
struct Node *next;
}Node,*List;
データ構造
/*数据域的数据结构体*/
typedef struct Contet{
int id;
char name[20];
}Item;
リンクリストを初期化する
// 初始化一个链表
List init(){
// 定义头节点
List head=(List)malloc(sizeof(Node));
if(!head){
printf("分配内存空间失败!");
return 0;
}else{
printf("内存分配成功链表创建!");
// 指针域为空
head->next=NULL;
return head;
}
}
リンクリストにデータを追加する
// 增加数据
void insert(List head){
// 定义新的节点对象
Item item;
printf("输入编号:");
scanf("%d",&item.id);
printf("输入姓名:");
scanf("%s",&item.name);
// 清空缓冲区
getchar();
List p=(List)malloc(sizeof(Node));
p->item=item;
p->next=head->next;
head->next=p;
}
リンクリストからデータを削除する
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
/*数据域的数据结构体*/
typedef struct Contet{
int id;
char name[20];
}Item;
// 定义链表
typedef struct Node{
// 数据域
Item item;
// 指向后继节点的指针
struct Node *next;
}Node,*List;
// 初始化一个链表
List init(){
// 定义头节点
List head=(List)malloc(sizeof(Node));
if(!head){
printf("分配内存空间失败!");
return 0;
}else{
printf("内存分配成功链表创建!");
printf("\n");
// 指针域为空
head->next=NULL;
return head;
}
}
// 增加数据
void insert(List head){
// 定义新的节点对象
Item item;
printf("输入编号:");
scanf("%d",&item.id);
printf("输入姓名:");
scanf("%s",&item.name);
// 清空缓冲区
getchar();
List p=(List)malloc(sizeof(Node));
p->item=item;
p->next=head->next;
head->next=p;
}
int main(int argc, char *argv[]) {
// 初始化链表
List head=init();
int n;
printf("输入你想录入数据的个数:");
scanf("%d",&n);
int i;
for(i=0;i<n;i++){
insert(head);
}
Item *p;
p=head->next;
printf("当前人编号:%d",p->id);
printf("当前人姓名:%s",p->name);
return 0;
}
アレイ
javaでは、配列が作成されると、連続するメモリがメモリに分割され、データが入力されると、データはこの連続するメモリに順番に格納されます。アレイ内のデータを読み取る必要がある場合は、アレイ内のインデックスを指定する必要があります。その後、アレイはインデックスに従ってメモリ内のデータを取り出し、読み取りプログラムに返します。Javaでは、すべてのデータを配列に格納できるわけではなく、同じタイプのデータのみを一緒に配列に格納できます。
特徴
- 保存順序は順番に保存され、データを保存するためのメモリも連続しています。
- データのアドレス指定と読み取りは簡単ですが、挿入と削除はより困難です。
応用
動的配列ArrayList
- ArratListは動的配列と同等であり、拡張をサポートします。
- アレイを定義するときは、連続したメモリスペースを割り当てる必要があるため、事前にサイズを指定する必要があります。保存するデータがサイズよりも大きい場合は、より大きなスペースを割り当て、元のスペースをコピーして、新しいものを挿入する必要があります。要素。
- ArrayListでは、スペースが十分でない場合、元のサイズの1.5倍に自動的に拡張されます。
静的配列
- Javaで配列を定義するには、次の2つの構文があります
。typearrayName[];
type [] arrayName;
キュー
キューは先着順のデータ構造であり、配列とリンクリストもキューを生成できます。データがキューに入ると、最初に入力され、次に下に入力され、次に上に入力されますが、キューを離れるときは、最初に下から出力され、次に上のデータ、最後に入力されて最後に出力されます。
@Test
public void test(){
Queue<Integer> queue=new LinkedList<>();
queue.offer(1);
queue.offer(2);
queue.offer(3);
queue.offer(4);
queue.offer(5);
queue.offer(6);
queue.forEach(System.out::println);
}
ブロッキングキュー
同時キュー
スタック
スタックはファーストインラストアウトのデータ構造であり、アレイとリンクリストの両方でスタックを生成できます。データがスタックに入ると、ルールに従ってスタックの一番下にプッシュされ、再度入力されたデータは最初のデータの上にプッシュされます。スタック内のデータをフェッチするときは、最上位のデータが最初にフェッチされるため、最初から最後までです。
@Test
public void test1(){
Stack<Integer> stack=new Stack<>();
stack.push(1);
stack.push(2);
stack.push(4);
stack.forEach(System.out::println);
}
。。。。。。つづく