package main import "fmt" /* 稀疏數組 案例:五子棋存盤與覆盤 節省存儲空間 */ type ValNode struct { row int //行 col int //列 val int //值 } //原始數組實現 func normalArray() { var chessMap [11][11]int chessMap[1][2] = 1 //黑子 chessMap[2][3] = 2 //白子 //輸出 for _, v := range chessMap { for _, v2 := range v { fmt.Printf("%d ", v2) } fmt.Println() } } //稀疏數組實現 func sparseArray() { //數據源 var chessMap [11][11]int chessMap[1][2] = 1 //黑子 chessMap[2][3] = 2 //白子 //切片 var sparseArr []ValNode //建立一個ValNode節點 valNode := ValNode{ row: 11, col: 11, val: 0, } //輸入全局默認節點 sparseArr = append(sparseArr, valNode) for i, v := range chessMap { for j, v2 := range v { //建立一個節點 if v2 != 0 { valNode := ValNode{ row: i, col: j, val: v2, } sparseArr = append(sparseArr, valNode) } } } //輸出稀疏數組 fmt.Println("當前的稀疏數組是。。。") //循環切片 for i, valNode := range sparseArr { fmt.Printf("%d:%d %d %d\n", i, valNode.row, valNode.col, valNode.val) } var chessMap2 [11][11]int //稀疏數組恢復原始數組 for i, valNode := range sparseArr { //跳過第一行默認記錄值 if i != 0 { chessMap2[valNode.row][valNode.row] = valNode.val } } //輸出恢復後的數組 for _,v:=range chessMap2{ for _,v2:=range v{ fmt.Printf("%d ",v2) } fmt.Println() } } func main() { sparseArray() }
使用數據模擬隊列node
package main import ( "errors" "fmt" "os" ) //使用結構體管理隊列 type Queue struct { maxSize int array [5]int //數組=》模擬隊列 front int //表示指向隊首 rear int //表示指向隊尾 } //添加數據到隊列 func (this *Queue) AddQueue(val int) (err error) { //先判斷隊列是否已滿 if this.rear == this.maxSize-1 { //重要提示,rear是隊列尾部(含最後元素 return errors.New("queue full") } //元素從下標爲1開始存入 this.rear++ //後移 //存入元素 this.array[this.rear] = val return } //從隊列中取出元素 func (this *Queue) GetQueue() (val int, err error) { //先判斷隊列是否爲空 if this.rear == this.front { //隊列 return -1, errors.New("queue empty") } this.front++ val = this.array[this.front] return val, err } //顯示隊列,找到隊首,而後遍歷到隊尾 func (this *Queue) ShowQueue() { fmt.Println("隊列當前的狀況是:") //this.front//不包含隊首 for i := this.front + 1; i <= this.rear; i++ { fmt.Printf("array[%d]=%d\t", i, this.array[i]) } } func main(){ //建立一個隊列 queue:=&Queue{ maxSize: 5, array: [5]int{}, front: -1, rear: -1, } var key string var val int for{ fmt.Println("\n\n1.輸入add表示添加數據到隊列") fmt.Println("2.輸入get表示從隊列獲取數據") fmt.Println("3.輸入show表示顯示隊列") fmt.Println("4.輸入exit表示退出\n\n") fmt.Scanln(&key) switch key { case "add": fmt.Println("請輸入入隊的數") fmt.Scanln(&val) err:=queue.AddQueue(val) if err!=nil{ fmt.Println(err.Error()) }else{ fmt.Print("加入隊列ok") } case "get": val,err:=queue.GetQueue() if err!=nil{ fmt.Println(err.Error()) }else{ fmt.Println("從隊列中取出了一個數=",val) } case "show": queue.ShowQueue() case "exit": os.Exit(0) } } }
經過數組實現環形隊列程序員
package main import ( "errors" "fmt" "os" ) //數組模擬環形隊列 /* 1.尾索引下一個爲頭索引時表示隊列滿,即將隊列容量空出一個做爲約定,這個在作判斷隊列滿的時候須要注意 (tail+1)%maxSize==head滿 2.tail==head [空] */ type CircleQueue struct { maxSize int //4 array [5]int //數組 head int //指向隊首0 tail int //指向隊尾0 } //入隊 func (this *CircleQueue) Push(val int) (err error) { if this.IsFull() { return errors.New("queue full") } //分析指出this.tail 在隊列尾部,可是包含最後的元素 this.array[this.tail] = val //把值給隊尾 //若是當前行滿。回到行初開始(加1是由於下標從零開始) this.tail = (this.tail + 1) % this.maxSize return } //出隊 func (this *CircleQueue) Pop() (val int, err error) { if this.IsEmpty() { return 0, errors.New("queue empty") } //取出head指向隊首,而且含隊首元素 val = this.array[this.head] //%若是滿行回到行首 this.head = (this.head + 1) % this.maxSize return } //顯示隊列 func (this *CircleQueue) ListQueue() { fmt.Println("環形隊列狀況以下") //取出當前隊列有多少個元素 size := this.Size() if size == 0 { fmt.Println("隊列爲空") } //設計一個輔助便理那個指向head tempHead := this.head for i := 0; i < size; i++ { fmt.Printf("arr[%d]=%d\t", tempHead, this.array[tempHead]) tempHead = (tempHead + 1) % this.maxSize } fmt.Println() } //判斷隊列爲滿 func (this *CircleQueue) IsFull() bool { //隊尾以前的長度%總長度=隊首以後的長度 return (this.tail+1)%this.maxSize == this.head } //判斷隊列爲空 func (this *CircleQueue) IsEmpty() bool { //當隊列爲空,首尾下標重合 return this.tail == this.head } //取出環形隊列有多少個元素 func (this *CircleQueue) Size() int { //這是一個關鍵的算法 return (this.tail + this.maxSize - this.head) % this.maxSize } /* 1.隊尾在隊首以後 this.tail% this.maxSize + this.maxSize% this.maxSize - this.head% this.maxSize 隊尾以前的長度+1-隊首以前的長度=總長度 */ func main() { cq := CircleQueue{ maxSize: 5, array: [5]int{}, head: 0, tail: 0, } var key string var val int for { fmt.Println("\n\n1.輸入add表示添加數據到隊列") fmt.Println("2.輸入get表示從隊列獲取數據") fmt.Println("3.輸入show表示顯示隊列") fmt.Println("4.輸入exit表示退出\n\n") fmt.Scanln(&key) switch key { case "add": fmt.Println("請輸入入隊的數:") fmt.Scanln(&val) err := cq.Push(val) if err != nil { fmt.Println(err.Error()) } else { fmt.Println("入隊成功") } case "get": val, err := cq.Pop() if err != nil { fmt.Println(err.Error()) } else { fmt.Printf("出隊成功:%d", val) } case "show": cq.ListQueue() case "exit": os.Exit(0) default: fmt.Println("輸入錯誤") } } }
單向鏈表算法
package main import "fmt" /* 單向鏈表的應用 水滸英雄排行榜 */ type HeroNode struct { no int name string nickname string next *HeroNode //表示指向下一個節點 } //給鏈表插入一個節點 //編寫第一個插入方法,在單鏈表最後加入 func InsertHeroNode(head *HeroNode, newHeroNode *HeroNode) { temp := head for { if temp.next == nil { //表示找到最後 break } temp = temp.next //讓temp不斷指向下一個節點 } //3.將newHeroNode加入到鏈表最後 temp.next = newHeroNode } //第二種插入方法,根據no的編號從小到大插入 func InsertHeroNode2(head *HeroNode, newHreoNode *HeroNode) { //1.找到適當的節點 temp := head flag := true //讓插入的節點的no,和temp的下一個結點比較 for { if temp.next == nil { //說明到了鏈表最後 break } else if temp.next.no >= newHreoNode.no { //說明newHeroNode就應該插入到temp後面 break } else if temp.next.no == newHreoNode.no { //說明鏈表中已經有這個no,就不插入 flag = false break } //不斷尋找下一個結點 temp = temp.next } if !flag { fmt.Println("對不起,已經存在no=", newHreoNode.no) return } else { newHreoNode.next = temp.next temp.next = newHreoNode } } //顯示全部鏈表節點信息 func ListNode(head *HeroNode) { //1.建立一個輔助結點 temp := head //先判斷該鏈表是否是一個空鏈表 if temp.next == nil { fmt.Println("空空如也。。。") return } //2.遍歷這個鏈表 for { fmt.Printf("[%d,%s,%s==>", temp.next.no, temp.next.name, temp.next.nickname) //判斷是否鏈表後 temp = temp.next if temp.next == nil { break } } } //刪除結點 func DelHeroNode(head *HeroNode, id int) { temp := head flag := false //找到要刪除的結點,和temp的下一個結點的no比較 for { if temp.next == nil { //說明到鏈表最後 break } else if temp.next.no == id { //找到了 flag = true break } temp = temp.next } if flag { temp.next = temp.next.next } else { fmt.Println("sorry,要刪除的id,不存在") } } func main() { //1.先建立一個頭結點 head := &HeroNode{} //2.建立一個新的HeroNode hero1 := &HeroNode{ no: 1, name: "宋江", nickname: "及時雨", } hero2 := &HeroNode{ no: 2, name: "盧俊義", nickname: "玉麒麟", } hero3 := &HeroNode{ no: 3, name: "林沖", nickname: "豹子頭", } hero4 := &HeroNode{ no: 3, name: "吳用", nickname: "智多星", } InsertHeroNode(head, hero4) InsertHeroNode(head, hero1) InsertHeroNode(head, hero2) InsertHeroNode(head, hero3) ListNode(head) //3.加入 //InsertHeroNode2(head, hero3) //InsertHeroNode2(head, hero1) //InsertHeroNode2(head, hero2) //InsertHeroNode2(head, hero4) ////4.顯示 //ListNode(head) }
雙向鏈表數據庫
package main import "fmt" type HeroNode struct { no int name string nickname string pre *HeroNode //這個結點指向前一個結點 next *HeroNode //着這結點指向下一個結點 } //給雙向鏈表插入一個結點 func InsertHeroNode(head *HeroNode, newHeroNode *HeroNode) { //思路 //1.先找到該鏈表的最後這個結點 //2.建立一個輔助結點 temp := head for { if temp.next == nil { break } temp = temp.next //讓temp不斷指向下一個結點 } //3.將newHeroNode加入到鏈表的最後 temp.next = newHeroNode newHeroNode.pre = temp } //給雙向鏈表插入一個結點 // func InsertHeroNode2(head *HeroNode, newHeroNode *HeroNode) { //1.找到適當的結點 //2.建立一個輔助結點 temp := head flag := true //讓插入結點的no,和temp的下一個結點的no比較 for { if temp.next == nil { break } else if temp.next.no >= newHeroNode.no { //說明newHeroNode就因該插入到temp後面 break } else if temp.next.no >= newHeroNode.no { flag = false break } temp = temp.next } if !flag { fmt.Println("對不起,已經存在no=", newHeroNode.no) return } else { newHeroNode.next = temp.next newHeroNode.pre = temp if temp.next != nil { //不是最後一個才進行操做 temp.next.pre = newHeroNode } temp.next = newHeroNode } } //刪除結點 func DelHeroNode(head *HeroNode, id int) { temp := head flag := true //找到要刪除的結點的no,和temp的下一個結點no比較 for { if temp.next == nil { break } else if temp.next.no == id { //說明找到了 flag = true break } temp = temp.next } if flag { temp.next = temp.next.next if temp.next != nil { temp.next.pre = temp } else { fmt.Println("sorry, 要刪除的id不存在") } } } //使用單鏈表的顯示方式顯示鏈表 func ListHeroNode(head *HeroNode) { //1.輔助結點 temp := head if temp.next == nil { fmt.Println("空空如也。。。") return } //遍歷鏈表 for { fmt.Printf("[%d,%s,%s]=>", temp.next.no, temp.next.name, temp.next.nickname) //判斷是否鏈表 temp = temp.next if temp.next == nil { break } } } //方式二 //使用單鏈表的顯示方式顯示鏈表 func ListHeroNode2(head *HeroNode) { //1.輔助結點 temp := head if temp.next == nil { fmt.Println("空空如也。。。") return } //2.讓temp定位到雙向鏈表的最後結點 for { if temp.next == nil { break } temp = temp.next } //遍歷鏈表 for { fmt.Printf("[%d,%s,%s]=>", temp.no, temp.name, temp.nickname) //判斷是否鏈表 temp = temp.pre if temp.pre == nil { break } } } func main() { //1.先建立一個頭結點 head := &HeroNode{} //2.建立一個新的HeroNode hero1 := &HeroNode{ no: 1, name: "宋江", nickname: "及時雨", } hero2 := &HeroNode{ no: 2, name: "盧俊義", nickname: "玉麒麟", } hero3 := &HeroNode{ no: 3, name: "林沖", nickname: "豹子頭", } hero4 := &HeroNode{ no: 3, name: "吳用", nickname: "智多星", } InsertHeroNode(head, hero1) InsertHeroNode(head, hero2) InsertHeroNode(head, hero3) InsertHeroNode(head, hero4) ListHeroNode(head) fmt.Println("\n逆序打印") ListHeroNode2(head) }
環形單向鏈表數組
package main import "fmt" /* 環形單向鏈表 */ //定義貓的結構體結點 type CatNode struct { no int //編號 name string next *CatNode } //在末尾加入新的結點 func InsertCatNode(head *CatNode, newCatNode *CatNode) { //判斷是否是添加第一隻貓 if head.next == nil { head.no = newCatNode.no head.name = newCatNode.name head.next = head //構成一個環形 fmt.Println(newCatNode, "加入到環形鏈表") return } //定義一個臨時變量,幫忙找到環形的最後結點 temp := head for { if temp.next == head { break } temp = temp.next } //加入到鏈表中 temp.next = newCatNode newCatNode.next = head } //輸出這個環形鏈表 func ListCircleLink(head *CatNode) { fmt.Println("環形鏈表的狀況以下") temp := head if temp.next == nil { fmt.Println("空空如也的環形鏈表。。") return } //循環輸出 for { fmt.Printf("貓的信息爲=[id=%d name=%s]->\n", temp.no, temp.name) if temp.next == head { //到結尾就跳出 break } //進入下一個結點 temp = temp.next } } //刪除一個節點 func DelCatNode(head *CatNode, id int) *CatNode { temp := head helper := head //空鏈表 if temp.next == nil { fmt.Println("這是一個空的環形鏈表,不能刪除") return head } //若是隻有一個結點 if temp.next == head { if temp.no == id { temp.next = nil //執行刪除 fmt.Printf("刪除貓貓=%d\n", id) } return head } //將helper定位到鏈表最後 for { if helper.next == head { break } helper = helper.next } //到這裏爲止helper爲最後一個結點,temp爲頭結點,也就是說helper是temp前面一個結點。在循環中二者的關係始終相鄰。 //head爲頭結點 //若是有兩個包含兩個以上的結點 flag := true for { //循環到結尾,跳出 if temp.next == head { //若是到這來,說明咱們比較到最後一個[最後一個還沒比較] break } //找到結點 if temp.no == id { //目標是頭結點 if temp == head { //說明刪除的是頭結點 head = head.next //刪除頭結點 } //目標是其餘結點 //恭喜找到,咱們也能夠直接刪除 helper.next = temp.next //執行刪除,若是helper.no爲2,temp.no爲3,此時刪除的是3 fmt.Printf("刪除貓貓=%d\n", id) flag = false break } //繼續循環,相似i++,兩個結點同步循環 temp = temp.next //移動 helper = helper.next //移動 } //flag爲true表示沒找到 if flag { fmt.Printf("對不起,沒有no=%d\n", id) } return head } func main() { //初始化一個環形鏈表的頭節點 head := &CatNode{} //建立一隻貓 cat1 := &CatNode{ no: 1, name: "tom", } cat2 := &CatNode{ no: 2, name: "tom2", } cat3 := &CatNode{ no: 3, name: "tom3", } cat4 := &CatNode{ no: 4, name: "tom4", } InsertCatNode(head, cat1) InsertCatNode(head, cat2) InsertCatNode(head, cat3) InsertCatNode(head, cat4) ListCircleLink(head) head = DelCatNode(head, 1) fmt.Println() fmt.Println() fmt.Println() fmt.Println() ListCircleLink(head) }
環形單向鏈表應用數據結構
package main import "fmt" /* 環形單項鍊表的應用 問題爲:設編號爲1, 2,... n的n我的圍坐一圈,約定編號爲k (1<=k<=n) 的人從1 臺報數,數到m的那我的出列,它的下一位又從1開始報數,數到m的那我的又出列,依次類推, 直到全部人出列爲止,由此產生個出隊編號 的序列。 */ //小孩的結構體 type Boy struct { No int //編號 Next *Boy //指向下一個小孩的指針【默認值是nil】 } //編寫一個函數,構成單向的環形鏈表 //num:表示小孩的個數 //*Boy:返回該環形鏈表的第一個小孩的指針 func AddBoy(num int) *Boy { first := &Boy{} //空結點 curBoy := &Boy{} //空結點 //判斷 if num < 1 { fmt.Println("num的值不對") return first } //循環的構建這個環形鏈表 for i := 1; i <= num; i++ { boy := &Boy{ No: i, } //分析構成循環鏈表,須要一個輔助指針 //1.由於第一個小孩比較特殊 if i == 1 { //第一個小孩 first = boy //不要動 curBoy = boy //curBoy默認爲第一個小孩 curBoy.Next = first //第一個小孩自成鏈表 } else { curBoy.Next = boy //連接上前面的 curBoy = boy //保存當前小孩留待下次循環使用 curBoy.Next = first //連接上後面的,構成環形鏈表 } } return first //返回頭結點 } //顯示單向的環形鏈表【遍歷】 func ShowBoy(first *Boy) { //處理一下若是環形鏈表爲空 if first.Next == nil { fmt.Println("鏈表爲空,沒有小孩") return } //建立一個指針,幫助遍歷。[說明至少有一個小孩] curBoy := first for { fmt.Println("小孩編號=%d->", curBoy.No) //退出的條件?curBoy.Next==first if curBoy.Next == first { //循環到最後一個結束 break } //curBoy//移動到下一個 curBoy = curBoy.Next } } /* 設編號爲1,2,。。n的n我的未作一圈,約定編號爲k(1<=k<=n) 的人從1開始報數,數到m的那個出列,它的下一位又從1開始報數。 數到m的那我的又出列,一次類推,直到全部人出列爲止,由此產生一個出列編號的序列 */ //分析思路 //1.編寫一個函數,PlayGame(first *Boy,startNo int,countNum int) //2.最後咱們使用一個算法,按照要求,在環形鏈表中留下最後一我的 func PlayGame(first *Boy, startNo int, countNum int) { //1.空的鏈表咱們單獨處理 if first.Next == nil { fmt.Println("空的鏈表,沒有小孩") return } //留一個,判斷startNo<=小孩總數 //2.須要定義的輔助指針,幫助咱們刪除小孩 tail := first //3.讓tail執行環形鏈表的最後一個小孩,這個很是的重要 //由於tail在刪除小孩時須要使用到 for { if tail.Next == first { //說明tail到了最後的小孩 break } tail = tail.Next //獲取尾結點 } //4.讓first移動到startNo後面咱們刪除小孩,就以first爲準 for i := 1; i <= startNo-1; i++ { first = first.Next tail = tail.Next } //保持順序推動到開始結點 fmt.Println() //.開始數countNum,而後刪除first指向的小孩 for { //開始數countNum-1次 for i := 1; i <= countNum-1; i++ { first = first.Next tail = tail.Next } fmt.Printf("小孩編號爲%d 出圈\n", first.No) //刪除first執行大小孩 first = first.Next //連接後面的新的,同時表示刪除 //tail始終是first前面一個 tail.Next = first //把first前面的連接上 //判斷若是tail==first,圈子中只有一個小孩 if tail == first { break } } fmt.Printf("小孩編號爲%d出圈\n", first.No) } func main() { first := AddBoy(5) //顯示 ShowBoy(first) PlayGame(first, 2, 3) }
package main import ( "fmt" ) /* 選擇排序 */ func SelectSort(arr *[6]int) { for j := 0; j < len(arr)-1; j++ { max := arr[j] maxIndex := j //每一次都找到全局最大值,放到前面 for i := j + 1; i < len(arr); i++ { if max < arr[i] { //找到真正最大值 max = arr[i] maxIndex = i } } //交換 if maxIndex != j { arr[j], arr[maxIndex] = arr[maxIndex], arr[j] } fmt.Printf("第%d次%v\n", j+1, *arr) } } /* 插入排序 */ func InsertSort(arr *[7]int) { //完成第一次,給第二個元素找到合適的位置並插入 for i := 1; i < len(arr); i++ { insertVal := arr[i] insertIndex := i - 1 //下標 //若是後面的值大於前面的值,進行交換 //對i前面的數,從右向左,一次相鄰做比較,大的放前面,同時數據後移 for insertIndex >= 0 && arr[insertIndex] < insertVal { fmt.Printf("arr[%v]=%v<%v\n", insertIndex, arr[insertIndex], insertVal) arr[insertIndex+1] = arr[insertIndex] //數據後移 insertIndex-- } //插入 if insertIndex+1 != i { fmt.Printf("insertIndex=%v\n", insertIndex) arr[insertIndex+1] = insertVal } fmt.Printf("第%d次插入後 %v\n", i, *arr) } } /* 快速排序法 */ //說明 //1.left表示數組左邊的下標 //2.right表示數組右邊的下標 //3.array表示要排序的數組 func QuickSort(left int, right int, array *[9]int) { l := left r := right //pivot是中軸,支點 pivot := array[(left+right)/2] temp := 0 //for循環的目標是將此pivot小的數放到左邊 //比pivot大的數放到右邊 for ; l < r; { //從pivot的左邊找到大於等於pivot的值 for ; array[l] < pivot; { l++ } //從pivot的upibian找到小於等於pivot的值 for ; array[r] > pivot; { r-- } //l<=r 代表本次分解任務完成,nreak if l >= r { break } //交換 temp = array[l] array[l] = array[r] array[r] = temp //優化 if array[l] == pivot { r-- } if array[r] == pivot { l++ } } //若是 lr,再移動下 if l == r { l++ r-- } //向左遞歸 if left < r { QuickSort(left, r, array) } //向右遞歸 if right > l { QuickSort(l, right, array) } } func main() { //arr:=[6]int{2,34,56,678,3,4} //SelectSort(&arr) //iarr := [7]int{2, 354, 67, 5, 687, 22, 343} //InsertSort(&iarr) arr:=[9]int{-9,78,0,23,-567,70,123,90,-23} fmt.Println("初始",arr) //調用快速排序 QuickSort(0,len(arr)-1,&arr) fmt.Println("main..") fmt.Println(arr) }
使用數組來模擬一個棧的使用app
package main import ( "errors" "fmt" ) //使用數組來模擬一個棧的使用 type Stack struct { MaxTop int //表示咱們棧最大能夠存放的個數 Top int //表示棧頂,由於棧頂固定,所以直接使用Top arr [5]int //數組模擬戰 } //入棧 func (this *Stack) Push(val int) (err error) { //判斷棧是否滿了 if this.Top == this.MaxTop-1 { fmt.Println("stack full") return errors.New("stack full") } this.Top++ //放入數據 this.arr[this.Top] = val return } //出棧 func (this *Stack) Pop() (val int, err error) { //判斷棧是否爲空 if this.Top == -1 { fmt.Println("stack empty !") return 0, errors.New("stack empty") } //先取值,再this.Top-- val = this.arr[this.Top] this.Top-- return val, nil } //遍歷棧,注意須要從棧頂開始遍歷 func (this *Stack) List() { //先判斷棧是否爲空 if this.Top == -1 { fmt.Println("stack empty") return } fmt.Println("棧的狀況以下:") for i := this.Top; i >= 0; i-- { fmt.Printf("arr[%d]=%d\n", i, this.arr[i]) } } func main() { stack := &Stack{ MaxTop : 5, // 表示最多存放5個數到棧中 Top : -1, // 當棧頂爲-1,表示棧爲空,由於數組下標是從0開始 } stack.Push(2) stack.Push(3) stack.Push(4) stack.Push(5) stack.List() stack.Pop() stack.List() }
棧實現綜合計算器ide
package main import ( "errors" "fmt" "strconv" ) //使用數組來模擬一個棧的使用 type Stack struct { MaxTop int // 表示咱們棧最大能夠存放數個數 Top int // 表示棧頂, 由於棧頂固定,所以咱們直接使用Top arr [20]int // 數組模擬棧 } //入棧 func (this *Stack) Push(val int) (err error) { //先判斷棧是否滿了 if this.Top == this.MaxTop-1 { fmt.Println("stack full") return errors.New("stack full") } this.Top++ //放入數據 this.arr[this.Top] = val return } //出棧 func (this *Stack) Pop() (val int, err error) { //判斷棧是否空 if this.Top == -1 { fmt.Println("stack empty!") return 0, errors.New("stack empty") } //先取值,再 this.Top-- val = this.arr[this.Top] this.Top-- return val, nil } //遍歷棧,注意須要從棧頂開始遍歷 func (this *Stack) List() { //先判斷棧是否爲空 if this.Top == -1 { fmt.Println("stack empty") return } fmt.Println("棧的狀況以下:") for i := this.Top; i >= 0; i-- { fmt.Printf("arr[%d]=%d\n", i, this.arr[i]) } } //判斷一個字符是否是一個運算符[+, - , * , /] func (this *Stack) IsOper(val int) bool { if val == 42 || val == 43 || val == 45 || val == 47 { return true } else { return false } } //運算的方法 func (this *Stack) Cal(num1 int, num2 int, oper int) int { res := 0 switch oper { case 42: res = num2 * num1 case 43: res = num2 + num1 case 45: res = num2 - num1 case 47: res = num2 / num1 default: fmt.Println("運算符錯誤.") } return res } //編寫一個方法,返回某個運算符的優先級[程序員定義] //[* / => 1 + - => 0] func (this *Stack) Priority(oper int) int { res := 0 if oper == 42 || oper == 47 { res = 1 } else if oper == 43 || oper == 45 { res = 0 } return res } func main() { //數棧 numStack := &Stack{ MaxTop: 20, Top: -1, } //符號棧 operStack := &Stack{ MaxTop: 20, Top: -1, } exp := "30+3*6-4-6" //定義一個index ,幫助掃描exp index := 0 //爲了配合運算,咱們定義須要的變量 num1 := 0 num2 := 0 oper := 0 result := 0 keepNum := "" for { //這裏咱們須要增長一個邏輯, //處理多位數的問題 ch := exp[index : index+1] // 字符串. //ch ==>"+" ===> 43 temp := int([]byte(ch)[0]) // 就是字符對應的ASCiI碼 if operStack.IsOper(temp) { // 說明是符號 //若是operStack 是一個空棧, 直接入棧 if operStack.Top == -1 { //空棧 operStack.Push(temp) } else { //若是發現opertStack棧頂的運算符的優先級大於等於當前準備入棧的運算符的優先級 //,就從符號棧pop出,並從數棧也pop 兩個數,進行運算,運算後的結果再從新入棧 //到數棧, 當前符號再入符號棧 if operStack.Priority(operStack.arr[operStack.Top]) >= operStack.Priority(temp) { num1, _ = numStack.Pop() num2, _ = numStack.Pop() oper, _ = operStack.Pop() //num1先出棧,num2後出棧,說明num2是先入棧的num2做爲操做數,num1做爲被操做數也就是,num2-num1,num2/num1 result = operStack.Cal(num1, num2, oper) //將計算結果從新入數棧 numStack.Push(result) //當前的符號壓入符號棧 operStack.Push(temp) } else { operStack.Push(temp) } } } else { //說明是數 //處理多位數的思路 //1.定義一個變量 keepNum string, 作拼接 keepNum += ch //2.每次要向index的後面字符測試一下,看看是否是運算符,而後處理 //若是已經到表達最後,直接將 keepNum if index == len(exp)-1 { val, _ := strconv.ParseInt(keepNum, 10, 64) numStack.Push(int(val)) } else { //向index 後面測試看看是否是運算符 [index] if operStack.IsOper(int([]byte(exp[index+1 : index+2])[0])) { val, _ := strconv.ParseInt(keepNum, 10, 64) numStack.Push(int(val)) keepNum = "" } } } //繼續掃描 //先判斷index是否已經掃描到計算表達式的最後 if index+1 == len(exp) { break } index++ } //若是掃描表達式 完畢,依次從符號棧取出符號,而後從數棧取出兩個數, //運算後的結果,入數棧,直到符號棧爲空 for { if operStack.Top == -1 { break //退出條件 } num1, _ = numStack.Pop() num2, _ = numStack.Pop() oper, _ = operStack.Pop() result = operStack.Cal(num1, num2, oper) //將計算結果從新入數棧 numStack.Push(result) } //若是咱們的算法沒有問題,表達式也是正確的,則結果就是numStack最後數 res, _ := numStack.Pop() fmt.Printf("表達式%s = %v", exp, res) }
迷宮找路函數
package main import ( "fmt" ) //編寫一個函數,完成老鼠找路 //myMap *[8][7]int:地圖,保證是同一個地圖,使用引用 //i,j 表示對地圖的哪一個點進行測試 func SetWay(myMap *[8][7]int, i int, j int) bool { //分析出什麼狀況下,就找到出路 //myMap[6][5] == 2 if myMap[6][5] == 2 { return true } else { //說明要繼續找 if myMap[i][j] == 0 { //若是這個點是能夠探測 //假設這個點是能夠通, 可是須要探測 上下左右 //換一個策略 下右上左 myMap[i][j] = 2 if SetWay(myMap, i+1, j) { //下 return true } else if SetWay(myMap, i, j+1) { //右 return true } else if SetWay(myMap, i-1, j) { //上 return true } else if SetWay(myMap, i, j-1) { //左 return true } else { // 死路 myMap[i][j] = 3 return false } } else { // 說明這個點不能探測,爲1,是強 return false } } } func main() { //先建立一個二維數組,模擬迷宮 //規則 //1. 若是元素的值爲1 ,就是牆 //2. 若是元素的值爲0, 是沒有走過的點 //3. 若是元素的值爲2, 是一個通路 //4. 若是元素的值爲3, 是走過的點,可是走不通 var myMap [8][7]int //先把地圖的最上和最下設置爲1 for i := 0; i < 7; i++ { myMap[0][i] = 1 myMap[7][i] = 1 } //先把地圖的最左和最右設置爲1 for i := 0; i < 8; i++ { myMap[i][0] = 1 myMap[i][6] = 1 } myMap[3][1] = 1 myMap[3][2] = 1 myMap[1][2] = 1 myMap[2][2] = 1 //輸出地圖 for i := 0; i < 8; i++ { for j := 0; j < 7; j++ { fmt.Print(myMap[i][j], " ") } fmt.Println() } //使用測試 SetWay(&myMap, 1, 1) fmt.Println("探測完畢....") //輸出地圖 for i := 0; i < 8; i++ { for j := 0; j < 7; j++ { fmt.Print(myMap[i][j], " ") } fmt.Println() } }
僱員系統測試
package main import ( "fmt" "os" ) /* 有一個公司,當有新的員工來報道時,要求將該員工的信息加入(id,性別,年齡,住址..),當輸入該員工 的id時要求查找到該員工的全部信息. ➢要求: 1)不使用數據庫儘可能節省內存,速度越快越好=>哈希表(散列) 2)添加時,保證按照僱員的id從低到高插入 */ //定義emp type Emp struct { Id int Name string Next *Emp } //方法待定.. func (this *Emp) ShowMe() { fmt.Printf("鏈表%d 找到該僱員 %d\n", this.Id%7, this.Id) } //定義EmpLink //咱們這裏的EmpLink 不帶表頭,即第一個結點就存放僱員 type EmpLink struct { Head *Emp } //方法待定.. //1. 添加員工的方法, 保證添加時,編號從小到大 func (this *EmpLink) Insert(emp *Emp) { cur := this.Head // 這是輔助指針 var pre *Emp = nil // 這是一個輔助指針 pre 在cur前面 //若是當前的EmpLink就是一個空鏈表 //爲空的話直接放到開頭 if cur == nil { this.Head = emp //完成 return } //若是不是一個空鏈表,給emp找到對應的位置並插入 //思路是 讓 cur 和 emp 比較,而後讓pre 保持在 cur 前面 for { if cur != nil { //比較 if cur.Id > emp.Id { //找到位置 break } //下面兩句確保pre在cur前面,且相鄰 pre = cur //保證同步 cur = cur.Next //移動,此種方法會致使最後一個判斷爲nil,對應上面的cur!=nil判斷 } else { break } } //退出時,咱們看下是否將emp添加到鏈表最後 pre.Next = emp //存入pre後面 emp.Next = cur //後面連上cur } //顯示鏈表的信息 func (this *EmpLink) ShowLink(no int) { if this.Head == nil { fmt.Printf("鏈表%d 爲空\n", no) return } //變量當前的鏈表,並顯示數據 cur := this.Head // 輔助的指針 for { if cur != nil { fmt.Printf("鏈表%d 僱員id=%d 名字=%s ->", no, cur.Id, cur.Name) cur = cur.Next } else { break } } fmt.Println() //換行處理 } //根據id查找對應的僱員,若是沒有就返回nil func (this *EmpLink) FindById(id int) *Emp { cur := this.Head for { //不是最後一個以後,且存在 if cur != nil && cur.Id == id { return cur } else if cur == nil { //結束 break } //進入下一個 cur = cur.Next } return nil } //定義hashtable ,含有一個鏈表數組 type HashTable struct { LinkArr [7]EmpLink } //給HashTable 編寫Insert 僱員的方法. func (this *HashTable) Insert(emp *Emp) { //使用散列函數,肯定將該僱員添加到哪一個鏈表 linkNo := this.HashFun(emp.Id) //使用對應的鏈表添加 this.LinkArr[linkNo].Insert(emp) // } //編寫方法,顯示hashtable的全部僱員 func (this *HashTable) ShowAll() { for i := 0; i < len(this.LinkArr); i++ { this.LinkArr[i].ShowLink(i) } } //編寫一個散列方法 func (this *HashTable) HashFun(id int) int { return id % 7 //獲得一個值,就是對於的鏈表的下標 } //編寫一個方法,完成查找 func (this *HashTable) FindById(id int) *Emp { //使用散列函數,肯定將該僱員應該在哪一個鏈表 linkNo := this.HashFun(id) return this.LinkArr[linkNo].FindById(id) } func main() { key := "" id := 0 name := "" var hashtable HashTable for { fmt.Println("===============僱員系統菜單============") fmt.Println("input 表示添加僱員") fmt.Println("show 表示顯示僱員") fmt.Println("find 表示查找僱員") fmt.Println("exit 表示退出系統") fmt.Println("請輸入你的選擇") fmt.Scanln(&key) switch key { case "input": fmt.Println("輸入僱員id") fmt.Scanln(&id) fmt.Println("輸入僱員name") fmt.Scanln(&name) emp := &Emp{ Id: id, Name: name, } hashtable.Insert(emp) case "show": hashtable.ShowAll() case "find": fmt.Println("請輸入id號:") fmt.Scanln(&id) emp := hashtable.FindById(id) if emp == nil { fmt.Printf("id=%d 的僱員不存在\n", id) } else { //編寫一個方法,顯示僱員信息 emp.ShowMe() } case "exit": os.Exit(0) default: fmt.Println("輸入錯誤") } } }
前,中,後遍歷
package main import "fmt" /* 二叉樹三種遍歷方式 */ type Hero struct { No int Name string Left *Hero Right *Hero } //前序遍歷【先輸出root結點,而後再輸出左子樹,而後右子樹】 func PreOrder(node *Hero) { if node != nil { fmt.Printf("no=%d name=%s\n", node.No, node.Name) PreOrder(node.Left) PreOrder(node.Right) } } //中序遍歷【先輸出root左子樹,再輸出root結點,最後輸出root的有子樹】 func InfixOrder(node *Hero) { if node != nil { InfixOrder(node.Left) fmt.Printf("no=%d name=%s\n", node.No, node.Name) InfixOrder(node.Right) } } //後序遍歷 func PostOrder(node *Hero) { if node != nil { PostOrder(node.Left) PostOrder(node.Right) fmt.Printf("no=%d name=%s\n", node.No, node.Name) } } func main() { //構建一個二叉樹 root := &Hero{ No: 1, Name: "宋江", } left1 := &Hero{ No: 2, Name: "吳用", } node10 := &Hero{ No: 10, Name: "李逵", } node12 := &Hero{ No: 12, Name: "楊雄", } left1.Left = node10 left1.Right = node12 right1 := &Hero{ No: 3, Name: "盧俊義", } root.Left = left1 root.Right = right1 right2 := &Hero{ No: 4, Name: "林沖", } right1.Right = right2 fmt.Println("前") PreOrder(root) fmt.Println("中") InfixOrder(root) fmt.Println("後") PostOrder(root) }
。。。