官方定義:數據結構(英語:data structure)是計算機中存儲、組織數據的方式。算法
數據的組織形式,數據元素之間存在的一種或多種特定關係的數據元素集合數組
通俗地講,數據結構 = 存儲結構 + 邏輯結構。bash
性質相同的數據元素的集合,是數據的一個子集markdown
數據的基本單位數據結構
組成數據元素的最小單位 spa
結構體Student就是一種數據結構,定義的name、age是數據項,Student 建立的 s一、s2... 是具體的 數據元素,由多個s一、s2...構成的數組studentArr[10] 便是數據對象指針
你們耳熟能詳的:線性表(順序表、鏈表)、棧、隊列、字符串、各類圖結構、集合結構、各類樹結構、二維數組、多維數組等code
邏輯結構又分爲 線性結構 和 非線性結構orm
一個有序數據元素的集合對象
1.集合中必存在惟一的一個"第一個元素";<br> 2.集合中必存在惟一的一個"最後的元素";<br> 3.除最後元素以外,其它數據元素均有惟一的"後繼";<br> 4.除第一元素以外,其它數據元素均有惟一的"前驅"。<br> 複製代碼
線性表(順序表、鏈表)、棧、隊列、字符串
各個數據元素再也不保持在一個線性序列中,每一個數據元素可能與零個或者多個其餘數據元素髮生聯繫
複製代碼
各類圖結構、集合結構、樹結構、二維數組、多維數組等
數據元素之間的關係有兩種不一樣的表示方法:順序映象 和 非順序映象,並由此獲得兩種不一樣的存儲結構:順序存儲結構 和 鏈式存儲結構。 數據的存儲結構是指數據的邏輯結構在計算機中的表示。
下面分別講順序存儲結構和鏈式存儲結構
注意:必定是先開闢空間,並且是連續的。
複製代碼
順序存儲由於須要開闢一塊連續的空間,因此在內存的利用率上不如鏈式結構,當處理增、刪、改的操做時,須要處理後續的每個數據元素,可是在執行查找操做時,按索引找到對應數據元素便可。
用爲僞代碼或文字演示
// 定義
typedef int ElemType;
typedef struct {
ElemType *data;
int length;
} List;
複製代碼
// 建立順序表
List L;
L->data = malloc(sizeof(ElemType) * MAXSIZE);
L->length = 0;
複製代碼
L->length = 0;
複製代碼
free(L)
複製代碼
插入位置i 插入元素e
一、在L中找到插入位置i,
二、從i到L爲元素依次向後移動一位,此時,L中i的位置空出,
三、將e放入i的位置中,L長度+1,完成插入操做。
複製代碼
一、根據刪除位置i找到i+1至表尾的全部元素
二、i+1到表尾的元素依次向前移動一位
三、L長度-1 ,完成刪除操做
複製代碼
鏈式存儲結構,又叫連接存儲結構。在計算機中用一組任意的存儲單元存儲線性表的數據元素(這組存儲單元能夠是連續的,也能夠是不連續的).
複製代碼
它不要求邏輯上相鄰的元素在物理位置上也相鄰.所以它沒有順序存儲結構所具備的弱點,但也同時失去了順序表可隨機存取的優勢.
只寫出核心步驟
// 定義節點等數據結構
typedef struct Node{
ElemType data; // 數據
struct Node *next; // 後繼指針 指向下一個節點
struct Node *pre; // 前驅指針 指向前一個節點
}Node;
typedef struct Node * List;
複製代碼
List L = (List)malloc(sizeof(Node));
L->next = NULL;
L->pre = NULL;
複製代碼
問題描述:向p和q節點之間插入s
算法描述:
一、新元素s的後繼指針指向後面的q;
二、q的前驅指針指向s;
三、s的前驅動指針指向前面的p;
四、p的後繼指針指向s;
複製代碼
代碼描述:
s->next = q;
q->pre = s;
s->pre = p;
p->next = s;
複製代碼
或者只用節點p和s
s->next = p->next;
p->next>-pre = s;
s->pre = p;
p->next = s
複製代碼
問題描述:刪除p、s、q順序中的s
算法描述:
一、p的後繼指針指向q;
二、q的前驅指針指向p;
三、銷燬s
複製代碼
代碼描述:
p-next = p->next->next;
p->next->pre = p;
free(s);
複製代碼
算法描述:
核心思想:根據持有的頭節點,新節點始終插入在頭節點以後,成爲新的首元節點
步驟:
一、根據頭節點後找到首元節點,即頭節點以後的節點;
二、建立新節點,新節點的後繼指針指向首元節點;
三、首元節點的前驅指針指向新節點;
四、頭節點的後繼指針指向新節點;
五、新節點的前驅指針指向頭節點;
複製代碼
/* 隨機產生n個元素值,創建帶表頭結點的雙鏈線性表L(前插法)*/ void CreateListHead(LinkList *L, int n) { LinkList p; LinkList list; //創建1個帶頭結點的雙鏈表 *L = (LinkList)malloc(sizeof(Node)); list = *L; list->next = NULL; list->pre = NULL; //循環前插入隨機數據 for(int i = 0; i < n;i++) { //生成新結點 p = (LinkList)malloc(sizeof(Node)); //i賦值給新結點的data p->data = i; // 將原先list的後繼節點和p創建雙指向 p->next = list->next; if (list->next != NULL) list->next->pre = p; //將結點P插入到頭結點 list->next = p; p->pre = list; } } 複製代碼
算法描述
核心思想:根據持有的尾節點,每次新插入的節點均插入到鏈表的尾節點以後,成爲新的尾節點。
步驟:
一、將尾節點p的後繼指針指向新節點q;
二、新節點q的前驅指針指向原尾節點p;q已經成了尾節點;
三、尾節點q的next置爲NULL。
複製代碼
/* 隨機產生n個元素值,創建帶表頭結點的單鏈線性表L(後插法)*/ void CreateListTail(LinkList *L, int n) { // p 每次新產生的節點, r 當前的尾節點,每次尾插入後,及時更新r LinkList p,r; //創建一個帶頭結點的雙鏈表 *L = (LinkList)malloc(sizeof(Node)); //r指向尾部的結點 r = *L; for (int i=0; i<n; i++) { //生成新結點 p = (Node *)malloc(sizeof(Node)); p->data = i; // 將表尾終端結點的指針指向新結點 r->next = p; // 新尾節點p的前驅指針指向前面的r p->pre = r; //將當前的新結點定義爲表尾終端結點 r = p; } //將尾指針的next = null r->next = NULL; } 複製代碼