1. 程式人生 > 其它 >Pytorch(五) 使用DataSet和DataLoader資料載入

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