データ構造 C コード 2.3: 二重リンクリスト

要約と考察: 

1. 利点:シングルリンクリストと比較して、ダブルリンクリストは逆方向にトラバースする機能があり、各ノードが連動しています。

2. 欠点:単一リンクリストと比較して、より多くの操作があり、*previous は前のノードを指す必要があるため、構造体には前のノードへのポインタも含まれるため、より多くのスペースが必要になります。

3.私の提案は、単一のリンクされたリストで十分であるということです

学習目標:

二重リンク リストを学習します。主な目的は、リンク リストのバリエーションを練習し、より多くのデザイン感覚を見つけることです。このようにして、実際的な問題に直面したときに、ある程度のモデリング能力を身につけることができます。

学習ガイド:ファンシェンのコード

学習課題:

  1. コードをコピーします。
  2. insertElement などの関数に対してさらにテストを実行します。
  3. locateElement 関数を自分で実装します。
  4. バグを選択して、Fanshen Code にメッセージを残してください。
  5. CSDN ブログを書くには、ツールで描いたり、写真を撮るために手描きしたりできるアイコンが必要です。
  6. 学習成果カタログ

     1 スクライブコード

    1.1 二重リンクリスト構造

    1.2 リンクリストの初期化

     1.3 リンクリストの印刷

    1.4 ノードの挿入

    1.5 ノードの削除

    2. ノードの配置

    3. 単体テスト

    3.1 追加と削除

    3.2 位置決め

    3.3 アドレスの割り当て

    3.4 実行結果

    4つのすべてのコード

3. コードの説明

  1. 印刷、挿入、配置、削除を実装しました。
  2. 関連するすべてのポインターを変更する必要があり、プログラムの作成を支援するために図を描画する必要があります。
  3. 末尾ノードを削除するときは注意が必要であり、境界テストが必要です。

勉強の時間:

2022.5.3

 1 スクライブコード

1.1 二重リンクリスト構造

/**
 * 双链表结构体,存储字符串数据
 */
typedef struct DoubleLinkeNdode {
	char data;
	struct DoubleLinkeNdode *previous;
	struct DoubleLinkeNdode *next;
} DLNode, *DLNodePtr;

1.2 リンクリストの初期化

/**
 * @brief 初始化链表,创建一个头节点
 *
 * @return 返回头节点
 */
DLNodePtr initLinkList() {
	//申请空间
	DLNodePtr tempHeader = (DLNodePtr)malloc(sizeof(struct DoubleLinkeNdode) * 1);
	//初始化
	tempHeader->data = '\0';
	tempHeader->previous = NULL;
	tempHeader->next = NULL;
	return tempHeader;
}

 1.3 リンクリストの印刷

/**
 * @brief 打印链表
 *
 * @param paraHeader 传入头节点
 */
void printList(DLNodePtr paraHeader) {
	DLNodePtr p = paraHeader->next;
	//节点不为空,则打印数据
	while (p != NULL) {
		printf("%c", p->data);
		p = p->next;
	}
	printf("\n");
}

1.4 ノードの挿入

/**
 * @brief 插入一个节点操作
 *
 * @param paraChar
 * @param paraHeader
 * @param paraPosition
 */
void insertElement(DLNodePtr paraHeader, char paraChar, int paraPosition) {
	//创建三个结构体变量:p查找查找插入链表位置,q申请新空间,r插入节点的后一节点,辅助插入
	DLNodePtr p, q, r;
	//1查找插入链表位置
	p = paraHeader;
	for (int i = 0; i < paraPosition; i++) {
		p = p->next;
		if (p == NULL) {
			printf("位置%d已经超出链表范围\n", paraPosition);
			return;
		}
	}

	//2申请空间
	q = (DLNodePtr)malloc(sizeof(struct DoubleLinkeNdode) * 1);
	//赋值
	q->data = paraChar;

	//3把新节点插入双链表
	r = p->next;
	q->next = p->next;
	q->previous = p;
	p->next = q;
	//如果不是尾节点,才需要把插入节点的后一节点指向插入节点(非常巧妙)
	if (r != NULL) {
		r->previous = q;
	}
	printf("插入元素%c成功!\n", paraChar);
}

1.5 ノードの削除

/**
 * @brief 删除一个节点操作
 * 
 * @param paraChar 
 * @param paraHeader 
 */
void deleteElement(DLNodePtr paraHeader, char paraChar) {
	//创建三个结构体变量:p为查找传入数据的前节点
	DLNodePtr p, q, r;
	//1查找传入数据的前节点
	p = paraHeader;
	while ((p->next != NULL) && (p->next->data != paraChar)) {
		p = p->next;
	}
	//2找不到数据,提示并结束
	if (p->next == NULL) {
		printf("节点%c不存在\n", paraChar);
		return;
	}
	//3找到数据,删除并提示
	q = p->next;
	r = q->next;
	p->next = r;
	if (r != NULL) {
		r->previous = p;
	}
	printf("你已经删除了节点%c", q->data);
	free(q);

}

2. ノードの配置

/**
 * @brief 定位节点
 * 
 * @param paraChar 
 * @param paraHeader 
 * 
 * @return 
 */
