DS005データ構造-単一リンクリスト実装の原理に関する調査-C ++テンプレートクラスの実装

1.シーケンステーブルは非常に優れていますが、リンクリストが必要なのはなぜですか。

シーケンステーブルの欠点:

テーブルの最後に加えて、 シーケンス テーブルで 要素を 挿入 および削除するには、他の要素を移動する必要があり ます。 これは非効率的です。平均時間の複雑さは O(n) です。
シーケンステーブルには連続スペースが必要ですデータ量が比較的多い場合、十分な連続スペースがないと、シーケンステーブルは失敗し ます。
 
この欠点を解決するために、リンクリストが設計されています。 リンクリストの挿入と削除は他の要素を移動する必要がなく、挿入と削除の効率は高くなりますが、ランダムアクセスの利点は失われ ます。
 
もう1つ:これは破壊的な革新であり、シーケンシャルストレージのフレームワーク内で修復するのではなく、新たに始まります。
単一リンクリストは最も単純なチェーン構造であり、この分岐と拡張から、ツリーやグラフなどのより複雑な構造を構築できます。
基盤は強くなく、地面は揺れ動いており、リンクされたリストはよく学ぶ必要があります。

第二に、シングルリンクリストの定義

単一リンクリストは、後続ノードのアドレスを現在のノードに格納することにより、「チェーン」のようにシーケンスデータを接続するため、リンクリストと呼ばれます。
単一リンクリストの「単一」とは、現在のノード、つまり後続のデータノードのアドレスに格納されているアドレスデータが1つだけであることを意味します。

3、単一リンクリストのノード形式

第4に、単一リンクリストの全体的な形式

 

 

単一リンクリストにヘッドノードを設定すると、リンクリストの先頭にノードを簡単に挿入および削除できます。

      このセクションで説明した単一リンクリストのヘッドノードとデータノードは同じタイプです。

       便宜上、リンクリストの先頭へのポインター、リンクリストの末尾へのポインター、およびリンクリストの長さを表す整数をヘッドノードに設定できますこのとき、ヘッドノードのタイプは、リンクリストノードのタイプとは異なります。

5、リンクリストノードのC ++記述

template <typename T>クラスリスト
{//一方向リンクリスト 
    struct node
    {         T data;         node * next;     };     node * head; // Head node pointer     int length; //要素ノードの数を記録




}

このように、headはヘッドポインターであり、lengthはリンクされたリスト内の要素ノードの数を記録します(ヘッドノードを除く)。

6、ノードを生成する    

	node* creatNode(T x)
	{//为x生成结点,返回结点地址
		node* t;
		t = new node;
		if (t == 0)
			return 0;
		t->data = x;
		t->next = 0;
		return t;

	}

new演算子を使用して、オペレーティングシステムからノー​​ドタイプスペースを申請します。

オペレーティングシステムが私が裕福ではないと言って拒否した場合、0を返します。これはnullポインターです。それ以外の場合は、新しいノードのアドレスを返します。 

7、初期化

最初に、ヘッドノードが生成され、コンストラクターに実装されます。

	void init()
	{
		head = new node;
		head->next = 0;
		length = 0;
	}

    list()
	{
		init();
	}

headは変数で、アドレスを格納します。これは、名前のないヘッドノードのアドレスです。 

 

8.特定のノードの後に​​要素を挿入する

void insert(node* p, node* q)
	{//p是链表中某个结点的指针,q是一个新结点的指针
		//将q插入到p的后面
		q->next = p->next;
		p->next = q;
		length++;
	}

	void insert(node* p, T x)
	{//在指针p所指的结点后面插入x
		node* q, * t;

		t = creatNode(x);
		insert(p, t);		

	}

C ++関数のオーバーロードの関数名は同じですが、パラメーターが異なります。 

ノードpの後にqノードを挿入します。最初にpの後にポインタを切断しないでください。切断する前に、元のpの後にノードへのポインタが必要です。

そうしないと、ノードが失われます。

9、ヘッドノードの後に​​要素を挿入

void push_front(T x)
	{

		insert(head, x);

	}

以前の挿入機能の先見性により、先頭にノードを挿入する操作は非常に簡単です。

10.リンクリストの最後にノードを挿入します

 

void push_back(T x)
	{
		node* p;
		p = head;
		while (p->next)
		{
			p = p->next;
		}

		insert(p, x);

	}

 最初にリンクリストの終了ノードを見つけ、ポインターpでポイントしてから、pの後にデータを挿入します。

11. i番目のノードのアドレスを取得する

node* Address(int i)
	{//得到第i个元素结点的地址
		if (i<0 || i>length)
			return 0;
		if (i == 0)
			return head;
		if (i == 1)
			return head->next;


		int j = 0;
		node* p = head;
		while (j < i)
		{
			p = p->next;
			j++;
		}
		return p;

	}

