code: func (nc *Controller) classifyNodes(allNodes []*v1.Node) (added, deleted, newZoneRepresentatives []*v1.Node) {
  	for i := range allNodes {
  		if _, has := nc.knownNodeSet[allNodes[i].Name]; !has {
  			added = append(added, allNodes[i])
  		} else {
  			// Currently, we only consider new zone as updated.
  			zone := utilnode.GetZoneKey(allNodes[i])
  			if _, found := nc.zoneStates[zone]; !found {
  				newZoneRepresentatives = append(newZoneRepresentatives, allNodes[i])
  			}
  		}
  	}
  
  	// If there's a difference between lengths of known Nodes and observed nodes
  	// we must have removed some Node.
  	if len(nc.knownNodeSet)+len(added) != len(allNodes) {
  		knowSetCopy := map[string]*v1.Node{}
  		for k, v := range nc.knownNodeSet {
  			knowSetCopy[k] = v
  		}
  		for i := range allNodes {
  			delete(knowSetCopy, allNodes[i].Name)
  		}
  		for i := range knowSetCopy {
  			deleted = append(deleted, knowSetCopy[i])
  		}
  	}
  	return
  }
docs: // classifyNodes classifies the allNodes to three categories:
  //   1. added: the nodes that in 'allNodes', but not in 'knownNodeSet'
  //   2. deleted: the nodes that in 'knownNodeSet', but not in 'allNodes'
  //   3. newZoneRepresentatives: the nodes that in both 'knownNodeSet' and 'allNodes', but no zone states