int locateElement(DLNodePtr paraHeader, char paraChar) {
	DLNodePtr p = paraHeader;
	for (int i = 0; p != NULL; i++) {
		if (p->data == paraChar) return i;
		p = p->next;
	}
	return -1;
}

3. 単体テスト

3.1 追加と削除

/**
 * 单元测试
 */
void insertDeleteTest() {
	printf("----insertDeleteTest开始测试-----\n");
	DLNodePtr tempList = initLinkList();
	printList(tempList);

	insertElement(tempList, 'H', 0);
	insertElement(tempList, 'e', 1);
	insertElement(tempList, 'l', 2);
	insertElement(tempList, 'l', 3);
	insertElement(tempList, 'o', 4);
	insertElement(tempList, '!', 5);
	printList(tempList);

	deleteElement(tempList, 'e');
	deleteElement(tempList, 'a');
	deleteElement(tempList, 'o');
	printList(tempList);

	insertElement(tempList, 'o', 1);
	printList(tempList);
	printf("--------------**********-------------\n\n");

}

3.2 位置決め

/**
 * 单元测试2
 */
void insertLocateTest() {
	printf("----insertLocateTest开始测试-----\n");
	int location, data;
	DLNodePtr tempList = initLinkList();
	printList(tempList);

	insertElement(tempList, 'H', 0);
	insertElement(tempList, 'e', 1);
	insertElement(tempList, 'l', 2);
	insertElement(tempList, 'l', 3);
	insertElement(tempList, 'o', 4);
	insertElement(tempList, '!', 5);
	printList(tempList);

	data = 'e';
	location = locateElement(tempList, data);
	if (location == -1) {
		printf("找不到元素%c!!!\n", data);
	} else {
		printf("元素%c的位置是%d\n", data, location);
	}
	data = 'a';
	location = locateElement(tempList, data);
	if (location == -1) {
		printf("找不到元素%c!!!\n", data);
	} else {
		printf("元素%c的位置是%d\n", data, location);
	}
	data = 'o';
	location = locateElement(tempList, data);
	if (location == -1) {
		printf("找不到元素%c!!!\n", data);
	} else {
		printf("元素%c的位置是%d\n", data, location);
	}
	printList(tempList);

	insertElement(tempList, 'o', 1);
	printList(tempList);
	printf("--------------**********-------------\n\n");

}

3.3 アドレスの割り当て

/**
 * 地址分配测试
 */
void basicAddressTest() {
	printf("------basicAddressTest开始测试-------\n");
	DLNode tempNode1, tempNode2;

	tempNode1.data = 4;
	tempNode1.next = NULL;

	tempNode2.data = 6;
	tempNode2.next = NULL;

	printf("第一个节点,data,next: %d, %d, %d\r\n",
	       &tempNode1, &tempNode1.data, &tempNode1.next);
	printf("第二个节点,data,next: %d, %d, %d\r\n",
	       &tempNode2, &tempNode2.data, &tempNode2.next);

	tempNode1.next = &tempNode2;
	printf("--------------**********-------------\n\n");

}

3.4 実行結果

----insertDeleteTest开始测试-----

插入元素H成功!
插入元素e成功!
插入元素l成功!
插入元素l成功!
插入元素o成功!
插入元素!成功!
Hello!
你已经删除了节点e节点a不存在
你已经删除了节点oHll!
插入元素o成功!
Holl!
--------------**********-------------

----insertLocateTest开始测试-----

插入元素H成功!
插入元素e成功!
插入元素l成功!
插入元素l成功!
插入元素o成功!
插入元素!成功!
Hello!
元素e的位置是2
找不到元素a!!!
元素o的位置是5
Hello!
插入元素o成功!
Hoello!
--------------**********-------------

------basicAddressTest开始测试-------
第一个节点,data,next: -834668016, -834668016, -834668000
第二个节点,data,next: -834668048, -834668048, -834668032
--------------**********-------------


--------------------------------
Process exited after 0.06356 seconds with return value 0

Press ANY key to continue...

4つのすべてのコード

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

/**
 * 双链表结构体,存储字符串数据
 */
typedef struct DoubleLinkeNdode {
	char data;
	struct DoubleLinkeNdode *previous;
	struct DoubleLinkeNdode *next;
} DLNode, *DLNodePtr;

/**
 * @brief 初始化链表,创建一个头节点
 *
 * @return 返回头节点
 */
DLNodePtr initLinkList() {
	//申请空间
	DLNodePtr tempHeader = (DLNodePtr)malloc(sizeof(struct DoubleLinkeNdode) * 1);
	//初始化
	tempHeader->data = '\0';
	tempHeader->previous = NULL;
	tempHeader->next = NULL;
	return tempHeader;
}

/**
 * @brief 打印链表
 *
 * @param paraHeader 传入头节点
 */
void printList(DLNodePtr paraHeader) {
	DLNodePtr p = paraHeader->next;
	//节点不为空,则打印数据
	while (p != NULL) {
		printf("%c", p->data);
		p = p->next;
	}
	printf("\n");
}

