日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构(一)线性表链式存储实现

發布時間:2024/4/15 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构(一)线性表链式存储实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

(一)前提

在前面的線性表順序存儲結構,最大的缺點是插入和刪除需要移動大量的元素,需要耗費較多的時間。
原因:在相鄰兩個元素的存儲位置也具有鄰居關系,他們在內存中的位置是緊挨著的,中間沒有間隙,當然無法快速插入和刪除。
為了解決這個為題,出現了鏈式存儲結構

(二)鏈式線性表兩種結構(帶有頭結點和不帶頭結點)

不帶頭結點:

空鏈表:

?

帶有頭結點:

空鏈表:

?(三)頭結點和頭指針的區別

頭指針:

1.頭指針是指向第一個結點的指針,若是鏈表中只有頭結點,則是指向頭結點的指針 2.頭指針具有標識作用,所以常常以頭指針冠以鏈表的名字(指針變量名) 3.無論鏈表是否為空,頭結點均不為空 4.頭指針是鏈表必要元素

頭結點:

1.頭結點是為了操作統一和方便而設立的,放在第一個元素結點之前,其數據域一般無意義(也可以存放表長度) 2.有了頭結點,對第一個元素結點的插入,刪除,其操作和其他結點操作統一了 3.頭結點不一定是鏈表的必要元素

?(四)帶頭結點的單鏈表實現

#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h>#define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0typedef int ElemType; typedef int Status;typedef struct Node {ElemType data;struct Node* next; }Node;typedef struct Node* LinkList;//四個基本操作,初始,清空,判斷是否為空,獲取長度 Status InitList(LinkList* L); Status ClearList(LinkList* L); Status ListEmpty(LinkList L); int ListLength(LinkList L);//四個元素操作,插入,刪除,兩種查找 Status GetElem(LinkList L, int i, ElemType* e); int LocateElem(LinkList L, ElemType e); Status ListInsert(LinkList* L, int i, ElemType e); Status ListDelete(LinkList* L, int i, ElemType* e);//用來打印鏈表 void PrintList(LinkList L);int main() {LinkList L;ElemType e;Status ret;int i;printf("1.InitList\n");InitList(&L);printf("2.1 Insert range of 5 elements by head\n");for (i = 1; i <= 5;i++){ListInsert(&L, 1, i);}printf("2.2 Insert range of 5 elements by end\n");for (; i <= 10; i++){ListInsert(&L, ListLength(L)+1, i);}PrintList(L);printf("3. list length:%d\n", ListLength(L));printf("4.find element by element:%d get index:%d\n",8, LocateElem(L, 8));GetElem(L, 6, &e);printf("5.find element by index:%d get element:%d\n",6,e);ListDelete(&L, 3, &e);printf("6.delete element by index:%d get element:%d\n",3,e);PrintList(L);printf("7.Clear\n");ClearList(&L);printf("8.is empty:%d\n", ListEmpty(L));system("pause");return 0; }//四個基本操作,初始,清空,判斷是否為空,獲取長度 //初始化帶有頭結點的鏈表 Status InitList(LinkList* L) {*L = (LinkList)malloc(sizeof(Node)); //使頭指針指向頭結點if (*L == NULL) //內存分配失敗return ERROR;(*L)->next = NULL; //指針域為空(*L)->data = 0; //頭結點數據域用來存放鏈表長度return OK; }//清空鏈表(不會清除頭結點) Status ClearList(LinkList* L) {LinkList q, p;q = (*L)->next; //是q指向第一個結點while (q){p = q;q = q->next;free(p);}(*L)->next = NULL;return OK; }//判斷鏈表是否為空 Status ListEmpty(LinkList L) {if (L->next)return FALSE;return TRUE; }//獲取列表長度 int ListLength(LinkList L) {/*int length=0;LinkList q=L;while (q=q->next)length++;return length;*/return L->data; }//四個元素操作,插入,刪除,兩種查找 //按照索引查找,獲取元素 Status GetElem(LinkList L, int i, ElemType* e) {int j=1;LinkList q = L->next;while (q&&j<i){q = q->next;j++;}if (!q || j>i) //對結果進行判斷!q是沒有找到數據,已經到達尾結點,j>i是針對函數輸入進行判斷,例如輸入i=0,就不會走上面循環但是p!=null,這時節點也沒有找到,就需要我們進行判斷,針對這個,我們也可以在函數開始就進行長度校驗,更加容易理解return ERROR;*e = q->data;return OK; }//按照元素進行查找,獲取索引 int LocateElem(LinkList L, ElemType e) {int j=0;LinkList q = L->next;while (q){j++;if (q->data == e)break;q = q->next;}return j; }//按照索引進行插入數據 Status ListInsert(LinkList* L, int i, ElemType e) {if (L == NULL && i > (*L)->data+1)return ERROR;int j = 1;LinkList q = *L;while (q&&j<i){q = q->next;j++;}if (i < j)return ERROR;//新建節點,加入鏈表LinkList n = (LinkList)malloc(sizeof(Node));n->data = e;n->next = q->next;q->next = n;(*L)->data++; //長度自加return OK; }//進行元素刪除 Status ListDelete(LinkList* L, int i, ElemType* e) {if (L == NULL || i>(*L)->data)return ERROR;int j=1;LinkList q, p;q = *L;while (q->next&&j<i) //這是去找指定索引元素的直接前驅 {q = q->next;j++;}if (!(q->next) || j>i)return ERROR;p = q->next; //這才是我們要刪除的*e = p->data;q->next = p->next;free(p);(*L)->data--;return OK; }//用來打印鏈表 void PrintList(LinkList L) {printf("begin print data:\n");LinkList q = L->next;while (q){printf("%d ", q->data);q = q->next;}printf("\nend print data\n"); } 1.InitList 2.1 Insert range of 5 elements by head 2.2 Insert range of 5 elements by end begin print data: 5 4 3 2 1 6 7 8 9 10 end print data 3. list length:10 4.find element by element:8 get index:8 5.find element by index:6 get element:6 6.delete element by index:3 get element:3 begin print data: 5 4 2 1 6 7 8 9 10 end print data 7.Clear 8.is empty:1 請按任意鍵繼續. . . 輸出結果 注意:對于元素的插入和刪除注意索引的正確與否

