實驗一 線性表的順序存儲與實現_【自考】數據結構中的線性表,期末不掛科指南,第2篇

7f6464c9d941aa5d96710d953009b966.png

線性表

這篇博客寫的是線性表相關的內容,包括如下部分,先看下有木有期待

  1. 啥是線性表
  2. 線性表的順序存儲
  3. 線性表的基本運算在順序表上的實現
  4. 線性表的鏈式存儲
  5. 線性表的基本運算在單鏈表上的實現
  6. 循環鏈表與雙向循環鏈表

Over,內容還蠻多的!~  ̄□ ̄||,頭大了...

首先明確一個非常重要的點

線性表是一個線性結構,注意上篇博客提過線性結構是數據的邏輯結構中的一種

基本概念

線性表是由n(n≥0)個數據元素組成的有窮序列

大白話:在內存上一個個排著,找到一個,剩下的挨著找就行

數據元素又稱作結點

吐槽:人類在創造術語的路上就是這么帶勁,上節課剛說數據元素又稱元素,這又來一個結點,得,記住吧

結點個數叫做表長,那么我們用一張完整的圖來說明一下

ada52e39f1beb67dcbb7577f21dfc0a6.png

線性表的基本運算,需要了解一下

  1. 初始化 Initiate(L)
  2. 求表長 Length(L)
  3. 讀表元素 Get(L,i)
  4. 定位 Locate(L,i)
  5. 插入Insert(L,x,i)
  6. 刪除Delete(L,i)

線性表的順序存儲

用順序存儲實現的線性表稱為順序表。一般使用數組來表示順序表

接下就是刺激的時刻了,比較難的部分來了,因為要用C來實現線性表的基本運算

首先假定線性表的數據元素的類型為DataType ,這個DataType 可以是自定義的,也可以是默認的int,char等類型

const int Maxsize = 100 ;  // 預先定義一個足夠大的常數
typedef struct{DataType data[Maxsize]; // 存放數據的數組int length ; // 順序表的實際長度
} SeqList; // 順序表類型名為SeqList  
SeqList L ;  // 定義一個L為順序表

實現插入操作,函數名字為InsertSeqList(SeqList L,DataType x,int i) 表示在順序表第i(1≤i≤n+1)個元素之前,插入一個新元素。使得線性表長度加1。

上面是邏輯上的C語言實現,接下來咱們先引用一個圖,說明一下如何用C語言在內存上開辟一塊空間,并且向里面存數據

#include <stdio.h>
#include <stdlib.h>const int Maxsize = 10;
typedef struct SeqList{int *data; //一個int指針,后面用來初始化數組用int length;
} seq;// 順序表的初始化函數
seq init(){seq s;s.data = (int*)malloc(Maxsize*sizeof(int)); // 構造一個空的順序表,動態申請存儲空間if(!s.data) // 如果申請失敗,退出程序{printf("初始化失敗");exit(0);}s.length = 0; // 空表的長度初始化為0return s;
}

上述代碼,相當于在內存上做了圖示的操作

80d57f22bf39b10e645c40f07713cee2.gif

開辟空間之后,向每個小格子里面添加數字

void display(seq s){for(int i=0;i<s.length;i++){printf("%d",s.data[i]);}printf("n");}int main()
{seq s = init();//添加一個元素進入for(int i=1;i<=5;i++){s.data[i-1] = i;s.length++;}printf("初始化之后,表的數據為:n");display(s);return 0;
}

可以看動畫理解

873fda761ce7923a610a0a3f5a137592.gif

添加元素完成之后,就是刪除元素

刪除的基本步驟 1. 結點a~i+1~,....a~n~依次向左移動一個元素位置 2. 表長度減1

看一下代碼吧

seq delete_seq(seq s,int i){if(i<1||i>s.length){printf("位置錯誤");exit(0);}// 第i個元素下標修改為i-1for(int j=i;j<s.length;j++){s.data[j-1] = s.data[j];}s.length--;return s;
}

接下來實現定位的算法,說白了,就是判斷一個值(x)的位置(i)

C語言的代碼如下

// 注意,這個地方需要返回的為int了,也就是位置
int locate(seq s,int x){int i =0;while((i<s.length)&&(s.data[i]!=x)){i++;}if(i<s.length) return i+1;else return -1;
}

