Pytorch(五) 使用DataSet和DataLoader資料載入
技術標籤:c
雙向連結串列
雙向連結串列
雙向連結串列也叫雙鏈表,是連結串列的一種,它的每個資料結點中都有兩個指標,分別指向直接後繼和直接前驅。所以,從雙向連結串列中的任意一個結點開始,都可以很方便地訪問它的前驅結點和後繼結點。下圖為雙向連結串列的結構圖。
/* 單鏈表的結構 */
struct List{
int data; // 資料域
struct List *next; // 指標域
};
/* 雙向連結串列的結構 */
typedef struct List{
int data; // 資料域
struct List *next; // 向後的指標
struct List *front; // 向前的指標
};
typedef struct List* pElem;
typedef struct List eElem;
注:1.在單鏈表中,由於每個結點只指向下一個節點,所以我們只能通過頭結點遍歷連結串列。但是雙向連結串列的每個結點既有指向下一個結點的指標,也有指向上一個結點的指標,所以我們要遍歷雙向連結串列可以通過其頭結點,也可以通過其尾結點。
2.當我們要找的結點靠近頭結點的時候,我們可以從頭結點開始遍歷;當我們要找的結點靠近尾結點的時候,我們可以從尾結點開始遍歷。從而提高執行效率。
- 雙向連結串列的建立(建立單鏈表結點類似)
pElem CreatList (){
pElem head = (pElem)malloc( sizeof(eElem) );
assert( head != NULL ); // 包含於標準庫<assert.h>
head->next = head->front = NULL; // 初始化連結串列,指標置空
return head;
}
-雙向連結串列的插入
在單向連結串列的頭插法中,最主要的語句自然就是tmp->next = head->next, 而在雙向連結串列中,自然也是一樣,只不過多了連線一個向前的指標而已。
void InsertElem( pElem head , int data ){
if( head == NULL ){
printf("The list is empty.\n"); // 頭結點為空,則無法插入
return;
}
pElem tmpHead = head; // 建立一個臨時的頭結點指標
if( tmpHead->next == NULL ){
/* 當雙向連結串列只有一個頭結點時 */
pElem addition = (pElem)malloc( sizeof(eElem) );
assert( addition != NULL );
addition->data = data; // 資料域賦值
addition->next = tmpHead->next; // 後向指標連線
tmpHead->next = addition;
addition->front = tmpHead; // 將插入結點的front 指向頭結點
}
else{
/* 當雙向連結串列不只一個頭結點時 */
pElem addition = (pElem)malloc( sizeof(eElem) );
assert( addition != NULL );
addition->data = data; // 資料域賦值
tmpHead->next->front = addition; // 頭結點的下一個結點的front 指標
addition->front = tmpHead; // 插入的結點的front 指標指向頭結點
addition->next = tmpHead->next; // 插入結點的next 指標指向原本頭指標的下一結點
tmpHead->next = addtion; // 將頭結點的next 指標指向插入結點
}
}
-雙向連結串列的插入
根據資料新增到雙向連結串列中的位置不同,可細分為以下 3 種情況:
1.新增至表頭
將新資料元素新增到表頭,只需要將該元素與表頭元素建立雙層邏輯關係即可。
換句話說,假設新元素節點為 temp,表頭節點為 head,則需要做以下 2 步操作即可:
temp->next=head; head->prior=temp;
將 head 移至 temp,重新指向新的表頭;
將新元素 7 新增至雙鏈表的表頭,則實現過程如下圖所示:
2.新增至表的中間位置
同單鏈表新增資料類似,雙向連結串列中間位置新增資料需要經過以下 2 個步驟,如下圖所示:
新節點先與其直接後繼節點建立雙層邏輯關係;
新節點的直接前驅節點與之建立雙層邏輯關係;
3.新增至表尾
與新增到表頭是一個道理,實現過程如下:
找到雙鏈表中最後一個節點;
讓新節點與最後一個節點進行雙層邏輯關係;
/*在第add位置的前面插入data節點*/
Node * InsertListHead(Node * head,int add,int data)
{
/*新建資料域為data的結點*/
Node * temp=(Node*)malloc(sizeof(Node));
if(head == NULL)
{
printf("malloc error!\r\n");
return NULL;
}
else
{
temp->data=data;
temp->pre=NULL;
temp->next=NULL;
}
/*插入到連結串列頭,要特殊考慮*/
if (add==1)
{
temp->next=head;
head->pre=temp;
head=temp;
}
else
{
Node * body=head;
/*找到要插入位置的前一個結點*/
for (int i=1; i<add-1; i++)
{
body=body->next;
}
/*判斷條件為真,說明插入位置為連結串列尾*/
if (body->next==NULL)
{
body->next=temp;
temp->pre=body;
}
else
{
body->next->pre=temp;
temp->next=body->next;
body->next=temp;
temp->pre=body;
}
}
return head;
}
```c
/*在第add位置的後面插入data節點*/
Node * InsertListEnd(Node * head,int add,int data)
{
int i = 1;
/*新建資料域為data的結點*/
Node * temp=(Node*)malloc(sizeof(Node));
temp->data=data;
temp->pre=NULL;
temp->next=NULL;
Node * body=head;
while ((body->next)&&(i<add+1))
{
body=body->next;
i++;
}
/*判斷條件為真,說明插入位置為連結串列尾*/
if (body->next==NULL)
{
body->next=temp;
temp->pre=body;
temp->next=NULL;
}
else
{
temp->next=body->pre->next;
temp->pre=body->pre;
temp->pre=body->pre;
body->pre->next=temp;
}
return head;
}
參考:https://blog.csdn.net/qq_16933601/article/details/105351119?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.control