1. 程式人生 > 其它 >【Go資料結構】靜態連結串列 Static List

【Go資料結構】靜態連結串列 Static List

和連結串列一樣,只是針對沒有指標的語言。新增一個數據儲存下一個元素的遊標。

可以看到,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("測試完成")
}