数组与链表算法

数组

静态数组扩容

//定义一个结构体模拟数组
type Array struct {
	data []interface{} //存放数据
	size int //已使用的容量
}

func NewArray(capacity int) *Array{
	arr := &Array{}
	arr.data = make([]interface{},capacity)
	arr.size = 0
	return arr
}

//扩容:申请一个新空间,把遍历旧空间,把数据搬运过去
func (this *Array)resize(newCapacity int){
	newArr := make([]interface{},newCapacity)
	for i:=0; i<this.size; i++ {
		newArr[i] = this.data[i]
	}
	this.data = newArr
}
//增加一个新元素
func (this *Array)add(index int,element interface{}){
	if index < 0 || index > this.size {
		panic("error index")
	}
	//已用空间==容量 触发扩容
	if len(this.data) == this.size {
		this.resize(this.size*2)
	}
	//把index后的数据全部都后移一个位置
	for i:=this.size-1; i>=index; i-- {
		this.data[i+1] = this.data[i]
	}
	this.data[index] = element
	this.size++
}

链表

type Node struct {
	data interface{}
	next *Node
}

type List struct {
	head *Node
}

func NewNode(data interface{})*Node{
	return &Node{
		data:data,
		next:nil,
	}
}
/**
在指定节点后插入一个数据(要判断传入的节点是否为空)
 */
func (this *List)InsertAfer(node *Node,newValue interface{}) bool{
	if node == nil{
		return false
	}
	newNode := NewNode(newValue)
	newNode.next = node.next
	node.next = newNode
	return true
}

/**
插入一个节点(主要需要区分插入的是不是第一个节点)
 */
func (this *List)Insert(newValue interface{}) bool{
	newNode := NewNode(newValue)
	if this.head == nil{
		this.head = newNode
	}else{
		//循环找最后一个节点
		p := this.head
		for p.next != nil{
			p = p.next
		}
		//节点的指针变换(关键要防止丢指针)
		newNode.next = p.next
		p.next = newNode
	}
	return true
}

/*
删除一个节点
*/

func (this *List)DeleteNode(node *Node) bool{
	//链表为空或者传入的节点为空,返回false
	if this.head == nil || node == nil {
		return false
	}
	//特殊处理第一个节点
	if this.head == node {
		this.head = this.head.next
		return true
	}
	//以第二个节点为当前节点
	prev := this.head
	cur := prev.next
	//下一个节点非空 继续往下找
	//如果当前节点已经是目标节点才停止
	for cur.next != nil && node != cur {
		prev = cur
		cur = cur.next
	}
	prev.next = cur.next
	return true
}


/**
循环链表(关键是怎么判断到最后一个元素)
*/
type LoopList struct {
	head *Node
}

func (this *LoopList) add(value interface{}){
	newNode := NewNode(value)
       //特殊处理头节点
	if this.head == nil{
		this.head = newNode
		newNode.next = this.head
	}else{
		p := this.head
                //下一个元素是头元素,则该元素是就是要找的尾元素,结束循环
		for p.next != this.head {
			p = p.next
		}
		newNode.next = p.next
		p.next = newNode
	}
}
*/

/**
链表反转
前驱指针和后驱指针构成,每次循环把后驱指针指向到前驱指针
*/
func reverseList(head *ListNode) *ListNode {
   //前驱指针默认为空
   var pre *ListNode = nil
   //把头指针作为当前指针,只要当前指针不为空,表示有数据
   var cur = head
   for cur != nil {
       //临时保存后驱指针
       tmp := cur.Next
       //后驱指针指向 前一个数据
       cur.Next = pre
       //更新数据,下一个数据的cur就是当前的pre
       pre = cur
       cur = tmp
   }
   //最后一个cur是赋值给了pre,如果返回cur,指针是空的
    return pre
}

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */

 /**
两个有序链表合并成一个
 解题思路:
 1.用哨兵简化插入
 2.两个节点比较,把哨兵指向到数字小的节点,然后节点往后走一步,再重复比较。
 3.每次比较后哨兵都要往后走一步,指向到正确的位置
 4.走到最后哨兵是停留在最后一个位置,所以需要一开始就保存好哨兵的头
 */
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
    //哨兵节点,不存数据,为了插入的时候更方便
    preHead := &ListNode{}
    //把头节点暂存
    result := preHead
    //判断哪个节点的数据小,就把哨兵指向该节点,同时该节点偏移到下一个
    for l1 != nil && l2 != nil {
        if l1.Val < l2.Val{
            preHead.Next = l1
            l1 = l1.Next
        }else{
            preHead.Next = l2
            l2 = l2.Next
        }
        //哨兵节点偏移到下一个
        preHead = preHead.Next
    }
    //l1 或者 l2 有剩余数据,直接用哨兵指向他就可以了
    if l1 != nil {
        preHead.Next = l1
    }
    if l2 != nil{
        preHead.Next = l2
    }
    //哨兵的后一个节点
    return result.Next
}


/**
 * 需要考虑奇偶数的情况,奇数fast.Next生效,偶数fast生效
 * 快指针可以前进的条件是:当前快指针和当前快指针的下一个结点都非空。
*/
func middleNode(head *ListNode) *ListNode {
   slow := head
   fast := head

   //奇数: 1 
   //第一轮: fast.Next != nil 生效,循环结束
   //偶数: 1 -> 2
   //第一轮:slow == 2 ,fast != nil 生效,循环结束 
   for fast != nil && fast.Next != nil {
       slow = slow.Next
       fast = fast.Next.Next
   }
   return slow
}
posted @ 2020-06-10 22:51  defmain  阅读(155)  评论(0编辑  收藏  举报