【Go資料結構】靜態連結串列 Static List
阿新 • • 發佈:2022-05-18
和連結串列一樣,只是針對沒有指標的語言。新增一個數據儲存下一個元素的遊標。
可以看到,A的遊標是1,指向的下一個元素在2,就是C。
插入的時候,就把A下個元素指向5,就是B,B的下個元素是2,就是C。
- 優點:
- 插入不用移動元素。(申請記憶體很困難的情況)
- 缺點:
- 和陣列一樣,不知道長度。
- 失去了陣列的隨機訪問特性。
- 總結:基本不會使用,但是是一種思路。(現在記憶體都不是瓶頸了)
Go實現:
package static_list import ( "fmt" "my_go/dataStructure/list" ) //靜態連結串列 type StaticList struct { Element [list.MAXSIZE]StaticNode Length int } type StaticNode struct { Data list.ElemType //資料 Cur int //遊標 } //靜態連結串列理論上是要用引數傳遞的。 //初始化列表 func (l *StaticList) InitList() { l.Length = 0 for i := 0; i < list.MAXSIZE; i++ { l.Element[i] = StaticNode{list.EmptyElement, i + 1} } //初始化使還沒有資料,所以這時頭結點指標指向0,代表空 l.Element[list.MAXSIZE-1].Cur = 0 } //清空列表 就是將首尾兩個陣列設定為原始的1和0 func (l *StaticList) ClearList() { l.Element[0].Cur = 1 l.Element[list.MAXSIZE-1].Cur = 0 } //判斷是否為空 func (l *StaticList) ListEmpty() bool { if l.Length > 0 { return false } return true } //獲取長度 func (l *StaticList) ListLength() int { return l.Length } //獲取指定位置的元素,返回在指標元素中 func (l *StaticList) GetElem(index int, e *list.ElemType) bool { if l.Length == 0 { fmt.Println("獲取失敗,佇列為空") return false } if index < 1 || index > l.Length { fmt.Println("獲取失敗,位置錯誤") return false } //獲取頭結點 index_first := l.Element[list.MAXSIZE-1].Cur for j := 1; index_first != 0; j++ { if j == index { *e = l.Element[index_first].Data break } index_first = l.Element[index_first].Cur } return true } //查詢元素線上性表中的位置 func (l *StaticList) LocateElem(value list.ElemType) int { if l.Length == 0 { fmt.Println("獲取失敗,佇列為空") return 0 } //獲取頭結點 index_first := l.Element[list.MAXSIZE-1].Cur j := 1 for ; j < list.MAXSIZE; j++ { if l.Element[index_first].Data == value { break } index_first = l.Element[index_first].Cur } return j } //獲取備份連結串列的第一個可用下標 func (l *StaticList) Malloc_SLL() int { //獲取當前陣列的第一個元素中存放的可用下標 i := l.Element[0].Cur //若是下標可用,若是指向0,陣列空間全部用盡 if l.Element[0].Cur != 0 { l.Element[0].Cur = l.Element[i].Cur } return i } //增 func (l *StaticList) ListInsert(index int, value list.ElemType) bool { if l.Length == list.MAXSIZE { //滿了 fmt.Println("插入失敗,佇列已滿") return false } if index < 1 || index > l.Length+1 { fmt.Println("插入失敗,位置錯誤") return false } //獲取空閒分量的下標 free_index := l.Malloc_SLL() k := list.MAXSIZE - 1 //k首先是最後一個元素的下標 if free_index != 0 { l.Element[free_index].Data = value for i := 1; i < index-1; i++ { //找到第i個元素的之前的位置 k = l.Element[k].Cur } //把第i個元素之前的cur賦值給新的元素的cur l.Element[free_index].Cur = l.Element[k].Cur l.Element[k].Cur = free_index l.Length++ return true } return false } //將回退首陣列的資料,指向我們刪除的那個空間,不會造成記憶體碎片 func (l *StaticList) Free_SLL(k int) { //將我們刪除的這個元素遊標指向原來的下一個空閒分量,方便一會回到原來的位置 l.Element[k].Cur = l.Element[0].Cur //將我們刪除的那個元素放入到0下標的遊標中,在下一次插入時會被呼叫,存放資料,節約空間 l.Element[0].Cur = k } //刪 func (l *StaticList) ListDelete(index int, e *list.ElemType) bool { if l.Length == 0 { fmt.Println("獲取失敗,佇列為空") return false } if index < 1 || index > l.Length { fmt.Println("獲取失敗,位置錯誤") return false } first_index := list.MAXSIZE - 1 //頭結點位置 //注意下標index開始和j的關係,我們要刪除第三個,j會迴圈兩次, // 我們若是從index = space[MAXSIZE-1].cur(是指向第一個)開始, // 迴圈兩次會直接指向我們要刪除的那個,而不是我們想要的前一個 j := 0 //找到我們要刪除的元素的前一個i-1元素的下標 for j = 1; j < index; j++ { first_index = l.Element[first_index].Cur } //用來儲存原來刪除的那個元素下標 j = l.Element[first_index].Cur *e = l.Element[j].Data //使前一個元素遊標指向要刪除元素下一個元素的下標,跳過中間這個要刪除的 l.Element[first_index].Cur = l.Element[j].Cur //將我們刪除的那個元素下標放入到備用連結串列中 l.Free_SLL(j) l.Length-- return true } //輸出 func (l *StaticList) Echo() { start := l.Element[list.MAXSIZE-1].Cur index := start for index != 0 { fmt.Print(l.Element[index].Data, " ") index = l.Element[index].Cur } fmt.Println() }
package static_list import ( "fmt" "my_go/dataStructure/list" "testing" ) func Test(t *testing.T) { fmt.Println("測試開始") my_list := new(StaticList) my_list.InitList() for i := 1; i <= 10; i++ { my_list.ListInsert(i, list.ElemType(i*i+1)) my_list.Echo() } fmt.Println("第5個這裡插入256") my_list.ListInsert(5, 256) my_list.Echo() my_list.ListInsert(199, 99) var e list.ElemType my_list.ListDelete(1, &e) fmt.Println("刪除頭元素:", e) my_list.Echo() my_list.ListDelete(my_list.ListLength(), &e) fmt.Println("刪除尾元素:", e) my_list.Echo() my_list.GetElem(6, &e) fmt.Println("獲取第6個:", e) fmt.Println("256的位置:", my_list.LocateElem(256)) fmt.Println("長度:", my_list.ListLength()) fmt.Println("開始清空") my_list.ClearList() if my_list.ListEmpty() { fmt.Println("已清空") my_list.Echo() } fmt.Println("測試完成") }