線性表的順序存儲的時間復雜度

|運算| 插入|刪除|定位|求表長|讀取元素| |--|--|--|--|--|--| | 時間復雜度|O(n) |O(n)|O(n)|O(1)|O(1)| 具體是怎么來的,需要你自己看看算法的實現嘍,通過上述表格知道 順序表的插入、刪除算法在時間性能方面不是很理想,接下來我們就采用線性表的鏈接存儲來看一下,是否存在優化。

線性表的鏈接存儲

鏈式存儲結構,上來需要記住有三種常見的 單鏈表循環鏈表雙向循環鏈表

首先明確,單鏈表中每個結點由兩部分組成

00f6cda16ef9f20ea9d8df190108a240.png

- data表示==數據域== - next表示==指針域==或==鏈域==

一些簡單的結點概念

0acc1987f3ad22f93ba689b2bba615b1.png

線性表在單鏈表上實現基本運算

接下來重頭戲來了,我們要用代碼實現一個簡單的單鏈表

空的單鏈表由一個頭指針和一個頭結點組成

初始化

初始化之前,我們需要先用C語言定義一個新的結構體

//鏈表中的每個結點的實現
//包含數據域與指針域
typedef struct node{int data;// 數據域,為了計算方便,類型設置為數字struct node *next; // 指針域,指向后繼元素
} Node,*LinkList;

結構體定義好了之后,就可以開始初始化操作了 頭結點初始化其實就是在內存上開辟一塊空間,然后將指針域指向NULL

5c414e3d33f63c7a1c59914812840103.png

請看代碼,注意返回的是一個指針類型,說白了就是頭結點的地址

// 初始化
LinkList init(){Node *L; // 定義一個頭結點L =(LinkList)malloc(sizeof(Node)); //頭結點申請地址if(L == NULL){printf("初始化失敗!n");exit(0);}L->next =NULL;return L;
}

初始化成功,開始插入元素

插入元素,有頭插入、尾插、任意插

