シーケンステーブルは、データ要素が連続した物理アドレスを持つストレージユニットのセグメントに順次格納される線形構造であり、通常は配列ストレージを使用します。アレイでの完全なデータの追加、削除、検索、および変更。シーケンステーブルは、一般的に次のように分割できます。静的シーケンステーブル:固定長の配列ストレージを使用します。動的シーケンステーブル:動的に開発された配列ストレージを使用します。静的シーケンステーブルは、保存する必要のあるデータの量がわかっている場合に役立ちます。静的シーケンステーブルの固定長配列により、Nが大きくなり、スペースが無駄になり、少ないだけでは不十分です。対照的に、動的シーケンステーブルはより柔軟で、スペースのサイズが動的に割り当てられます。必要に応じて。
次に、動的シーケンステーブルを実装しましょう。
まず、実装するインターフェース
public class SeqList {
// 打印顺序表
public void display() { }
// 在 pos 位置新增元素
public void add(int pos, int data) { }
// 判定是否包含某个元素
public boolean contains(int toFind) { return true; }
// 查找某个元素对应的位置
public int search(int toFind) { return -1; }
// 获取 pos 位置的元素
public int getPos(int pos) { return -1; }
// 给 pos 位置的元素设为 value
public void setPos(int pos, int value) { }
//删除第一次出现的关键字key
public void remove(int toRemove) { }
// 获取顺序表长度
public int size() { return 0; }
// 清空顺序表
public void clear() { }
}
第二に、インターフェースの実現
1、テーブルのフレームを作成します
上の図からわかるように、配列(int [] elem)を作成し、自分で要素を追加する必要があります。同時に、このテーブルの配列のサイズも知っておく必要があります。配列のサイズは自分で決定します。ここでは、初期容量(int IntCapacity)を10と仮定します。このような大きなテーブルを開きましたが、すべての配列に要素が含まれているわけではありません。このとき、有効サイズ(int usedSize)である実際のサイズを知る必要があります。
public int[] elem;
//有效的数据个数
public int usedSize;
//初始容量,且不能被改变
public static final int intCapacity = 10;
//创建对象并调用合适的构造方法
public MyArrayList() {
//创建一个初始容量为10个大小的数组对象
this.elem = new int[intCapacity];
this.usedSize = 0;
}
2.注文表を印刷する
まず、シーケンステーブルを印刷します。印刷して初めて、後続のインターフェイスの実装が正しいかどうかを知ることができます。最初は、テーブルの内容が空であるため、印刷されたテーブルは自然に空になります。ここでは、テーブルにコンテンツがあると想定しています。このテーブルをトラバースする必要があります。それだけです。このテーブルの有効な要素を出力するには、IntCapacityであるかusedSizeであるかにかかわらず、トラバーサルの終了条件を指定する必要があることに注意してください。
// 打印顺序表
public void display() {
int i = 0;
for(i = 0; i < this.usedSize; i++) {
System.out.print(this.elem[i] + " ");
}
System.out.println();
//System.out.print(Arrays.toString(this.elem));
}
3.位置に要素を追加します
ここでは、次のことを考慮する必要があります。1、どのように達成するか。2.入力位置はこの配列の有効範囲内にありますか?3.このアレイはいっぱいになりますか?いっぱいになったらどうすればいいですか?
まず、この問題を実装する方法を検討します。最初に位置位置を見つけたら、要素を内側に移動して、要素を挿入する位置を残す必要があります。そうしないと、直接挿入すると位置位置の内容が上書きされます。したがって、要素をposの後ろに移動します。移動するときは、最後の位置から始めてください。そうしないと、posの位置から移動すると、上書きされる問題が発生します。完了したら、usedSize++に実行させます。
次に、質問2と3について考えます。質問2の場合、posは有効範囲内であり、操作できます。この範囲は、添え字0からusedSizes-1添え字までです。この範囲から外れると、違法であり、警告する必要があります。例外を使用することも、印刷することもできます。質問3、私たちは完全な状況を判断する必要があります。要素を追加すると、usedSize(有効長)が累積されます。十分な数の要素が追加されると、usedSizeは配列の容量の長さに等しくなります。ここに、拡張が必要かどうかを判断するための条件があります。同時に、初期容量は変更できないため、容量を拡張する場合は、アレイをコピーして容量を拡張する必要があります。配列のcopyOfメソッドを使用して、配列をコピーし、同時に容量を拡張します。
//检查pos位置合法性
private void checkPos(int pos) {
if(pos < 0 || pos > this.usedSize) {
throw new RuntimeException("pos位置不合法!");
}
}
//检查数组是否满的情况
private boolean isFull() {
if(this.elem.length == this.usedSize) {
return true;
}
return false;
}
// 在 pos 位置新增元素
public void add(int pos, int data) {
//pos位置合法性
checkPos(pos);
//检查数组是否满了
if(isFull()) {
this.elem = Arrays.copyOf(this.elem, 2 * this.elem.length);
}
//新增元素
for(int i = this.usedSize - 1; i >= pos; i--) {
this.elem[i + 1] = this.elem[i];
}
this.elem[pos] = data;
this.usedSize++;
}
4.要素が含まれているかどうかを確認します
これは、トラバースしてから判断する必要があるだけです。
// 判定是否包含某个元素
public boolean contains(int toFind) {
for(int i = 0; i < this.usedSize; i++) {
if(this.elem[i] == toFind) {
return true;
}
}
return false;
}
5.要素に対応する位置を見つけます
これは、トラバースしてから判断する必要があるだけです。妥当性チェック関数は以前に作成されており、直接呼び出すことができます。
// 查找某个元素对应的位置
public int search(int toFind) {
//合法性检查
checkPos(toFind);
for(int i = 0; i < this.usedSize; i++) {
if(this.elem[i] == toFind) {
return i;
}
}
return -1;
}
6.位置にある要素を取得します
考慮すべき質問:1。見つける方法は?2.合法性?3.テーブルは空ですか?
以前、posの有効性を判断する関数を作成しましたが、ここではそれを呼び出すだけで済みます。それでは、問題3を解決しましょう。テーブルが空かどうかを判断する必要があるのはなぜですか?テーブルは空であり、有効な長さが0であることを示しています。つまり、テーブルに返す要素がなく、それらを取得する必要がないことを示しています。
//判断是否为空
private boolean isEmpty() {
return this.usedSize == 0;
}
// 获取 pos 位置的元素
public int getPos(int pos) {
//表是否为空
if (isEmpty()) {
//也可以进行打印
throw new RuntimeException("表为空!");
}
//检查合法性
if(pos < 0 || pos >= this.usedSize) {
throw new RuntimeException("pos位置不合法!");
}
//获取元素
return this.elem[pos];
}
7.位置の要素を値に設定します
最初に有効性を確認してから、値を上書きします。テーブルが空かどうかを判断する必要があります。
// 给 pos 位置的元素设为 value
public void setPos(int pos, int value) {
checkPos(pos);
if(isFull()) {
throw new RuntimeException("表为空!");
}
this.elem[pos] = value;
}
8.キーワードキーの最初の出現を削除します
削除後、有効長を-にします。
//删除第一次出现的关键字key
public void remove(int toRemove) {
int pos = search(toRemove);
if(pos == -1) {
System.out.println("未找到该值!");
return;
}
for(int i = pos; i < this.usedSize - 1; i++) {
this.elem[i] = this.elem[i + 1];
}
this.usedSize--;
}
9.シーケンステーブルの長さを取得します
シーケンステーブルの長さは、その有効な長さです。
// 获取顺序表长度
public int size() {
if (!isEmpty()) {
return this.usedSize;
}
return 0;
}
10.シーケンステーブルをクリアします
有効長を0とします。
// 清空顺序表
public void clear() {
this.usedSize = 0;
}
3.すべてのコードと結果
import java.util.Arrays;
/**
* @author: Naion
* @create: 2021-12-26 14:56
**/
public class MySeqlist {
//定义一个顺序表
private int[] elem;
private int usedSize;
private int intCapacity = 10;
//调用合适的构造方法
public MySeqlist() {
//定义大小
this.elem = new int[intCapacity];
this.usedSize = 0;
}
// 打印顺序表
public void display() {
int i = 0;
for(i = 0; i < this.usedSize; i++) {
System.out.print(this.elem[i] + " ");
}
System.out.println();
}
//检查pos位置合法性
private void checkPos(int pos) {
if(pos < 0 || pos > this.usedSize) {
throw new RuntimeException("pos位置不合法!");
}
}
//检查数组是否满的情况
private boolean isFull() {
if(this.elem.length == this.usedSize) {
return true;
}
return false;
}
// 在 pos 位置新增元素
public void add(int pos, int data) {
//pos位置合法性
checkPos(pos);
//检查数组是否满了
if(isFull()) {
this.elem = Arrays.copyOf(this.elem, 2 * this.elem.length);
}
//新增元素
for(int i = this.usedSize - 1; i >= pos; i--) {
this.elem[i + 1] = this.elem[i];
}
this.elem[pos] = data;
this.usedSize++;
}
// 判定是否包含某个元素
public boolean contains(int toFind) {
for(int i = 0; i < this.usedSize; i++) {
if(this.elem[i] == toFind) {
return true;
}
}
return false;
}
// 查找某个元素对应的位置
public int search(int toFind) {
//合法性检查
checkPos(toFind);
for(int i = 0; i < this.usedSize; i++) {
if(this.elem[i] == toFind) {
return i;
}
}
return -1;
}
//判断是否为空
private boolean isEmpty() {
return this.usedSize == 0;
}
// 获取 pos 位置的元素
public int getPos(int pos) {
//表是否为空
if (isEmpty()) {
throw new RuntimeException("表为空!");
}
//检查合法性
if(pos < 0 || pos >= this.usedSize) {
throw new RuntimeException("pos位置不合法!");
}
//获取元素
return this.elem[pos];
}
// 给 pos 位置的元素设为 value
public void setPos(int pos, int value) {
checkPos(pos);
if(isFull()) {
throw new RuntimeException("表为空!");
}
this.elem[pos] = value;
}
//删除第一次出现的关键字key
public void remove(int toRemove) {
int pos = search(toRemove);
if(pos == -1) {
System.out.println("未找到该值!");
return;
}
for(int i = pos; i < this.usedSize - 1; i++) {
this.elem[i] = this.elem[i + 1];
}
this.usedSize--;
}
// 获取顺序表长度
public int size() {
if (!isEmpty()) {
return this.usedSize;
}
return 0;
}
// 清空顺序表
public void clear() {
this.usedSize = 0;
}
}
/**
* @author: Naion
* @create: 2021-12-26 14:55
**/
public class test_12_26_01 {
public static void main(String[] args) {
MySeqlist myseqlist = new MySeqlist();
for(int i = 0; i < 10; i++) {
myseqlist.add(i, i);
}
myseqlist.display();
System.out.println("======");
myseqlist.add(1, 3);
myseqlist.display();
System.out.println("======");
System.out.println(myseqlist.contains(3));
System.out.println("======");
System.out.println(myseqlist.search(3));
System.out.println("======");
System.out.println(myseqlist.getPos(1));
System.out.println("======");
myseqlist.setPos(1, 0);
myseqlist.display();
System.out.println("======");
myseqlist.remove(0);
myseqlist.display();
System.out.println("======");
System.out.println(myseqlist.size());
System.out.println("======");
myseqlist.clear();
myseqlist.display();
}
}
第四に、シーケンステーブルの問題
1.シーケンステーブルの中央/先頭での挿入と削除。時間計算量はO(N)です。
2.容量を増やすには、新しいスペースを申請し、データをコピーして、古いスペースを解放する必要があります。多少の消費があります。
3.容量の拡張は、通常2倍になり、ある程度のスペースデブリが発生します。たとえば、現在の容量は100で、容量がいっぱいになると容量は200に増加します。引き続き5つのデータを挿入し、後でデータを挿入しないため、95のデータスペースが無駄になります。
これらの問題を解決するには、単一リンクリストが必要です。