• 练习Golang链表使用多线程


    非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

    如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

    package linkNode
    
    import (
    	"container/list"
    	"runtime"
    )
    
    //初始化链表
    func InitList(arr ...int) *list.List {
    	l := list.New()
    	for _, v := range arr {
    		l.PushBack(v)
    	}
    	return l
    }
    
    //go协程并行读取另外一个链表
    func goReadList(temp *list.List, c chan int, len int) {
    	for e := temp.Back(); e != nil; e = e.Prev() {
    		c <- e.Value.(int) //读取的数值放入通道
    	}
    	for i := 0; i < len; i++ {
    		c <- -1 //虚拟对齐,放入标志符
    	}
    }
    
    //主要函数
    func ListAdd(l1, l2 *list.List) *list.List {
    	var c = make(chan int) //创建一个通道传递list.value
    	var addList = list.New()
    	var result = 0 //临时储存结点相加的值
    	var carry = 0  //进位标识符
    	var lengthPoor = 0
    	if l1.Len() < l2.Len() {
    		l1, l2 = l2, l1 // 让协程内的链长度始终小于或等于主线程链长度
    		lengthPoor = l1.Len() - l2.Len()
    	} else {
    		lengthPoor = l1.Len() - l2.Len() //虚拟对齐,使得go协程和主线程保持通信
    	}
    	go goReadList(l2, c, lengthPoor) // 传入参数为 短链 通道 需要多次循环次数
    	for e := l1.Back(); e != nil; e = e.Prev() { // 从链尾遍历
    		b := <-c
    		if b == -1 { //标识符,此时说明短链已经遍历完成,长链只需要加进位的值
    			result = e.Value.(int) + carry //断言
    			carry = 0                      //进位符使用后清零
    			if result > 9 {
    				result = result % 10 // 取余数放入新链表
    				addList.PushFront(result)
    				carry = 1 //有进位时,进位符=1
    			} else {
    				addList.PushFront(result) //放入链尾
    			}
    		} else {
    			result = e.Value.(int) + b + carry //同上加上通道的值在判断
    			carry = 0
    			if result > 9 {
    				result = result % 10
    				addList.PushFront(result)
    				carry = 1
    			} else {
    				addList.PushFront(result)
    			}
    		}
    	}
    	runtime.Gosched() //挂载go协程
    	if carry == 1 { //最后判断有没有进位,有进位链首添加1
    		addList.PushFront(1)
    	}
    	return addList
    }
    

     测试函数

    package linkNode
    
    import (
    	"fmt"
    	"testing"
    )
    
    func TestListAdd(t *testing.T) {
    	l1 := InitList(9, 9, 9, 9, 9, 9, 9) //9, 2, 3, 4, 5, 6, 7
    	l2 := InitList(9, 9, 9, 9, 9, 9, 9)
    	l3 := ListAdd(l1, l2)
    	for e := l3.Front(); e != nil; e = e.Next() {
    		fmt.Print(e.Value, "  ")
    	}
    }
    
  • 相关阅读:
    sql server 2005中模仿merge的使用方法
    c#中怎么控制session失效时间
    MasterPage,Page 2者之间事件的执行顺序
    ToolStripComboBox的DataSource和DataTable
    C#综合揭秘——细说多线程(上)(转载)
    SQL Server 2008 MERGE
    SQL output语句的用法
    SQL中使用update inner join和delete inner join
    C#综合揭秘——细说事务(转载)
    SQLMETAL :Linq对象生成
  • 原文地址:https://www.cnblogs.com/Addoil/p/10858659.html
Copyright © 2020-2023  润新知