先說一下頭插,當頭結點初始化完畢之后,第一個元素插入進來就比較簡單了,看動圖 ![在這里插入圖片描述](https://img-blog.csdnimg.cn/20191110174036251.gif =400x) 這是插入一個元素,在用頭插法插入第二個元素呢? ![在這里插入圖片描述](https://img-blog.csdnimg.cn/20191110174900608.gif =500x) 新生成的pnew2首先將自己的指針域指向頭結點的指針域pnew2->next = L.next,然后L.next = pnew2 即可

上述的邏輯寫成代碼如下

// 頭插入法
void insert_head(Node *L){int i,n,num;  // n表示元素的個數 Node *pnew;printf("請輸入要插入的元素個數:n = ");scanf("%d",&n);for(i=0;i<n;i++){printf("請輸入第%d個元素: ",i+1);scanf("%d",&num);pnew = (LinkList)malloc(sizeof(Node));pnew->data = num; // 將數字存儲到數據域pnew->next = L->next; // 指針域指向L(頭結點)的指針域L->next = pnew; // 頭結點指針域指向新結點地址}
}

接下來看一下尾插法,其實理解起來也不難,說白了就是在鏈表后面追加元素即可 ![在這里插入圖片描述](https://img-blog.csdnimg.cn/20191110180601505.gif =600x) 代碼如下,這個地方看一下里面有一個p=L請問直接使用L可以嗎?為什么不直接用,搞清楚了,你也就明白了

// 尾插法
void insert_tail(Node *L){int i,n,num;Node *p,*pnew;p = L;printf("要輸入元素的個數:n = ");scanf("%d",&n);for(i=0;i<n;i++){printf("請輸入第%d個元素:",i+1);scanf("%d",&num);pnew = (LinkList)malloc(sizeof(Node));if(pnew == NULL){printf("初始化失敗");exit(0);}pnew->data = num;p->next = pnew;p = pnew;}p->next = NULL;}

剩下的算法實現就比較簡單了,例如求表長,通過循環的方式,計算一下即可

//求表長
int get_length(LinkList L){LinkList p;int length = 0;p = L->next;   // p 指向第一個結點while(p){printf("單鏈表的數據為%dn",p->data);length++;p = p->next;}return length;
}

讀表中的元素

// 讀表中的元素
LinkList get_element(LinkList L,int i){// 在單鏈表L中查找第i個結點,若找到,則返回指向該結點的指針,否則返回NULLNode *p;p = L->next;int position = 1;while((position<i)&&(p!=NULL)){ // 當未到第i結點且未到尾結點時繼續后移p = p->next;position++;}if(i==position) return p; //找到第i個結點else return NULL;   // 查找失敗
}

讀取表的元素,還可以按照值去找,返回位置,嘗試一下吧,寫起來都是比較容易的

int get_element_by_data(LinkList L,int x){Node *p;p = L->next;int i = 0;while(p!=NULL && p->data == x){p = p->next;i++;}if (p!=NULL) return i+1;else return 0;
}

寫個復雜點的,在任意位置插入一個元素,這個還是好玩一些的

/在任意位置插入元素,x為要插入的內容,i為插入的位置
void insert(LinkList L,int x,int i){Node *p,*q; //p表示要插入的元素,q表示要被插入的元素if(i==1) q = L; //如果i==1,那么p=L進行初始化操作else q = get_element(L,i-1); // 找到第i-1個元素if(q==NULL){printf("找不到位置");exit(0);}else{p =(LinkList)malloc(sizeof(Node));p->data = x;p->next = q->next; // 新生成的p指向q的下一個結點q->next = p;//q的指針域指向新生成的p}
}

簡單說明一下吧 大白話為 要在第i個位置插入一個元素x,那么需要找到i-1位置的元素,這個元素叫做 q

讓新元素p(數據域為x,指針域為空)的指針域指向第i 元素,也就是q原先的指針域,==防止丟失掉==

然后在叫q的指針域指向p的地址即可,如果還不明白,看圖

5408fd139d527ecc394b48b2e471ec45.png

對于刪除任意位置的節點,這個就要留給你自己了

如果將a~i~移除鏈表,需要找到直接前驅,讓直接前驅的指針域指向a~i+1~的地址就可以了

記得,通過free(p)釋放結點

刪除全部結點也需要自己完成一下,盡量把代碼寫完哦~~~

單鏈表的時間復雜度

  • insert(LinkList L,int x,int i) 時間復雜度為O(n^2^)
  • 頭插法和尾插法時間復雜度為O(n)

循環鏈表

環狀鏈表只需要將表中最后一個結點的指針指向頭結點,鏈表就形成了一個環 如圖

6bc2f767124442b2d13946764013aa81.png

循環鏈表如何想研究一下可以去實現約瑟夫環,由于本教材中不是重點,所以選修即可

雙向循環鏈表

雙向循環鏈表就是在單鏈表中的每個結點在增加一個指向直接前驅的指針域prior ,這樣每個結點就有兩個指針了

66b5a652f346e8a52f13b5945bb1b0b7.png

注意點 1. 雙向循環鏈表是一種對稱結構,即可以直接訪問前驅結點又可以直接訪問后繼結點,所以找前驅和后繼結點的時間復雜度都是O(1),也可以得到結論雙向循環鏈表適合應用在需要經常查找結點的前驅和后繼場合 2. p = p->prior->next = p->next->prior

教材中重點給出了刪除和插入的兩個邏輯,我們看一下

// p表示的是待刪除的結點
p->prior->next = p->next;
p->next->prior = p->prior;
free(p)

圖示如下

c3defce9f12a3214656b876d0aad87e8.png

大白話 先讓p等于要刪除的結點,然后把p刪除前,需要將p的前驅和后繼結點連接起來,剛才的代碼干的就是這個事情!

插入邏輯

在p所指的結點后面插入一個新結點*t,需要修改四個指針:
t->prior = p;
p->next = t;  // 這兩個步驟將t和p連接起來了t->next = p->next;
p->next->prior = t; //這兩個步驟將t和p后繼結點連接起來了

期末考試

這章是期末考試或者自考的一個比較重要的考試章節,一般會出現算法設計題,難度系數挺高的

建議,在能力范圍內用C語言實現順序表的基本運算,實現單鏈表的基本運算

懵了吧,嘿嘿~,多看幾遍,多看幾遍,看圖,看圖,寫代碼,運行,運行

歡迎關注,夢想橡皮擦公眾號哦~

6de2c87e9a8bd065fa7b2d89dccb7bde.png

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/542697.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/542697.shtml
英文地址,請注明出處:http://en.pswp.cn/news/542697.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

二叉樹打印葉子節點,非遞歸_使用遞歸打印鏈接列表中的備用節點

二叉樹打印葉子節點,非遞歸Solution: 解&#xff1a; Input: A singly linked list whose address of the first node is stored in a pointer, say head 輸入&#xff1a;一個單鏈表 &#xff0c;其第一個節點的地址存儲在指針中&#xff0c;例如head Output: The alternati…

TYVJ P1012 火柴棒等式 Label:枚舉

背景 NOIP2008年提高組第二題描述 給你n根火柴棍&#xff0c;你可以拼出多少個形如“ABC”的等式&#xff1f;等式中的A、B、C是用火柴棍拼出的整數&#xff08;若該數非零&#xff0c;則最高位不能是0&#xff09;。用火柴棍拼數字0-9的拼法如圖所示&#xff1a;注意&#xff…

java math max_Java Math類靜態double max(double d1,double d2)示例

java math max數學類靜態double max(double d1&#xff0c;double d2) (Math Class static double max(double d1,double d2) ) This method is available in java.lang package. 此方法在java.lang包中可用。 This method is used to return the maximum one of both the give…

python怎么開發軟件_怎么使用python進行軟件開發

一、下載pyinstaller 我使用的版本為PyInstaller-2.1&#xff0c;支持python版本2.3-2.7&#xff0c;點擊這里下載。 二、安裝pyinstaller 下載完成后&#xff0c;解壓即可。我的解壓目錄為D:\Python27\PyInstaller-2.1\ 三、使用pyinstaller打包.py成.exe應用程序 1.注意使用前…

28、清華大學腦機接口實驗組SSVEP數據集:通過視覺觸發BCI[飛一般的趕腳!]

前言&#xff1a; 哈嘍&#xff0c;最近對清華大學腦機接口的數據進行了嘗試&#xff0c;輸入到了DL模型中&#xff0c;以下是本人對于清華BCI數據的個人見解。 數據地址&#xff1a; 清華大學腦機接口研究組 (tsinghua.edu.cn) 打開網站可以看到有很多個數據&#xff0c;官…

python Pexpect

http://www.cnblogs.com/dkblog/archive/2013/03/20/2970738.htmlhttp://www.ibm.com/developerworks/cn/linux/l-cn-pexpect2/index.htmlhttp://www.cnblogs.com/dkblog/archive/2013/03/20/2970738.htmlpython Pexpect Pexpect 是一個用來啟動子程序并對其進行自動控制的純 P…

python 冪運算 整數_在Python中檢查一個數字是否是另一個數字的冪

python 冪運算 整數To solve this problem simply, we will use the log() function from the math module. The math module provides us various mathematical operations and here we will use the log() function from this module. In Python working of log() function, …

3dmax鏡像后模型線條亂了_3dMax入門教程來啦!小白趕緊收藏!

3D Studio Max&#xff0c;常簡稱為3d Max或3ds MAX&#xff0c;是Discreet公司開發的&#xff08;后被Autodesk公司合并&#xff09;基于PC系統的三維動畫渲染和制作軟件&#xff0c; 3dmax軟件主要功能有建模&#xff0c;動畫&#xff0c;渲染&#xff0c;特效等&#xff0c;…

java中哲學家就餐死鎖_哲學家就餐問題與死鎖總結

死鎖的四個條件&#xff1a;(1) 互斥條件&#xff1a;一個資源每次只能被一個進程使用。(2) 請求與保持條件&#xff1a;一個進程因請求資源而阻塞時&#xff0c;對已獲得的資源保持不放。(3) 不剝奪條件:進程已獲得的資源&#xff0c;在末使用完之前&#xff0c;不能強行剝奪。…

linux掃描工具之nmap

Linux下有很多強大網絡掃描工具&#xff0c;網絡掃描工具可以分為&#xff1a;主機掃描、主機服務掃描、路由掃描等,nmap支持批量主機掃描和主機服務掃描。檢測安裝&#xff1a;[rootbier ~]# rpm -qa nmap nmap-5.51-4.el6.x86_64如果沒有安裝就安裝一下nmap的安裝直接使用&am…

如何將多個一維列表轉化為二維列表_數據分析2_如何處理一維、二維數據

吞一塊大餅&#xff0c;還不如切成小塊吃得香常見的數據集&#xff0c;要么是數列&#xff0c;要么是表格&#xff1b;因此&#xff0c;數據分析最首要的是&#xff0c;處理一維、二維數據。主要知識點可參考如圖。如需要&#xff0c;可點擊以下百度網盤鏈接下載數據分析基礎知…

關于java中鎖的面試題_Java面試題-Java中的鎖

1. 如何實現樂觀鎖(CAS)&#xff1f;如何避免ABA問題&#xff1f;答&#xff1a;1)讀取內存值的方式實現了樂觀鎖(比如&#xff1a;SVN系統)&#xff0c;方法&#xff1a;第一&#xff0c;比較內存值和期望值&#xff1b;第二&#xff0c;替換內存值為要替換值。2)帶參數版本來…

NSUserDefaults

2019獨角獸企業重金招聘Python工程師標準>>> NSUserDefaults 轉載于:https://my.oschina.net/18829297883/blog/737931

什么是算術運算和邏輯運算_8086微處理器的算術和邏輯運算

什么是算術運算和邏輯運算邏輯指令 (Logical Instructions) a) AND: Logical AND a)AND&#xff1a;邏輯AND Atleast one of the operant should be a register or a memory operant both the operant cannot be a memory location or immediate operant. 操作中的至少一個應該…

python文件讀寫用到的庫_Python使用pyshp庫讀取shapefile信息的方法

通過pyshp庫&#xff0c;可以讀寫shapefile文件&#xff0c;查詢相關信息&#xff0c;github地址為 import shapefile # 使用pyshp庫 file shapefile.reader("data\\市界.shp") shapes file.shapes() # print(file.shapetype) # 輸出shp類型null 0 point 1 poly…

h5引入json_Vue中如何使用本地Json文件?

我需要將菜單配置成Json文件&#xff0c;然后再程序中引入{{menu.name}}import menuListConfig from ../../config/menu.jsonexport default {name: "Sider",data(){return {menuList:JSON.parse(JSON.stringify(menuListConfig))}}}需要如何做&#xff0c;才能v-for…

深入學習jQuery選擇器系列第四篇——過濾選擇器之屬性選擇器

前面的話 屬性過濾選擇器的過濾規則是通過元素的屬性來獲取相應的元素&#xff0c;對應于CSS中的屬性選擇器。屬性過濾選擇器可分為簡單屬性選擇器、具體屬性選擇器和條件屬性選擇器三種。本文將詳細該部分內容 簡單屬性選擇器 [attribute] [attribute]選擇器選擇擁有該屬性的元…

c++ scanf讀取_使用scanf()讀取內存地址并在C中打印其值

c scanf讀取Here, we have to input a valid memory address and print the value stored at memory address in C. 在這里&#xff0c;我們必須輸入一個有效的內存地址并在C中打印存儲在內存地址中的值。 To input and print a memory address, we use "%p" format…

python正則匹配_Python正則表達式只匹配一次

我正在嘗試創建一個簡單的降價乳膠轉換器,只是為了學習 python和基本的正則表達式,但我不知道試圖弄清楚為什么下面的代碼不起作用&#xff1a; re.sub (r\[\*\](.*?)\[\*\]: ?(.*?)$, r\\footnote{\2}\1, s, flagsre.MULTILINE|re.DOTALL) 我想轉換像&#xff1a; s "…

Virtual Network (1) - How to use it in a guest

本文將講述一個問題&#xff1a;kvm guest使用libvirt xml定義如何使用virtual network&#xff1f;1&#xff09;nat&#xff0c; route &#xff0c;isolated, open類型在host中定義virtual network會創建一個虛擬的bridge&#xff0c;相當于一個交換機。guest只需要連接到這…