/**
 * @brief 插入一个节点操作
 *
 * @param paraChar
 * @param paraHeader
 * @param paraPosition
 */
void insertElement(DLNodePtr paraHeader, char paraChar, int paraPosition) {
	//创建三个结构体变量:p查找查找插入链表位置,q申请新空间,r插入节点的后一节点,辅助插入
	DLNodePtr p, q, r;
	//1查找插入链表位置
	p = paraHeader;
	for (int i = 0; i < paraPosition; i++) {
		p = p->next;
		if (p == NULL) {
			printf("位置%d已经超出链表范围\n", paraPosition);
			return;
		}
	}

	//2申请空间
	q = (DLNodePtr)malloc(sizeof(struct DoubleLinkeNdode) * 1);
	//赋值
	q->data = paraChar;

	//3把新节点插入双链表
	r = p->next;
	q->next = p->next;
	q->previous = p;
	p->next = q;
	//如果不是尾节点,才需要把插入节点的后一节点指向插入节点(非常巧妙)
	if (r != NULL) {
		r->previous = q;
	}
	printf("插入元素%c成功!\n", paraChar);
}

/**
 * @brief 删除一个节点操作
 *
 * @param paraChar
 * @param paraHeader
 */
void deleteElement(DLNodePtr paraHeader, char paraChar) {
	//创建三个结构体变量:p为查找传入数据的前节点
	DLNodePtr p, q, r;
	//1查找传入数据的前节点
	p = paraHeader;
	while ((p->next != NULL) && (p->next->data != paraChar)) {
		p = p->next;
	}
	//2找不到数据,提示并结束
	if (p->next == NULL) {
		printf("节点%c不存在\n", paraChar);
		return;
	}
	//3找到数据,删除并提示
	q = p->next;
	r = q->next;
	p->next = r;
	if (r != NULL) {
		r->previous = p;
	}
	printf("你已经删除了节点%c", q->data);
	free(q);

}

/**
 * @brief 定位节点
 * 
 * @param paraChar 
 * @param paraHeader 
 * 
 * @return 
 */
int locateElement(DLNodePtr paraHeader, char paraChar) {
	DLNodePtr p = paraHeader;
	for (int i = 0; p != NULL; i++) {
		if (p->data == paraChar) return i;
		p = p->next;
	}
	return -1;
}

/**
 * 单元测试
 */
void insertDeleteTest() {
	printf("----insertDeleteTest开始测试-----\n");
	DLNodePtr tempList = initLinkList();
	printList(tempList);

	insertElement(tempList, 'H', 0);
	insertElement(tempList, 'e', 1);
	insertElement(tempList, 'l', 2);
	insertElement(tempList, 'l', 3);
	insertElement(tempList, 'o', 4);
	insertElement(tempList, '!', 5);
	printList(tempList);

	deleteElement(tempList, 'e');
	deleteElement(tempList, 'a');
	deleteElement(tempList, 'o');
	printList(tempList);

	insertElement(tempList, 'o', 1);
	printList(tempList);
	printf("--------------**********-------------\n\n");

}

/**
 * 单元测试2
 */
void insertLocateTest() {
	printf("----insertLocateTest开始测试-----\n");
	int location, data;
	DLNodePtr tempList = initLinkList();
	printList(tempList);

	insertElement(tempList, 'H', 0);
	insertElement(tempList, 'e', 1);
	insertElement(tempList, 'l', 2);
	insertElement(tempList, 'l', 3);
	insertElement(tempList, 'o', 4);
	insertElement(tempList, '!', 5);
	printList(tempList);

	data = 'e';
	location = locateElement(tempList, data);
	if (location == -1) {
		printf("找不到元素%c!!!\n", data);
	} else {
		printf("元素%c的位置是%d\n", data, location);
	}
	data = 'a';
	location = locateElement(tempList, data);
	if (location == -1) {
		printf("找不到元素%c!!!\n", data);
	} else {
		printf("元素%c的位置是%d\n", data, location);
	}
	data = 'o';
	location = locateElement(tempList, data);
	if (location == -1) {
		printf("找不到元素%c!!!\n", data);
	} else {
		printf("元素%c的位置是%d\n", data, location);
	}
	printList(tempList);

	insertElement(tempList, 'o', 1);
	printList(tempList);
	printf("--------------**********-------------\n\n");

}

/**
 * 地址分配测试
 */
void basicAddressTest() {
	printf("------basicAddressTest开始测试-------\n");
	DLNode tempNode1, tempNode2;

	tempNode1.data = 4;
	tempNode1.next = NULL;

	tempNode2.data = 6;
	tempNode2.next = NULL;

	printf("第一个节点,data,next: %d, %d, %d\r\n",
	       &tempNode1, &tempNode1.data, &tempNode1.next);
	printf("第二个节点,data,next: %d, %d, %d\r\n",
	       &tempNode2, &tempNode2.data, &tempNode2.next);

	tempNode1.next = &tempNode2;
	printf("--------------**********-------------\n\n");

}



int main() {
	insertDeleteTest();
	insertLocateTest();
	basicAddressTest();
	return 0;
}

おすすめ

転載: blog.csdn.net/qq_61649579/article/details/124549972