顺序表知识点总结

961 阅读4分钟

比如数组适合做随机读取,

链表适合做插入和删除

// 在 c/c++ 中, 数组的长度是类型的一部分
int arr[5] ; // 表示要给长度为 5 的 int 型的数组
  • 线性表的主要操作特点是: 在任意的位置插入和删除元素

  • 单链表的存储密度小于 1

  • 线性表在需要不断删除或者插入操作的情况下使用链表来实现

  • 线性表如果采用链式存储结构, 则要求内存中可用的存储单元的地址连续或不连续都可以

  • 链式存储结构所占空间分两部分, 一部分存放结点的值, 另一个部分保存表示结点间关系的指针

  • 数据在内存中表示时, 物理地址与逻辑地址相同并且是连续的, 称为顺序存储结构

  • 单链表中设置头节点的作用是什么? csdn回答挺好的, 总之就是为了操作简单和减少 bug

  • 在顺序表中插入和删除一个结点平均需要移动 n 个结点, 具体的移动次数取决于插入和删除的位置

  • 线性表的定位操作 ListFind(L,x) 的功能是: 在线性表中 L 查找是否存在数据元素 x, 如果存在返回线性表中的和 x 相等的第一个元素的需要 (序号从 0 开始), 如果不存在, 返回 -1

    package main
    import (
    	"fmt"
    )
    func ListFind(data[]int , x int ) int {
        for index, val:=range data {
            // 如果 当前的值和 x 相等, 直接返回当前的下标
            if val == x {
               return index
            }
        }
        // 如果没有找到, 直接返回 -1
        return -1 
    }
    
    func main() {
        data:= []int{1,2,3,4,5,6,7,8,8,9}
        x:= 8
        fmt.Println("index:",ListFind(data, x)) // example:7
    }
    
  • 设顺序表 L 中的数据元素有序递增, 编写一个算法, 将数据元素 x 插入到顺序表L 中的适当位置, 以保持该顺序表的有序性

    • 首先需要找到对应的插入位置
    • 如果对应的位置后面还有数据, 需要将对应位置下的所有数据整体向后移动一位
    • 在对应的位置插入元素 x
  • 编写算法实现顺序表的就地逆置

    • 使用头尾指针的法则逆序

      func reverse(data []int ) {
          i, j:= 0 , len(data) -1
          // 这里使用的是头尾指针的方法, 如果头指针和尾指针不相同,交换当前两个的数据元素
          for i!= j {
              data[i],data[j] = data[j],data[i]
              i++
              j--
          }
      }
      
  • 使用单链表实现删除链表中元素数据大于或等于 x 的数据 ListDeleteMore(L, x)

    • 这里的实现需要注意保存好上一个结点的指针, 如果当前的结点的值大于或者等于 x , 就把上一个结点的值指向当前结点的下一个结点, 如果没有自动垃圾回收的还需要释放当前结点
    package main
    
    import "fmt"
    
    type ListNode struct {
    	Val int
    	Next *ListNode
    }
    
    // 这里使用带有头节点的单链表实现
    func ListDeleteMore(head *ListNode, val int ) {
    	curr:=head
    
    	for curr.Next !=nil {
    		// 如果当前的结点不满足条件, 直接把当前的结点的指针域指向下一个结点的指针域
    		if curr.Next.Val >= val {
    			curr.Next = curr.Next.Next
    			continue
    		}
    		curr = curr.Next
    	}
    }
    
    func main() {
    	// 这里是构造一个链表
    	node:=&ListNode{Val:0,Next:&ListNode{Val:2,Next:&ListNode{Val:3,Next:&ListNode{Val:5,Next:&ListNode{Val:5,Next:&ListNode{Val:3,Next:&ListNode{Val:4}}}}}}}
    	ListDeleteMore(node,4)
    	for h:=node.Next; h!=nil ; h = h.Next {
    		fmt.Print(h.Val, " ")
    	}
    }
    
    
  • 超级经典的一个问题, 单链表的就地逆序

    package main
    
    import "fmt"
    
    type ListNode struct {
    	Val int
    	Next *ListNode
    }
    
    func Reverse(head *ListNode) {
    	curr:= head.Next
    	head.Next = nil
    	// 
    	for curr !=nil {
    		tmp:= curr
    		curr = curr.Next
    		// 这里是主要实现就是, 将当前的结点插入到 头节点的 next 域
    		tmp.Next = head.Next
    		head.Next = tmp
    	}
    }
    
    func main() {
    	node:=&ListNode{Val:0,Next:&ListNode{Val:1,Next:&ListNode{Val:2,Next:&ListNode{Val:3,Next:&ListNode{Val:4}}}}}
    	Reverse(node)
    	for h:=node.Next; h!=nil ; h = h.Next {
    		fmt.Print(h.Val , "  ")
    	}
    }
    
    
  • 设带头节点的单链表 L1 和 L2 中分别存放着两个数据元素的集合, 编写算法判断 L1 是否是集合 L2 的子集

    package main
    
    import "fmt"
    
    type ListNode struct {
    	Val int
    	Next *ListNode
    }
    
    func Contains(L1, L2 *ListNode) bool {
    	// 这里的实现使用了两重的循环
    	for h1:= L1.Next; h1!=nil ; h1 = h1.Next {
    		h2:= L2.Next
    		for ; h2!=nil ; h2 = h2.Next {
    			if h2.Val == h1.Val {
    				break
    			}
    		}
    		// 如果 h2 == nil 表示寻找是否等于 h1.Val 的值的时候, 在 L2 中没有找到
    		if h2 == nil {
    			return false
    		}
    	}
    	return true
    }
    func main() {
    	node:=&ListNode{Val:0,Next:&ListNode{Val:1,Next:&ListNode{Val:2,Next:&ListNode{Val:3,Next:&ListNode{Val:4,Next:&ListNode{Val:7}}}}}}
    	node2:=&ListNode{Val:0,Next:&ListNode{Val:1,Next:&ListNode{Val:2,Next:&ListNode{Val:3,Next:&ListNode{Val:4}}}}}
    	
    	fmt.Println("contains",Contains(node, node2))
    }
    
    

使用快慢指针

  1. 判断链表是否有环
  2. 找到链表的中点 (快指针每次走两步, 慢指针每次走一步, 快指针走完时, 慢指针刚好走到链表的中点)

跳表

在一个普通链表上建立多级索引用于加快搜索的顺序

:1         ->        5        ->        9
:1    ->   3    ->   5    ->   7   ->    9 
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10

github地址