?補充:使用頭插法和尾插法創建單鏈表

//頭插法和尾插法創建單鏈表 void CreateListHead(LinkList* L, int n); void CreateListEnd(LinkList* L, int n);//頭插法 void CreateListHead(LinkList* L, int n) {LinkList q;//創建頭結點*L = (LinkList)malloc(sizeof(Node));(*L)->next = NULL;(*L)->data = 0;srand(time(0));for (int i = 0; i < n;i++){q = (LinkList)malloc(sizeof(Node)); //創建一個新節點q->data = rand() % 100 + 1;q->next = (*L)->next;(*L)->next = q;(*L)->data++;} }//尾插法 void CreateListEnd(LinkList* L, int n) {LinkList q, p;//創建頭結點*L = (LinkList)malloc(sizeof(Node));(*L)->next = NULL;(*L)->data = 0;p = *L;srand(time(0)); //創建隨機種子for (int i = 0; i < n; i++){q = (LinkList)malloc(sizeof(Node)); //創建一個新節點q->data = rand() % 10 + 1;//進行指針交換q->next = p->next;  //這一步可以省去,但是需要在for循環后面加上p->next=NULL;p->next = q;//將p指針始終指向最后元素p = q;//頭結點數據域自增記錄鏈表長度(*L)->data++;} }

?(五)時間復雜度的分析

單鏈表的查找性能為O(n)---->順序存儲結構為O(1) 單鏈表的插入和刪除,在計算出某位置的指針后,插入和刪除性能為O(1)----->順序存儲結構為O(n)

(六)空間性能分析

順序存儲結構需要預分配存儲空間。 單鏈表不需要分配存儲空間,元素限制不受控制

(七)總結

若線性表需要頻繁查找,很少進行插入和刪除操作,應該選擇順序存儲結構。 當線性表中元素個數變化較大或者根本不知道有多大時,最好使用單鏈表結構,不需要考慮存儲空間大小問題

轉載于:https://www.cnblogs.com/ssyfj/p/9417023.html

總結

以上是生活随笔為你收集整理的数据结构(一)线性表链式存储实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。