単一リンクリストでi番目のノードを見つけることは、基本的な操作です。 

12. i番目のノードの前にデータを挿入する

void insert(int i, T x)
	{//在链表的第i个数据前面插入x
	 //即在第i-1个元素后面插入x
		node* p;
		if (i == 1)
			push_front(x);
		else if (i == length + 1)
			push_back(x);
		else
		{
			p = Address(i - 1);
			insert(p, x);

		}

	}

i番目のノードにデータを挿入するには、i-1番目のノードの後に​​データを挿入します。最初にi-1番目のノードを見つける必要があります。

13. i番目のノードを削除する

void erase(int i)
	{//删除第i个元素结点
		if (i<1 || i>length)
			return;
		node* q, * t;
		t = Address(i - 1);
		q = t->next;
		t->next = q->next;

		delete q;
		length--;
	}

i番目のノードを削除するには、最初にi-1番目のノードを見つける必要があります。 

14.リンクされたリストで検索

 

node* find(T x)
	{//查找元素x,若存在返回地址,否则返回空指针0
		node* p = head->next;
		while (p != 0)
		{
			if (p->data == x)
				return p;
			p = p->next;
		}
		return 0;
	}

15.単一リンクリストによって占有されていたスペースを解放する

デストラクタに実装されています

~list()
	{
		node* p;
		node* q;
		while (head->next)
		{
			p = head->next;
			head->next = p->next;
			delete p;
		}
		delete head;
		head = 0;
		length = 0;
	}

16.完全なコード

 



//#include "stdafx.h" //vc下面工程带的头文件,用dev编译时注释掉即可


#include <iostream>
using namespace std;

template<typename T>class list
{//单向链表 
	struct node
	{
		T data;
		node* next;
	};
	node* head;//头结点
	int length;
public:
	void init()
	{
		head = new node;
		head->next = 0;
		length = 0;
	}
	list()
	{
		init();
	}
	int size()
	{
		return length;
	}
	void print()
	{
		node* p;
		p = head->next;
		while (p != 0)
		{
			cout << p->data << " ";
			p = p->next;
		}
		cout << endl;
	}
	node* creatNode(T x)
	{//为x生成结点,返回结点地址
		node* t;
		t = new node;
		t->data = x;
		t->next = 0;
		return t;

	}

	void insert(node* p, node* q)
	{//p是链表中某个结点的指针,q是一个新结点的指针
		//将q插入到p的后面
		q->next = p->next;
		p->next = q;
		length++;
	}

	void insert(node* p, T x)
	{//在指针p所指的结点后面插入x
		node* q, * t;

		t = creatNode(x);
		insert(p, t);		

	}

	



	void push_front(T x)
	{

		insert(head, x);

	}
	void push_back(T x)
	{
		node* p;
		p = head;
		while (p->next)
		{
			p = p->next;
		}

		insert(p, x);

	}
	node* Address(int i)
	{//得到第i个元素结点的地址
		if (i<0 || i>length)
			return 0;
		if (i == 0)
			return head;
		if (i == 1)
			return head->next;


		int j = 0;
		node* p = head;
		while (j < i)
		{
			p = p->next;
			j++;
		}
		return p;

	}

	void insert(int i, T x)
	{//在链表的第i个数据前面插入x
	 //即在第i-1个元素后面插入x
		node* p;
		if (i == 1)
			push_front(x);
		else if (i == length + 1)
			push_back(x);
		else
		{
			p = Address(i - 1);
			insert(p, x);

		}

	}
	
	void erase(int i)
	{//删除第i个元素结点
		if (i<1 || i>length)
			return;
		node* q, * t;
		t = Address(i - 1);
		q = t->next;
		t->next = q->next;

		delete q;
		length--;
	}

	node* find(T x)
	{
		node* p = head->next;
		while (p != 0)
		{
			if (p->data == x)
				return p;
			p = p->next;
		}
		return 0;
	}

	~list()
	{
		node* p;
		node* q;
		while (head->next)
		{
			p = head->next;
			head->next = p->next;
			delete p;
		}
		delete head;
		head = 0;
		length = 0;
	}
};

int main()
{
	list<int> L;
	L.push_front(3);
	L.push_front(2);
	L.push_front(1);

	L.print();

	L.push_back(4);
	L.push_back(5);
	L.push_back(6);
	L.print();

	cout << L.size() << endl;

	cout << (L.Address(6)->data) << endl;

	L.insert(1, 44);
	L.print();
	L.insert(3, 55);
	L.print();
	L.insert(8, 66);
	L.print();

	cout << "begin to delete:\n";
	L.erase(1);
	L.print();
	L.erase(L.size());
	L.print();
	L.erase(3);
	L.print();

	cout << L.find(55)->data << endl;


	return 0;
}

17.実行結果

おすすめ

転載: blog.csdn.net/weixin_43917370/article/details/108565818
おすすめ