摘要:前言通過前面數據結構與算法前導我么知道了數據結構的一些概念和重要性,那么我們今天總結下線性表相關的內容。基本結構對于線性表,我們只需要一個數組和就能表示基本信息。
前言
通過前面數據結構與算法前導我么知道了數據結構的一些概念和重要性,那么我們今天總結下線性表相關的內容。當然,我用自己的理解解分享給大家。
其實說實話,可能很多人依然分不清線性表,順序表,和鏈表之間的區別和聯系!
線性表:邏輯結構, 就是對外暴露數據之間的關系,不關心底層如何實現。
順序表、鏈表:物理結構,他是實現一個結構實際物理地址上的結構。比如順序表就是用數組實現。而鏈表用指針完成主要工作。不同的結構在不同的場景有不同的區別。
對于java來說,大家都知道List接口類型,這就是邏輯結構,因為他就是封裝了一個線性關系的一系列方法和數據。而具體的實現其實就是跟物理結構相關的內容。比如順序表的內容存儲使用數組的,然后一個get,set,add方法都要基于數組來完成,而鏈表是基于指針的。當我們考慮對象中的數據關系就要考慮指針的屬性。指針的指向和value。
下面用一個圖來淺析線性表的關系。可能有些不太確切,但是其中可以參考,并且后面也會根據這個圖舉例。
在這里插入圖片描述
對于一個線性表來說。不管它的具體實現方法如何,我們應該有的函數名稱和實現效果應該一致。你也可以感覺的到在一些結構的設計。比如List的Arraylist和LinkedList。Map的HashMap和currentHashMap他們的接口api都是相同的,但是底層設計實現肯定是有區別的。
所以,基于面向對象的編程思維,我們可以將線性表寫成一個接口,而具體實現的順序表和鏈表可以繼承這個接口的方法,提高程序的可讀性。
還有一點比較重要的,記得初學數據結構與算法時候實現的線性表都是固定類型(int),隨著知識的進步,我們應當采用泛型來實現更合理。至于接口的具體設計如下:
package LinerList; public interface ListInterface順序表{ void Init(int initsize);//初始化表 int length(); boolean isEmpty();//是否為空 int ElemIndex(T t);//找到編號 T getElem(int index) throws Exception;//根據index獲取數據 void add(int index,T t) throws Exception;//根據index插入數據 void delete(int index) throws Exception; void add(T t) throws Exception;//尾部插入 void set(int index,T t) throws Exception; String toString();//轉成String輸出 }
順序表是基于數組實現的,所以一些方法要基于數組的特性。對于順序表應該有的基礎屬性為一個數組data和一個length.
還有需要注意的是初始化數組的大小,你可以固定大小,但是筆者為了可用性如果內存不夠將擴大二倍。當然這樣很可能因為空間使用問題造成很大的浪費。
一些基本的額方法就不說了,下面著重講解一些初學者容易混淆的概念和方法實現。這里把順序表比作一隊坐在板凳上的人。
插入add(int index,T t)
其中index為插入的編號位置,t為插入的數據
根據圖片你就很好理解插入操作。當插入一個index時候,他的后面所有元素都要后移一位。你可以看的出插入時候整個操作的臃腫性。所以這也是順序表性能表現最差的地方,頻繁的插入,刪除。
刪除同理,刪除也是非常占用資源的。原理和插入類似,不過人走了,空一個小板凳后面的人需要往前挪。
其他操作就很簡單了。比如如果按照編號獲取數據getElem(int index),你可以直接根據數據坐標返回。a[index],而其他操作,可以通過遍歷直接操作數組即可。
鏈表我想,表應該是很多人感覺很繞的東西,這個很大原因可能因為指針。很多人說java沒指針,其實java他也有隱形指針。只不過不能直接用罷了。
指針建立的數據關系往往比數組這些要抽象的多。對于指針域,你把他當成一個對象就好了,不過這個對象指向的是另一個同等級對象。對于這個關系,你可以比作每個person類。每個person類都有老公(老婆),而這個老公老婆也是一個實際對象,可以理解這更像一種邏輯約定關系,而不是硬生生的關系吧。
指針你可以考慮成腦子記憶。上面的順序表我們說它有序因為每個小板凳(數組)有編號,我們可以根據這個來確定位置。而對于鏈表來說,你可以看作成一個站在操場上的一隊人。而他的操作也略有不同,下面針對一些比較特殊和重要的進行歸納。
基本結構對于線性表,我們只需要一個data數組和length就能表示基本信息。而對于鏈表,我們需要一個node(head頭節點),和length,當然,這個node也是一個結構體。
class node{ T data;//節點的結果 node next;//下一個連接的節點 public node(){} public node(T data) { this.data=data; } public node(T data, node next) { this.data = data; this.next = next; } }
當然,這個節點有數據域和指針域。數據域就是存放真實的數據,而指針域就是存放下一個node的指針。所以相比順序表,如果用滿數組情況下,鏈表占用更多的資源,因為它要存放指針占用資源。
add(int index,T t)
其中index為插入的編號位置,t為插入的數據
加入插入一個節點node,根據index找到插入的前一個節點叫pre。那么操作流程為
node.next=pre.next如下1的操作,將插入節點后面聯系起來。此時node.next和pre.next一致。
pre.next=node因為我們要插入node,而node鏈可以替代pre自身的next。那么直接將pre指向node。那么就相當于原始鏈表插入了一個node。
很多人搞不清什么是帶頭節點和不帶頭節點。帶頭節點就是head節點不放數據,第0項從head后面那個開始數。而不帶頭節點的鏈表head放數據,head節點就是第0位。
主要區別:
帶頭節點和不帶頭節點的主要區別就在插入刪除首位,尤其是首位插入。帶頭節點找元素需要多遍歷一次因為它的第一個head節點是頭節點,不存數據(可看作一列火車的火車頭)。而方便的就是帶頭節點在首位插入更簡單。因為插入第0位也是在head的后面。
而不帶頭節點的鏈表就需要特殊考慮首位。因為插入第0位其實是插入head的前面。假設有head,插入node。具體操作為:
node.next=head;(node指向head,node這條鏈成我們想要的鏈)
head=node;(很多人想不明白,其實這個時候node才是插入后最長鏈的首位節點,head在他的后面,而在鏈表中head通常表示首位節點,所以head不表示第二個節點,直接"="node節點。這樣head和node都表示操作完成的鏈表。但是對外暴露的只有head。所以head只能指向第一個節點!)
插入尾而在插入尾部的時候,需要注意尾部的next為null。不能和插入普通位置相比!
刪除
按照index移除:delete(int index)
找到該index的節點node。node.next=node.next.nex
按照尾部移除(拓展):deleteEnd()
這個方法我沒有寫,但是我給大家講一下,按照尾部刪除的思想就是:
聲明一個node為head。
當node.next!=null時node=node.next 指向下一個
當node.next==null時候。說明這個節點時最后一個。你可以node=null。這個這個node的前驅pre的next就是null。這個節點就被刪除了。
頭部刪除(帶頭節點):
帶頭節點的刪除和普通刪除一直。直接head.next(第1個元素)=head.next.next(第二個元素)
這樣head.next就直接指向第二個元素了。第一個就被刪除了
頭部刪除(不帶頭節點)
我們知道不帶頭節點的第一個就是存貨真價實的元素的。不帶頭節點刪除也很簡單。直接將head移到第二位就行了。即:head=head.next
其他對于其他操作,主要時結合查找。而單鏈表的查找時從head開始。然后另一個節點team=head或head.next。然后用這個節點不停的等于它指向的next去查找我們需要的內容即while(循環條件){team=team.next}類似。
不同教程和人寫的線性表也不一致,這里只給出一個樣例學習使用而并不是標準,希望大家審視。
在實現上用了帶頭節點的鏈表實現,因為比較方便管理,不需要很多if else.
代碼實現 順序表package LinerList; public class seqlistimplements ListInterface { private Object[] date;//數組存放數據 private int lenth; public seqlist() {//初始大小默認為10 Init(10); } public void Init(int initsize) {//初始化 this.date=new Object[initsize]; lenth=0; } public int length() { return this.lenth; } public boolean isEmpty() {//是否為空 if(this.lenth==0) return true; return false; } /* * * @param t * 返回相等結果,為-1為false */ public int ElemIndex(T t) { // TODO Auto-generated method stub for(int i=0;i lenth-1) throw new Exception("數值越界"); return (T) date[index]; } public void add(T t) throws Exception {//尾部插入 add(lenth,t); } /* *根據編號插入 */ public void add(int index, T t) throws Exception { if(index<0||index>lenth) throw new Exception("數值越界"); if (lenth==date.length)//擴容 { Object newdate[]= new Object[lenth*2]; for(int i=0;i =index;i--)//后面元素后移動 { date[i+1]=date[i]; } date[index]=t;//插入元素 lenth++;//順序表長度+1 } public void delete(int index) throws Exception { if(index<0||index>lenth-1) throw new Exception("數值越界"); for(int i=index;i lenth-1) throw new Exception("數值越界"); date[index]=t; } public String toString() { String vaString=""; for(int i=0;i 鏈表 package LinerList; class node{ T data;//節點的結果 node next;//下一個連接的節點 public node(){} public node(T data) { this.data=data; } public node(T data, node next) { this.data = data; this.next = next; } } public class Linkedlist implements ListInterface { node head; private int length; public Linkedlist() { head=new node(); length=0; } public void Init(int initsize) { head.next=null; } public int length() { return this.length; } public boolean isEmpty() { if(length==0)return true; else return false; } /* * 獲取元素編號 */ public int ElemIndex(T t) { node team=head.next; int index=0; while(team.next!=null) { if(team.data.equals(t)) { return index; } index++; team=team.next; } return -1;//如果找不到 } @Override public T getElem(int index) throws Exception { node team=head.next; if(index<0||index>length-1) { throw new Exception("數值越界"); } for(int i=0;i length) { throw new Exception("數值越界"); } node team=head;//team 找到當前位置node for(int i=0;i node =new node(value);//新建一個node node.next=team.next;//指向index前位置的下一個指針 team.next=node;//自己變成index位置 length++; } @Override public void delete(int index) throws Exception { if(index<0||index>length-1) { throw new Exception("數值越界"); } node team=head;//team 找到當前位置node for(int i=0;i length-1) { throw new Exception("數值越界"); } node team=head;//team 找到當前位置node for(int i=0;i 測試與結果 package LinerList; public class test { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub System.out.println("線性表測試:"); ListInterfacelist=new seqlist (); list.add(5); list.add(6); list.add(1,8); list.add(3,996); list.add(7); System.out.println(list.ElemIndex(8)); System.out.println(list.toString()); list.set(2, 222); System.out.println(list.toString()); list.delete(4); System.out.println(list.toString()); System.out.println(list.length()); System.out.println("鏈表測試:"); list=new Linkedlist (); list.add(5); list.add(6); list.add(1,8); list.add(3,996); list.add(7); System.out.println(list.ElemIndex(8)); System.out.println(list.toString()); list.set(2, 222); System.out.println(list.toString()); list.delete(4); System.out.println(list.toString()); System.out.println(list.length()); } } 輸出:
線性表測試:總結
1
5 8 6 996 7
5 8 222 996 7
5 8 222 996
4
鏈表測試:
1
5 8 6 996 7
5 222 6 996 7
5 222 6 996
4這里的只是簡單實現,實現基本方法。鏈表也只是單鏈表。完善程度還可以優化。如果有錯誤還請大佬指正。
單鏈表查詢速度較慢,因為他需要從頭遍歷。如果頻繁操作尾部,可以考慮鏈表中不僅有head在加尾tail節點。而順序表查詢速度雖然快但是插入很費時費力。實際應用根據需求選擇!
java中的Arraylist和LinkedList就是兩種方式的代表,不過LinkedList使用雙向鏈表優化,并且jdk的api做了大量優化。所以大家不用造輪子,可以直接用,但是還是很有學習價值的。
如果有不理解或者不懂的可以聯系交流討論。筆者敞開自家公眾號的大門隨時歡迎受訪!下面還會持續出貨分享!,感覺不錯的可以點個贊,關注一波公眾號(回復數據結構有精心準備資料一份):bigsai
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76117.html
摘要:本論文將嘗試概述卷積網絡的架構,并解釋包含激活函數損失函數前向傳播和反向傳播的數學推導。本文試圖只考慮帶有梯度下降優化的典型卷積神經網絡架構的制定。 近日南洋理工大學研究者發布了一篇描述卷積網絡數學原理的論文,該論文從數學的角度闡述整個卷積網絡的運算與傳播過程。該論文對理解卷積網絡的數學本質非常有幫助,有助于讀者「徒手」(不使用卷積API)實現卷積網絡。論文地址:https://arxiv....
馬上就要開始啦這次共組織15個組隊學習 涵蓋了AI領域從理論知識到動手實踐的內容 按照下面給出的最完備學習路線分類 難度系數分為低、中、高三檔 可以按照需要參加 - 學習路線 - showImg(https://segmentfault.com/img/remote/1460000019082128); showImg(https://segmentfault.com/img/remote/...
摘要:資源獲取方式根據下面的索引,大家可以選擇自己需要的資源,然后在松哥公眾號牧碼小子后臺回復對應的口令,就可以獲取到資源的百度云盤下載地址。公眾號二維碼如下另外本文會定期更新,松哥有新資源的時候會及時分享給大家,歡迎各位小伙伴保持關注。 沒有一條路是容易的,特別是轉行計算機這條路。 松哥接觸過很多轉行做開發的小伙伴,我了解到很多轉行人的不容易,記得松哥大二時剛剛決定轉行計算機,完全不知道這...
摘要:程序設計數據結構算法數據結構數據結構就是關系,沒錯,就是數據元素相互之間存在的一種或多種特定關系的集合。物理結構是指數據的邏輯結構在計算機中的存儲形式。 程序設計=數據結構+算法 數據結構 數據結構就是關系,沒錯,就是數據元素相互之間存在的一種或多種特定關系的集合。 傳統上,我們把數據結構分為邏輯結構和物理結構。 邏輯結構:是指數據對象中數據元素之間的相互關系,也是我們今后最...
摘要:再附一部分架構面試視頻講解本文已被開源項目學習筆記總結移動架構視頻大廠面試真題項目實戰源碼收錄 Java反射(一)Java反射(二)Java反射(三)Java注解Java IO(一)Java IO(二)RandomAccessFileJava NIOJava異常詳解Java抽象類和接口的區別Java深拷貝和淺拷...
閱讀 25638·2021-09-29 09:41
閱讀 4799·2021-09-10 11:20
閱讀 1925·2021-09-09 09:32
閱讀 1888·2019-08-30 15:44
閱讀 3195·2019-08-29 17:13
閱讀 2813·2019-08-29 14:14
閱讀 2067·2019-08-29 14:11
閱讀 3230·2019-08-29 12:36